URL
https://opencores.org/ocsvn/jtag_stapl_player/jtag_stapl_player/trunk
Subversion Repositories jtag_stapl_player
[/] [jtag_stapl_player/] [trunk/] [jamarray.c] - Rev 2
Compare with Previous | Blame | View Log
/****************************************************************************/ /* */ /* Module: jamarray.c */ /* */ /* Copyright (C) Altera Corporation 1997 */ /* */ /* Description: Contains array management functions, including */ /* functions for reading array initialization data in */ /* compressed formats. */ /* */ /* Revisions: 1.1 added support for dynamic memory allocation */ /* */ /****************************************************************************/ /****************************************************************************/ /* */ /* Actel version 1.1 May 2003 */ /* */ /****************************************************************************/ #include "jamexprt.h" #include "jamdefs.h" #include "jamexec.h" #include "jamexp.h" #include "jamsym.h" #include "jamstack.h" #include "jamheap.h" #include "jamutil.h" #include "jamcomp.h" #include "jamarray.h" /* * Table of names of Boolean data representation schemes */ struct JAMS_BOOL_REP_MAP { JAME_BOOLEAN_REP rep; char string[4]; } jam_bool_rep_table[] = { { JAM_BOOL_BINARY, "BIN" }, { JAM_BOOL_HEX, "HEX" }, { JAM_BOOL_RUN_LENGTH, "RLC" }, { JAM_BOOL_COMPRESSED, "ACA" }, }; #define JAMC_BOOL_REP_COUNT \ ((int) (sizeof(jam_bool_rep_table) / sizeof(jam_bool_rep_table[0]))) #define JAMC_DICTIONARY_SIZE 4096 typedef enum { JAM_CONSTANT_ZEROS, JAM_CONSTANT_ONES, JAM_RANDOM } JAME_RLC_BLOCK_TYPE; JAM_RETURN_TYPE jam_reverse_boolean_array_bin ( JAMS_HEAP_RECORD *heap_record ) { long *heap_data = &heap_record->data[0]; long dimension = heap_record->dimension; int a, b; long i, j; for (i = 0; i < dimension / 2; ++i) { j = (dimension - 1) - i; a = (heap_data[i >> 5] & (1L << (i & 0x1f))) ? 1 : 0; b = (heap_data[j >> 5] & (1L << (j & 0x1f))) ? 1 : 0; if (a) { heap_data[j >> 5] |= (1L << (j & 0x1f)); } else { heap_data[j >> 5] &= ~(1L << (j & 0x1f)); } if (b) { heap_data[i >> 5] |= (1L << (i & 0x1f)); } else { heap_data[i >> 5] &= ~(1L << (i & 0x1f)); } } return (JAMC_SUCCESS); } JAM_RETURN_TYPE jam_reverse_boolean_array_hex ( JAMS_HEAP_RECORD *heap_record ) { long *heap_data = &heap_record->data[0]; long nibbles = (heap_record->dimension + 3) / 4; long a, b, i, j; for (i = 0; i < nibbles / 2; ++i) { j = (nibbles - 1) - i; a = (heap_data[i >> 3] >> ((i & 7) << 2)) & 0x0f; b = (heap_data[j >> 3] >> ((j & 7) << 2)) & 0x0f; heap_data[j >> 3] &= ~(0x0fL << ((j & 7) << 2)); heap_data[j >> 3] |= (a << ((j & 7) << 2)); heap_data[i >> 3] &= ~(0x0fL << ((i & 7) << 2)); heap_data[i >> 3] |= (b << ((i & 7) << 2)); } return (JAMC_SUCCESS); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_extract_bool_comma_sep ( JAMS_HEAP_RECORD *heap_record, char *statement_buffer ) /* */ /* Description: Extracts Boolean array data from statement buffer. */ /* Works on data in comma separated representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int expr_begin = 0; int expr_end = 0; char save_ch = 0; long address = 0L; long value = 0L; long dimension = heap_record->dimension; JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; for (address = 0L; (status == JAMC_SUCCESS) && (address < dimension); ++address) { status = JAMC_SYNTAX_ERROR; while ((jam_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_COMMA_CHAR) && (statement_buffer[index] != JAMC_SEMICOLON_CHAR) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over the expression */ } 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 = jam_evaluate_expression( &statement_buffer[expr_begin], &value, &expr_type); statement_buffer[expr_end] = save_ch; } 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 (value == 0L) { /* clear a single bit */ heap_data[address >> 5] &= (~(unsigned long)(1L << (address & 0x1f))); } else if (value == 1L) { /* set a single bit */ heap_data[address >> 5] |= (1L << (address & 0x1f)); } else { status = JAMC_SYNTAX_ERROR; } if ((address < dimension) && (statement_buffer[index] == JAMC_COMMA_CHAR)) { ++index; } } } if (status == JAMC_SUCCESS) { while ((jam_isspace(statement_buffer[index])) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over white space */ } if (statement_buffer[index] != JAMC_SEMICOLON_CHAR) { status = JAMC_SYNTAX_ERROR; } } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_extract_bool_binary ( JAMS_HEAP_RECORD *heap_record, char *statement_buffer ) /* */ /* Description: Extracts Boolean array data from statement buffer. */ /* Works on data in binary (001100100101) representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; long address = 0L; long dimension = heap_record->dimension; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; for (address = 0L; (status == JAMC_SUCCESS) && (address < dimension); ++address) { while ((jam_isspace(statement_buffer[index])) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over white space */ } if (statement_buffer[index] == '0') { /* clear a single bit */ heap_data[address >> 5] &= (~(unsigned long)(1L << (address & 0x1f))); } else if (statement_buffer[index] == '1') { /* set a single bit */ heap_data[address >> 5] |= (1L << (address & 0x1f)); } else { status = JAMC_SYNTAX_ERROR; } ++index; } if (status == JAMC_SUCCESS) { while ((jam_isspace(statement_buffer[index])) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over white space */ } if (statement_buffer[index] != JAMC_SEMICOLON_CHAR) { status = JAMC_SYNTAX_ERROR; } } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_extract_bool_hex ( JAMS_HEAP_RECORD *heap_record, char *statement_buffer ) /* */ /* Description: Extracts Boolean array data from statement buffer. */ /* Works on data in hexadecimal (3BA97C0F) representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int ch = 0; long data = 0L; long nibble = 0L; long nibbles = 0L; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; /* compute number of hex digits expected */ nibbles = (heap_record->dimension >> 2) + ((heap_record->dimension & 3) ? 1 : 0); for (nibble = 0L; (status == JAMC_SUCCESS) && (nibble < nibbles); ++nibble) { while ((jam_isspace(statement_buffer[index])) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over white space */ } ch = (int) statement_buffer[index]; if ((ch >= 'A') && (ch <= 'F')) { data = (long) (ch + 10 - 'A'); } else if ((ch >= 'a') && (ch <= 'f')) { data = (long) (ch + 10 - 'a'); } else if ((ch >= '0') && (ch <= '9')) { data = (long) (ch - '0'); } else { status = JAMC_SYNTAX_ERROR; } if (status == JAMC_SUCCESS) { /* modify four bits of data in the array */ heap_data[nibble >> 3] = (heap_data[nibble >> 3] & (~(unsigned long) (15L << ((nibble & 7) << 2)))) | (data << ((nibble & 7) << 2)); } ++index; } if (status == JAMC_SUCCESS) { while ((jam_isspace(statement_buffer[index])) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over white space */ } if (statement_buffer[index] != JAMC_SEMICOLON_CHAR) { status = JAMC_SYNTAX_ERROR; } } return (status); } /****************************************************************************/ /* */ int jam_6bit_char(int ch) /* */ /* Description: Extracts numeric value from ASCII character code, */ /* based on character mapping defined in JAM language */ /* specification. Numeric value is in range 0 to 63. */ /* Used for RLC and ACA data representations. */ /* */ /* Returns: Integer value in range 0 to 63, or -1 for error. */ /* */ /****************************************************************************/ { int result = 0; if ((ch >= '0') && (ch <= '9')) result = (ch - '0'); else if ((ch >= 'A') && (ch <= 'Z')) result = (ch + 10 - 'A'); else if ((ch >= 'a') && (ch <= 'z')) result = (ch + 36 - 'a'); else if (ch == '_') result = 62; else if (ch == '@') result = 63; else result = -1; /* illegal character */ return (result); } /****************************************************************************/ /* */ BOOL jam_rlc_key_char ( int ch, JAME_RLC_BLOCK_TYPE *block_type, int *count_size ) /* */ /* Description: Decodes RLC block ID character. Returns block type */ /* and count size (number of count characters in the */ /* block) by reference. */ /* */ /* Returns: TRUE for success, FALSE if illegal block ID character */ /* */ /****************************************************************************/ { BOOL status = TRUE; if ((ch >= 'A') && (ch <= 'E')) { *block_type = JAM_CONSTANT_ZEROS; *count_size = (ch + 1 - 'A'); } else if ((ch >= 'I') && (ch <= 'M')) { *block_type = JAM_CONSTANT_ONES; *count_size = (ch + 1 - 'I'); } else if ((ch >= 'Q') && (ch <= 'U')) { *block_type = JAM_RANDOM; *count_size = (ch + 1 - 'Q'); } else { status = FALSE; } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_extract_bool_run_length ( JAMS_HEAP_RECORD *heap_record, char *statement_buffer ) /* */ /* Description: Extracts Boolean array data from statement buffer. */ /* Works on data encoded using RLC (run-length compressed) */ /* representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int index2 = 0; int count_index = 0; int count_size = 0; int value = 0; long bit = 0L; long count = 0L; long address = 0L; long dimension = heap_record->dimension; JAME_RLC_BLOCK_TYPE block_type = JAM_CONSTANT_ZEROS; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; /* remove all white space */ while (statement_buffer[index] != JAMC_NULL_CHAR) { if (!jam_isspace(statement_buffer[index])) { statement_buffer[index2] = statement_buffer[index]; ++index2; } ++index; } statement_buffer[index2] = JAMC_NULL_CHAR; index = 0; while ((status == JAMC_SUCCESS) && (address < dimension)) { if (jam_rlc_key_char(statement_buffer[index], &block_type, &count_size)) { ++index; count = 0L; for (count_index = 0; count_index < count_size; ++count_index) { count <<= 6; value = jam_6bit_char(statement_buffer[index]); if (value == -1) { status = JAMC_SYNTAX_ERROR; } else { count |= value; } ++index; } if (status == JAMC_SUCCESS) { switch (block_type) { case JAM_CONSTANT_ZEROS: for (bit = 0; bit < count; bit++) { /* add zeros to array */ heap_data[address >> 5] &= ~(unsigned long) (1L << (address & 0x1f)); ++address; } break; case JAM_CONSTANT_ONES: for (bit = 0; bit < count; bit++) { /* add ones to array */ heap_data[address >> 5] |= (1L << (address & 0x1f)); ++address; } break; case JAM_RANDOM: for (bit = 0; bit < count; bit++) { /* add random data to array */ value = jam_6bit_char(statement_buffer[index + (bit / 6)]); if (value == -1) { status = JAMC_SYNTAX_ERROR; } else if (value & (1 << (bit % 6))) { heap_data[address >> 5] |= (1L << (address & 0x1f)); } else { heap_data[address >> 5] &= ~(unsigned long) (1L << (address & 0x1f)); } ++address; } index = index + (int)((count / 6) + ((count % 6) ? 1 : 0)); break; default: status = JAMC_SYNTAX_ERROR; break; } } } else { /* unrecognized key character */ status = JAMC_SYNTAX_ERROR; } } if ((status == JAMC_SUCCESS) && (statement_buffer[index] != JAMC_SEMICOLON_CHAR)) { status = JAMC_SYNTAX_ERROR; } if ((status == JAMC_SUCCESS) && (address != dimension)) { status = JAMC_SYNTAX_ERROR; } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_extract_bool_compressed ( JAMS_HEAP_RECORD *heap_record, char *statement_buffer ) /* */ /* Description: Extracts Boolean array data from statement buffer. */ /* Works on data encoded using ACA representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int bit = 0; int word = 0; int value = 0; int index = 0; int index2 = 0; long uncompressed_length = 0L; char *ch_data = NULL; long out_size = 0L; long address = 0L; long *heap_data = &heap_record->data[0]; JAM_RETURN_TYPE status = JAMC_SUCCESS; /* remove all white space */ while (statement_buffer[index] != JAMC_NULL_CHAR) { if (!jam_isspace(statement_buffer[index])) { 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) && (statement_buffer[index] != JAMC_NULL_CHAR) && (statement_buffer[index] != JAMC_SEMICOLON_CHAR)) { value = 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_SEMICOLON_CHAR)) { status = JAMC_SYNTAX_ERROR; } /* * We need two memory buffers: * * in (length of compressed bitstream) * out (length of uncompressed bitstream) * * The statement buffer is re-used for the "in" buffer. The "out" * buffer is inside the heap record. */ if (status == JAMC_SUCCESS) { /* * Uncompress the data */ out_size = (heap_record->dimension >> 3) + ((heap_record->dimension & 7) ? 1 : 0); uncompressed_length = jam_uncompress( statement_buffer, (address >> 3) + ((address & 7) ? 1 : 0), (char *)heap_data, out_size, jam_version); if (uncompressed_length != out_size) { status = JAMC_SYNTAX_ERROR; } else { /* convert data from bytes into 32-bit words */ out_size = (heap_record->dimension >> 5) + ((heap_record->dimension & 0x1f) ? 1 : 0); ch_data = (char *)heap_data; for (word = 0; word < out_size; ++word) { heap_data[word] = ((((long) ch_data[(word * 4) + 3]) & 0xff) << 24L) | ((((long) ch_data[(word * 4) + 2]) & 0xff) << 16L) | ((((long) ch_data[(word * 4) + 1]) & 0xff) << 8L) | (((long) ch_data[word * 4]) & 0xff); } } } return (status); } /****************************************************************************/ /* */ int jam_get_real_char(void) /* */ /* Description: Gets next character from input stream, eliminating */ /* white space and comments. */ /* */ /* Returns: Character code, or EOF if no characters available */ /* */ /****************************************************************************/ { int ch = 0; BOOL comment = FALSE; BOOL found = FALSE; JAM_RETURN_TYPE status = JAMC_SUCCESS; while ((status == JAMC_SUCCESS) && (!found)) { ch = jam_getc(); if ((!comment) && (ch == JAMC_COMMENT_CHAR)) { /* beginning of comment */ comment = TRUE; } if (!comment) { if (!jam_isspace((char) ch)) { found = TRUE; } } if (ch == EOF) { /* end of file */ status = JAMC_UNEXPECTED_END; } if (comment && ((ch == JAMC_NEWLINE_CHAR) || (ch == JAMC_RETURN_CHAR))) { /* end of comment */ comment = FALSE; } } return (ch); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_read_bool_comma_sep ( JAMS_HEAP_RECORD *heap_record ) /* */ /* Description: Reads Boolean array data directly from input stream. */ /* Works on data in comma separated representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int ch = 0; long address = 0L; long value = 0L; long dimension = heap_record->dimension; char expr_buffer[JAMC_MAX_STATEMENT_LENGTH + 1]; JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; if (jam_seek(heap_record->position) != 0) { status = JAMC_IO_ERROR; } while ((status == JAMC_SUCCESS) && (address < dimension)) { ch = jam_get_real_char(); if (((ch == JAMC_COMMA_CHAR) && (address < (dimension - 1))) || ((ch == JAMC_SEMICOLON_CHAR) && (address == (dimension - 1)))) { expr_buffer[index] = JAMC_NULL_CHAR; index = 0; status = jam_evaluate_expression( expr_buffer, &value, &expr_type); 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 (value == 0L) { /* clear a single bit */ heap_data[address >> 5] &= (~(unsigned long)(1L << (address & 0x1f))); ++address; } else if (value == 1L) { /* set a single bit */ heap_data[address >> 5] |= (1L << (address & 0x1f)); ++address; } else { status = JAMC_TYPE_MISMATCH; } } } else { expr_buffer[index] = (char) ch; if (index < JAMC_MAX_STATEMENT_LENGTH) { ++index; } else { /* expression was too long */ status = JAMC_SYNTAX_ERROR; } } if (ch == EOF) { /* end of file */ status = JAMC_UNEXPECTED_END; } } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_read_bool_binary ( JAMS_HEAP_RECORD *heap_record ) /* */ /* Description: Reads Boolean array data directly from input stream. */ /* Works on data in binary (001100100101) representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int ch = 0; long address = 0L; long dimension = heap_record->dimension; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; if (jam_seek(heap_record->position) != 0) { status = JAMC_IO_ERROR; } while ((status == JAMC_SUCCESS) && (address < dimension)) { ch = jam_get_real_char(); if (ch == '0') { /* clear a single bit */ heap_data[address >> 5] &= (~(unsigned long)(1L << (address & 0x1f))); ++address; } else if (ch == '1') { /* set a single bit */ heap_data[address >> 5] |= (1L << (address & 0x1f)); ++address; } else { status = JAMC_SYNTAX_ERROR; } if (ch == EOF) { /* end of file */ status = JAMC_UNEXPECTED_END; } } if (status == JAMC_SUCCESS) { ch = jam_get_real_char(); if (ch != JAMC_SEMICOLON_CHAR) { status = JAMC_SYNTAX_ERROR; } } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_read_bool_hex ( JAMS_HEAP_RECORD *heap_record ) /* */ /* Description: Reads Boolean array data directly from input stream. */ /* Works on data in hexadecimal (3BA97C0F) representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int ch = 0; long data = 0L; long nibble = 0L; long nibbles = 0L; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; /* compute number of hex digits expected */ nibbles = (heap_record->dimension >> 2) + ((heap_record->dimension & 3) ? 1 : 0); if (jam_seek(heap_record->position) != 0) { status = JAMC_IO_ERROR; } while ((status == JAMC_SUCCESS) && (nibble < nibbles)) { ch = jam_get_real_char(); if ((ch >= 'A') && (ch <= 'F')) { data = (long) (ch + 10 - 'A'); } else if ((ch >= 'a') && (ch <= 'f')) { data = (long) (ch + 10 - 'a'); } else if ((ch >= '0') && (ch <= '9')) { data = (long) (ch - '0'); } else { status = JAMC_SYNTAX_ERROR; } if (status == JAMC_SUCCESS) { /* modify four bits of data in the array */ heap_data[nibble >> 3] = (heap_data[nibble >> 3] & (~(unsigned long) (15L << ((nibble & 7) << 2)))) | (data << ((nibble & 7) << 2)); ++nibble; } if (ch == EOF) { /* end of file */ status = JAMC_UNEXPECTED_END; } } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_read_bool_run_length ( JAMS_HEAP_RECORD *heap_record ) /* */ /* Description: Reads Boolean array data directly from input stream. */ /* Works on data encoded using RLC (run-length compressed) */ /* representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int ch = 0; int count_index = 0; int count_size = 0; int value = 0; long bit = 0L; long count = 0L; long address = 0L; long dimension = heap_record->dimension; JAME_RLC_BLOCK_TYPE block_type = JAM_CONSTANT_ZEROS; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; if (jam_seek(heap_record->position) != 0) { status = JAMC_IO_ERROR; } while ((status == JAMC_SUCCESS) && (address < dimension)) { if (jam_rlc_key_char(jam_get_real_char(), &block_type, &count_size)) { count = 0L; for (count_index = 0; count_index < count_size; ++count_index) { count <<= 6; value = jam_6bit_char(jam_get_real_char()); if (value == -1) { status = JAMC_SYNTAX_ERROR; } else { count += (long) value; } } switch (block_type) { case JAM_CONSTANT_ZEROS: for (bit = 0; bit < count; bit++) { /* add zeros to array */ heap_data[address >> 5] &= ~(unsigned long) (1L << (address & 0x1f)); ++address; } break; case JAM_CONSTANT_ONES: for (bit = 0; bit < count; bit++) { /* add ones to array */ heap_data[address >> 5] |= (1L << (address & 0x1f)); ++address; } break; case JAM_RANDOM: for (bit = 0; bit < count; bit++) { /* add random data to array */ if ((bit % 6) == 0) { value = jam_6bit_char(jam_get_real_char()); if (value == -1) { status = JAMC_SYNTAX_ERROR; } } if (value & (1 << ((int)(bit % 6)))) { heap_data[address >> 5] |= (1L << (address & 0x1f)); } else { heap_data[address >> 5] &= ~(unsigned long) (1L << (address & 0x1f)); } ++address; } break; default: status = JAMC_SYNTAX_ERROR; break; } } else { /* unrecognized key character */ status = JAMC_SYNTAX_ERROR; } } ch = jam_get_real_char(); if (ch == EOF) { status = JAMC_UNEXPECTED_END; } if ((status == JAMC_SUCCESS) && ((ch != JAMC_SEMICOLON_CHAR) || (address != dimension))) { status = JAMC_SYNTAX_ERROR; } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_read_bool_compressed ( JAMS_HEAP_RECORD *heap_record ) /* */ /* Description: Reads Boolean array data directly from input stream. */ /* Works on data encoded using ACA representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int ch = 0; int bit = 0; int word = 0; int value = 0; long uncompressed_length = 0L; char *in = NULL; char *ch_data = NULL; long in_size = 0L; long out_size = 0L; long address = 0L; BOOL done = FALSE; long *heap_data = &heap_record->data[0]; JAM_RETURN_TYPE status = JAMC_SUCCESS; if (jam_seek(heap_record->position) != 0) { status = JAMC_IO_ERROR; } /* * We need two memory buffers: * * in (length of compressed bitstream) * out (length of uncompressed bitstream) * * The "out" buffer is inside the heap record. The "in" buffer * resides in temporary storage above the last heap record. */ out_size = (heap_record->dimension >> 3) + ((heap_record->dimension & 7) ? 1 : 0); in = jam_get_temp_workspace(out_size + (out_size / 10) + 100); if (in == NULL) { status = JAMC_OUT_OF_MEMORY; } while ((status == JAMC_SUCCESS) && (!done)) { ch = jam_get_real_char(); if (ch == JAMC_SEMICOLON_CHAR) { done = TRUE; } else { value = jam_6bit_char(ch); if (value == -1) { status = JAMC_SYNTAX_ERROR; } else { for (bit = 0; bit < 6; ++bit) { if (value & (1 << (bit % 6))) { in[address >> 3] |= (1L << (address & 7)); } else { in[address >> 3] &= ~(unsigned int) (1 << (address & 7)); } ++address; } } } } if (done && (status == JAMC_SUCCESS)) { /* * Uncompress the data */ in_size = (address >> 3) + ((address & 7) ? 1 : 0); uncompressed_length = jam_uncompress( in, in_size, (char *)heap_data, out_size, jam_version); if (uncompressed_length != out_size) { status = JAMC_SYNTAX_ERROR; } else { /* convert data from bytes into 32-bit words */ out_size = (heap_record->dimension >> 5) + ((heap_record->dimension & 0x1f) ? 1 : 0); ch_data = (char *)heap_data; for (word = 0; word < out_size; ++word) { heap_data[word] = ((((long) ch_data[(word * 4) + 3]) & 0xff) << 24L) | ((((long) ch_data[(word * 4) + 2]) & 0xff) << 16L) | ((((long) ch_data[(word * 4) + 1]) & 0xff) << 8L) | (((long) ch_data[word * 4]) & 0xff); } } } if (in != NULL) jam_free_temp_workspace(in); return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_read_boolean_array_data ( JAMS_HEAP_RECORD *heap_record, char *statement_buffer ) /* */ /* Description: Reads Boolean array initialization data. If it is all */ /* present in the statement buffer, then it is extracted */ /* from the buffer. If the array initialization data did */ /* not fit into the statement buffer, it is read directly */ /* from the input stream. Five formats of Boolean array */ /* initialization data are supported: comma-separated */ /* values (the default), and BIN, HEX, RLC, and ACA. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int ch = 0; int rep = 0; int length = 0; int data_offset = 0; long position = 0L; long data_position = 0L; BOOL done = FALSE; BOOL comment = FALSE; BOOL found_equal = FALSE; BOOL found_space = FALSE; BOOL found_keyword = FALSE; BOOL data_complete = FALSE; JAME_BOOLEAN_REP representation = JAM_ILLEGAL_REP; JAM_RETURN_TYPE status = JAMC_SUCCESS; while ((jam_isspace(statement_buffer[index])) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over white space */ } /* * Figure out which data representation scheme is used */ if (jam_version == 2) { if (statement_buffer[index] == JAMC_POUND_CHAR) { representation = JAM_BOOL_BINARY; data_offset = index + 1; } else if (statement_buffer[index] == JAMC_DOLLAR_CHAR) { representation = JAM_BOOL_HEX; data_offset = index + 1; } else if (statement_buffer[index] == JAMC_AT_CHAR) { representation = JAM_BOOL_COMPRESSED; data_offset = index + 1; } } else if (jam_isdigit(statement_buffer[index])) { /* * First character is digit -- assume comma separated list */ representation = JAM_BOOL_COMMA_SEP; data_offset = index; } else if (jam_isalpha(statement_buffer[index])) { /* * Get keyword to indicate representation scheme */ for (rep = 0; (rep < JAMC_BOOL_REP_COUNT) && (representation == JAM_ILLEGAL_REP); ++rep) { length = jam_strlen(jam_bool_rep_table[rep].string); if ((jam_strnicmp(&statement_buffer[index], jam_bool_rep_table[rep].string, length) == 0) && jam_isspace(statement_buffer[index + length])) { representation = jam_bool_rep_table[rep].rep; } } data_offset = index + length; } if (representation == JAM_ILLEGAL_REP) { status = JAMC_SYNTAX_ERROR; } else { heap_record->rep = representation; } if ((status == JAMC_SUCCESS) && (jam_version == 2)) { if ((representation != JAM_BOOL_BINARY) && (representation != JAM_BOOL_HEX) && (representation != JAM_BOOL_COMPRESSED)) { /* only these three formats are supported in Jam 2.0 */ status = JAMC_SYNTAX_ERROR; } } /* * See if all the initialization data is present in the statement buffer */ if ((status == JAMC_SUCCESS) && !heap_record->cached) { while ((statement_buffer[index] != JAMC_NULL_CHAR) && (statement_buffer[index] != JAMC_SEMICOLON_CHAR) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* look for semicolon */ } if (statement_buffer[index] == JAMC_SEMICOLON_CHAR) { data_complete = TRUE; } } /* * If data is not all present in the statement buffer, or if data * will be cached, find the position of the data in the input file */ if ((status == JAMC_SUCCESS) && ((!data_complete) || heap_record->cached)) { /* * Get position offset of initialization data */ if (jam_seek(jam_current_statement_position) == 0) { position = jam_current_statement_position; } else status = JAMC_IO_ERROR; while ((status == JAMC_SUCCESS) && !done) { ch = jam_getc(); if ((!comment) && (ch == JAMC_COMMENT_CHAR)) { /* beginning of comment */ comment = TRUE; } if ((!comment) && (!found_equal) && (ch == JAMC_EQUAL_CHAR)) { /* found the equal sign */ found_equal = TRUE; } if ((!comment) && found_equal && (!found_space) && jam_isspace((char)ch)) { /* found the space after the equal sign */ found_space = TRUE; } if ((!comment) && found_equal && found_space) { if (representation == JAM_BOOL_COMMA_SEP) { if (jam_isdigit((char)ch)) { /* found the first character of the data area */ done = TRUE; data_position = position; } } else /* other representations */ { if ((jam_version == 2) && (!found_keyword) && ((ch == JAMC_POUND_CHAR) || (ch == JAMC_DOLLAR_CHAR) || (ch == JAMC_AT_CHAR))) { found_keyword = TRUE; done = TRUE; data_position = position + 1; } if ((jam_version != 2) && (!found_keyword) && (jam_isalpha((char)ch))) { /* found the first char of the representation keyword */ found_keyword = TRUE; } if ((jam_version != 2) && found_keyword && (jam_isspace((char)ch))) { /* found the first character of the data area */ done = TRUE; data_position = position; } } } if ((!comment) && (ch == JAMC_SEMICOLON_CHAR)) { /* end of statement */ done = TRUE; } 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; } ++position; /* position of next character to be read */ } if (status == JAMC_SUCCESS) { heap_record->position = data_position; } /* * If data will not be cached, read it in from the file now. */ if ((status == JAMC_SUCCESS) && !heap_record->cached) { /* * Data is present, and will not be cached. Read it in. */ switch (representation) { case JAM_BOOL_COMMA_SEP: status = jam_read_bool_comma_sep(heap_record); break; case JAM_BOOL_BINARY: status = jam_read_bool_binary(heap_record); break; case JAM_BOOL_HEX: status = jam_read_bool_hex(heap_record); break; case JAM_BOOL_RUN_LENGTH: status = jam_read_bool_run_length(heap_record); break; case JAM_BOOL_COMPRESSED: status = jam_read_bool_compressed(heap_record); break; default: status = JAMC_INTERNAL_ERROR; } } /* * Restore file pointer to position of next statement */ if (status == JAMC_SUCCESS) { if (jam_seek(jam_next_statement_position) == 0) { jam_current_file_position = jam_next_statement_position; } else status = JAMC_IO_ERROR; } } if ((status == JAMC_SUCCESS) && data_complete && !heap_record->cached) { /* * Data is present, and will not be cached. Extract it from buffer. */ switch (representation) { case JAM_BOOL_COMMA_SEP: status = jam_extract_bool_comma_sep( heap_record, &statement_buffer[data_offset]); break; case JAM_BOOL_BINARY: status = jam_extract_bool_binary( heap_record, &statement_buffer[data_offset]); break; case JAM_BOOL_HEX: status = jam_extract_bool_hex( heap_record, &statement_buffer[data_offset]); break; case JAM_BOOL_RUN_LENGTH: status = jam_extract_bool_run_length( heap_record, &statement_buffer[data_offset]); break; case JAM_BOOL_COMPRESSED: status = jam_extract_bool_compressed( heap_record, &statement_buffer[data_offset]); break; default: status = JAMC_INTERNAL_ERROR; } } /* in Jam 2.0, Boolean arrays in BIN and HEX format are reversed */ if ((status == JAMC_SUCCESS) && (jam_version == 2) && (representation == JAM_BOOL_BINARY)) { status = jam_reverse_boolean_array_bin(heap_record); } if ((status == JAMC_SUCCESS) && (jam_version == 2) && (representation == JAM_BOOL_HEX)) { status = jam_reverse_boolean_array_hex(heap_record); } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_extract_int_comma_sep ( JAMS_HEAP_RECORD *heap_record, char *statement_buffer ) /* */ /* Description: Extracts integer array data from statement buffer. */ /* Works on data in comma separated representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int expr_begin = 0; int expr_end = 0; char save_ch = 0; long address = 0L; long value = 0L; long dimension = heap_record->dimension; JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; for (address = 0L; (status == JAMC_SUCCESS) && (address < dimension); ++address) { status = JAMC_SYNTAX_ERROR; while ((jam_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_COMMA_CHAR) && (statement_buffer[index] != JAMC_SEMICOLON_CHAR) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over the expression */ } 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 = jam_evaluate_expression( &statement_buffer[expr_begin], &value, &expr_type); statement_buffer[expr_end] = save_ch; } if ((status == JAMC_SUCCESS) && ((expr_type != JAM_INTEGER_EXPR) && (expr_type != JAM_INT_OR_BOOL_EXPR))) { status = JAMC_TYPE_MISMATCH; } if (status == JAMC_SUCCESS) { heap_data[address] = value; if ((address < dimension) && (statement_buffer[index] == JAMC_COMMA_CHAR)) { ++index; } } } if (status == JAMC_SUCCESS) { while ((jam_isspace(statement_buffer[index])) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* skip over white space */ } if (statement_buffer[index] != JAMC_SEMICOLON_CHAR) { status = JAMC_SYNTAX_ERROR; } } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_read_int_comma_sep ( JAMS_HEAP_RECORD *heap_record ) /* */ /* Description: Reads integer array data directly from input stream. */ /* Works on data in comma separated representation. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int ch = 0; long address = 0L; long value = 0L; long dimension = heap_record->dimension; char expr_buffer[JAMC_MAX_STATEMENT_LENGTH + 1]; JAME_EXPRESSION_TYPE expr_type = JAM_ILLEGAL_EXPR_TYPE; JAM_RETURN_TYPE status = JAMC_SUCCESS; long *heap_data = &heap_record->data[0]; if (jam_seek(heap_record->position) != 0) { status = JAMC_IO_ERROR; } while ((status == JAMC_SUCCESS) && (address < dimension)) { ch = jam_get_real_char(); if (((ch == JAMC_COMMA_CHAR) && (address < (dimension - 1))) || ((ch == JAMC_SEMICOLON_CHAR) && (address == (dimension - 1)))) { expr_buffer[index] = JAMC_NULL_CHAR; index = 0; status = jam_evaluate_expression( expr_buffer, &value, &expr_type); if ((status == JAMC_SUCCESS) && ((expr_type != JAM_INTEGER_EXPR) && (expr_type != JAM_INT_OR_BOOL_EXPR))) { status = JAMC_TYPE_MISMATCH; } if (status == JAMC_SUCCESS) { heap_data[address] = value; ++address; } } else if ((ch == JAMC_COMMA_CHAR) && (address >= (dimension - 1))) { status = JAMC_BOUNDS_ERROR; } else { expr_buffer[index] = (char) ch; if (index < JAMC_MAX_STATEMENT_LENGTH) { ++index; } else { /* expression was too long */ status = JAMC_SYNTAX_ERROR; } } if (ch == EOF) { /* end of file */ status = JAMC_UNEXPECTED_END; } } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_read_integer_array_data ( JAMS_HEAP_RECORD *heap_record, char *statement_buffer ) /* */ /* Description: Reads integer array initialization data. If it is all */ /* present in the statement buffer, then it is extracted */ /* from the buffer. If the array initialization data did */ /* not fit into the statement buffer, it is read directly */ /* from the input stream. The only data representation */ /* supported for integer arrays is a comma-separated list */ /* of integer expressions. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { int index = 0; int ch = 0; long position = 0L; long data_position = 0L; BOOL done = FALSE; BOOL comment = FALSE; BOOL found_equal = FALSE; BOOL found_space = FALSE; BOOL data_complete = FALSE; JAM_RETURN_TYPE status = JAMC_SUCCESS; /* * See if all the initialization data is present in the statement buffer */ if ((status == JAMC_SUCCESS) && !heap_record->cached) { while ((statement_buffer[index] != JAMC_NULL_CHAR) && (statement_buffer[index] != JAMC_SEMICOLON_CHAR) && (index < JAMC_MAX_STATEMENT_LENGTH)) { ++index; /* look for semicolon */ } if (statement_buffer[index] == JAMC_SEMICOLON_CHAR) { data_complete = TRUE; } } /* * If data is not all present in the statement buffer, or if data * will be cached, find the position of the data in the input file */ if ((status == JAMC_SUCCESS) && ((!data_complete) || heap_record->cached)) { /* * Get position offset of initialization data */ if (jam_seek(jam_current_statement_position) == 0) { position = jam_current_statement_position; } else status = JAMC_IO_ERROR; while ((status == JAMC_SUCCESS) && !done) { ch = jam_getc(); if ((!comment) && (ch == JAMC_COMMENT_CHAR)) { /* beginning of comment */ comment = TRUE; } if ((!comment) && (!found_equal) && (ch == JAMC_EQUAL_CHAR)) { /* found the equal sign */ found_equal = TRUE; } if ((!comment) && found_equal && (!found_space) && jam_isspace((char)ch)) { /* found the space after the equal sign */ found_space = TRUE; } if ((!comment) && found_equal && found_space && jam_isdigit((char)ch)) { /* found the first character of the data area */ done = TRUE; data_position = position; } if ((!comment) && (ch == JAMC_SEMICOLON_CHAR)) { /* end of statement */ done = TRUE; } 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; } ++position; /* position of next character to be read */ } if (status == JAMC_SUCCESS) { heap_record->position = data_position; } /* * If data will not be cached, read it in from the file now. */ if ((status == JAMC_SUCCESS) && !heap_record->cached) { /* * Data is present, and will not be cached. Read it in. */ status = jam_read_int_comma_sep(heap_record); } /* * Restore file pointer to position of next statement */ if (status == JAMC_SUCCESS) { if (jam_seek(jam_next_statement_position) == 0) { jam_current_file_position = jam_next_statement_position; } else status = JAMC_IO_ERROR; } } if ((status == JAMC_SUCCESS) && data_complete && !heap_record->cached) { /* * Data is present, and will not be cached. Extract it from buffer. */ status = jam_extract_int_comma_sep(heap_record, statement_buffer); } /* * For Jam 2.0, reverse the order of the data values */ if ((status == JAMC_SUCCESS) && (jam_version == 2)) { long *heap_data = &heap_record->data[0]; long dimension = heap_record->dimension; long a, b, i, j; for (i = 0; i < dimension / 2; ++i) { j = (dimension - 1) - i; a = heap_data[i]; b = heap_data[j]; heap_data[j] = a; heap_data[i] = b; } } return (status); } /****************************************************************************/ /* */ JAM_RETURN_TYPE jam_get_array_value ( JAMS_SYMBOL_RECORD *symbol_record, long index, long *value ) /* */ /* Description: Gets the value of an array element. The value is */ /* passed back by reference. */ /* */ /* Returns: JAMC_SUCCESS for success, else appropriate error code */ /* */ /****************************************************************************/ { JAM_RETURN_TYPE status = JAMC_SUCCESS; JAMS_HEAP_RECORD *heap_record = NULL; long *heap_data = NULL; if ((symbol_record == NULL) || ((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))) { status = JAMC_INTERNAL_ERROR; } else { heap_record = (JAMS_HEAP_RECORD *) symbol_record->value; if (heap_record == NULL) { status = JAMC_INTERNAL_ERROR; } if ((status == JAMC_SUCCESS) && ((index < 0) || (index >= heap_record->dimension))) { status = JAMC_BOUNDS_ERROR; } if (status == JAMC_SUCCESS) { heap_data = &heap_record->data[0]; if ((symbol_record->type == JAM_INTEGER_ARRAY_WRITABLE) || (symbol_record->type == JAM_INTEGER_ARRAY_INITIALIZED)) { if (!heap_record->cached) { if (value != NULL) *value = heap_data[index]; } else { /* get data from cache */ /* cache not implemented yet! */ status = JAMC_INTERNAL_ERROR; } } else if ((symbol_record->type == JAM_BOOLEAN_ARRAY_WRITABLE) || (symbol_record->type == JAM_BOOLEAN_ARRAY_INITIALIZED)) { if (!heap_record->cached) { *value = (heap_data[index >> 5] & (1L << (index & 0x1f))) ? 1 : 0; } else { /* get data from cache */ /* cache not implemented yet! */ status = JAMC_INTERNAL_ERROR; } } else { status = JAMC_INTERNAL_ERROR; } } } return (status); }