/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1999 by Sun Microsystems, Inc. * All rights reserved. * Copyright 2015 PALO, Richard. */ #include #include #include #include #include #include #include "iconv_tm.h" #include "itmcomp.h" #include "itm_util.h" #include "hash.h" #include "maptype.h" static size_t map_table_resultlen(itmc_map_t *); static int data_pair_compare(itmc_data_pair_t **, itmc_data_pair_t **); static long data_to_long(itm_data_t *); static itm_tbl_hdr_t *map_table_indexed_fixed(itmc_data_pair_t **, itm_size_t, itm_data_t *, long, itm_num_t); static itm_tbl_hdr_t *map_table_dense_encoding(itmc_data_pair_t **, itm_size_t, itm_data_t *, unsigned long, unsigned char *, unsigned char *, long, itm_num_t); static itm_tbl_hdr_t *map_table_lookup_fixed(itmc_data_pair_t **, itm_size_t, itm_data_t *, long, itm_size_t); static itm_tbl_hdr_t *map_table_hash(itmc_data_pair_t **, itm_size_t, itm_data_t *, long, long, itm_size_t, itm_num_t); static itm_tbl_hdr_t *map_table_lookup_var(); static void put_dense_encoding_default(char *, unsigned char *, unsigned char *, unsigned char *, long, long, long); static size_t map_table_resultlen(itmc_map_t *); static void map_range_adjust_byte_seq(unsigned char *, unsigned char *, long, itmc_data_pair_t *); static void map_range_make_result(char *, itm_size_t, itm_size_t, char *, itm_size_t); static size_t map_table_num_range(itmc_data_pair_t *); static itmc_map_type_t check_map_type(itmc_map_attr_t *); static itmc_name_t *name_lookup(itm_data_t *, itm_type_t); static itmc_name_t *name_refer(itm_data_t *, itm_type_t, itmc_ref_t *); static itmc_name_t *name_register(itm_data_t *, itm_type_t, itmc_ref_t *); static void op_hirarchy(itm_tbl_hdr_t *, itmc_obj_t *); static obj_array_t obj_list_to_array(itm_size_t, itmc_obj_t *, itm_size_t); void itm_def_process(itm_data_t *itm_name) { itm_hdr_t *itm_hdr; long len; TRACE_MESSAGE('y', ("itm_def_process\n")); itm_hdr = malloc_vital(sizeof (itm_hdr_t)); (void) memset(itm_hdr, 0, sizeof (itm_hdr_t)); if ((NULL != cmd_opt.interpreter) && (0 < (len = strlen(cmd_opt.interpreter)))) { itm_hdr->interpreter = *(str_to_data(len, cmd_opt.interpreter)); } if ((sizeof (itm_place_t)) < itm_hdr->interpreter.size) { (void) obj_register(ITMC_OBJ_STRING, NULL, (void *)itm_hdr->interpreter.place.itm_ptr, itm_hdr->interpreter.size, &(itm_hdr->interpreter.place), OBJ_REG_HEAD); } itm_hdr->type_id = *itm_name; if ((sizeof (itm_place_t)) < itm_hdr->type_id.size) { (void) obj_register(ITMC_OBJ_STRING, NULL, (void *)itm_hdr->type_id.place.itm_ptr, itm_hdr->type_id.size, &(itm_hdr->type_id.place), OBJ_REG_HEAD); } (void) assemble(itm_hdr); } itmc_obj_t * direction_unit( itmc_ref_t *cond, itm_data_t *cond_name, itmc_action_t *act, itm_data_t *act_name) { itmc_obj_t *du; itm_direc_t *direc; du = malloc_vital(sizeof (itmc_obj_t)); du->type = ITMC_OBJ_DIREC; du->name = NULL; du->obj = direc = malloc_vital(sizeof (itm_direc_t)); if (NULL != cond) { direc->condition.itm_ptr = (uintptr_t)NULL; cond->referencer = &(direc->condition); du->ref[0] = cond; } else if (NULL != cond_name) { direc->condition.itm_ptr = (itm_place2_t)(cond_name); du->ref[0] = obj_register(ITMC_OBJ_COND, cond_name, NULL, 0, &(direc->condition), OBJ_REG_TAIL); } else { direc->condition.itm_ptr = 0; du->ref[0] = NULL; } if (NULL != act_name) { direc->action.itm_ptr = (itm_place2_t)(act_name); du->ref[1] = obj_register(ITMC_OBJ_ACTION, act_name, NULL, 0, &(direc->action), OBJ_REG_TAIL); } else if (NULL != act && act->tbl_hdr != NULL) { direc->action.itm_ptr = (itm_place2_t)(act->tbl_hdr); du->ref[1] = obj_register(act->type, (itm_data_t *)(act->tbl_hdr->name.itm_ptr), act->tbl_hdr, act->tbl_hdr->size, &(direc->action), OBJ_REG_TAIL); } else { return (NULL); } du->ref[2] = NULL; return (du); } itm_tbl_hdr_t * obj_table(itm_type_t tbl_type, itm_data_t *name, itmc_obj_t *obj_list, itm_size_t obj_size) { itm_tbl_hdr_t *tbl; obj_array_t obj_array; obj_array = obj_list_to_array(sizeof (itm_tbl_hdr_t), obj_list, obj_size); tbl = obj_array.obj; tbl->type = tbl_type; if (name) { #if !defined(_LP64) tbl->name.itm_pad = 0; #endif tbl->name.itm_ptr = (itm_place2_t)name; } else { #if !defined(_LP64) tbl->name.itm_pad = 0; #endif tbl->name.itm_ptr = (uintptr_t)NULL; } tbl->size = (sizeof (itm_tbl_hdr_t)) + (obj_array.num *obj_size); tbl->number = obj_array.num; if ((ITM_TBL_MASK&tbl->type) == ITM_TBL_OP) { op_hirarchy(tbl, obj_list); } return (tbl); } /* * */ static obj_array_t obj_list_to_array(itm_size_t hdr_size, itmc_obj_t *obj_list, itm_size_t size) { obj_array_t obj_array; itm_size_t offset; itmc_obj_t *ol; for (obj_array.num = 0, ol = obj_list; ol; obj_array.num += 1, ol = ol->next) { /* NOP */; } obj_array.obj = malloc_vital(hdr_size + (size * obj_array.num)); if (obj_array.num == 0) return (obj_array); for (offset = hdr_size, ol = obj_list; ol; offset += size, ol = ol->next) { (void) memcpy((char *)(obj_array.obj) + offset, ol->obj, size); if (ol->ref[0]) { ol->ref[0]->referencer = (void *)((char *)(ol->ref[0]->referencer) + ((char *)(obj_array.obj) - (char *)(ol->obj) + offset)); } if (ol->ref[1]) { ol->ref[1]->referencer = (void *)((char *)(ol->ref[1]->referencer) + ((char *)(obj_array.obj) - (char *)(ol->obj) + offset)); } if (ol->ref[2]) { ol->ref[2]->referencer = (void *)((char *)(ol->ref[2]->referencer) + ((char *)(obj_array.obj) - (char *)(ol->obj) + offset)); } } return (obj_array); } static void op_hirarchy(itm_tbl_hdr_t *optbl, itmc_obj_t *obj_list) { itm_op_outer_t *o; itm_op_inner_t *in; itmc_obj_t *ol; TRACE_MESSAGE('l', ("op_hirarchy (optbl=%x)\n", optbl)); o = malloc_vital(sizeof (itm_op_outer_t)); o->link = itm_op_outer; itm_op_outer = o; o->in = NULL; o->optbl = optbl; for (ol = obj_list; ol != NULL; ol = ol->next) { if ((ol->type == ITMC_OBJ_OP) && (((itm_op_t *)ol->obj)->type == ITM_OP_OPERATION)) { in = malloc_vital(sizeof (itm_op_inner_t)); in->in = o->in; o->in = in; TRACE_MESSAGE('L', ("o->in(%x) in->in(%x)\n", o->in, in->in)); in->ref = ol->ref[0]; } } #ifdef ENABLE_TRACE for (in = o->in; in != NULL; in = in->in) { TRACE_MESSAGE('L', ("o=%x in=%x in->in=%x\n", o, in, in->in)); TRACE_MESSAGE('L', ("o(table)%x->in(ref)=%x\n", o->optbl, in->ref)); } #endif } itmc_obj_t * obj_list_append(itmc_obj_t *obj_list, itmc_obj_t *obj) { if (0 == obj) { return (obj_list); } obj->next = NULL; obj->last = obj; if (obj_list) { obj_list->last->next = obj; obj_list->last = obj; return (obj_list); } else { return (obj); } } itmc_ref_t * obj_register(itm_type_t type, itm_data_t *name, void *obj, size_t size, itm_place_t *ref, itm_type_t reg_place) { itmc_ref_t *refp; TRACE_MESSAGE('O', ("obj_register: %6ld %08p %08p %08ld %08p %ld\n", type, name, obj, size, ref, reg_place)); refp = malloc_vital(sizeof (itmc_ref_t)); refp->name = NULL; refp->referencee = obj; #if !defined(_LP64) refp->reloc.itm_pad = 0; #endif refp->reloc.itm_ptr = 0; refp->size = size; refp->referencer = ref; refp->next = NULL; if (NULL == obj) { /* reference to named object */ if (NULL == name) { if (0 == error_deferred) { /* should never happen */ itm_error( gettext("internal error: " "obj_register: (NULL == obj) " "&& (NULL == name)\n")); exit(ITMC_STATUS_SYS2); } return (NULL); } refp->name = name_refer(name, type, refp); return (refp); } else if ((NULL != name) && (0 < name->size)) { /* definition of named object */ refp->name = name_register(name, type, refp); } if ((ITMC_OBJ_FIRST <= type) && (type <= ITMC_OBJ_LAST)) { switch (reg_place) { case OBJ_REG_HEAD: refp->next = ref_first[type]; ref_first[type] = refp; if (NULL == ref_last[type]) { ref_last[type] = refp; } break; case OBJ_REG_TAIL: if (ref_first[type]) { ref_last[type]->next = refp; } else { ref_first[type] = refp; } ref_last[type] = refp; break; } } else { itm_error(gettext("obj_register: illegal object type\n")); exit(ITMC_STATUS_SYS2); } return (refp); } itm_tbl_hdr_t * range_table(itm_data_t *name, itmc_obj_t *obj_list) { itm_num_t num; itmc_obj_t *ol; itmc_data_pair_t *rp; itm_range_hdr_t *rh; itm_tbl_hdr_t *table; itm_size_t length = 0; itm_num_t i; char *p; itm_size_t table_size; /* count range, determine length */ for (num = 0, ol = obj_list; ol; ol = ol->next, num++) { rp = (itmc_data_pair_t *)(ol->obj); if (length == 0) { if (rp->data0.size == 0) { itm_error(gettext("between has null range\n")); error_deferred += 1; return (NULL); } length = rp->data0.size; } if ((rp->data0.size != length) || (rp->data1.size != length)) { itm_error(gettext( "length of source sequences must be the same\n")); error_deferred += 1; return (NULL); } } if (num == 0) { itm_error(gettext("between has no ranges\n")); error_deferred += 1; return (NULL); } table_size = ((sizeof (itm_tbl_hdr_t)) + (sizeof (itm_range_hdr_t)) + (length * num) * 2); table_size = ITMROUNDUP(table_size); table = malloc_vital(table_size); table->type = ITM_TBL_RANGE; if (NULL != name) table->name.itm_ptr = (itm_place2_t)name; table->size = table_size; table->number = num; rh = (itm_range_hdr_t *)(table + 1); rh->len = length; p = (char *)(rh + 1); for (ol = obj_list, i = 0; ol; ol = ol->next, i++) { rp = (itmc_data_pair_t *)(ol->obj); (void) memcpy(p, (NSPTR(&(rp->data0))), length); p += length; (void) memcpy(p, (NSPTR(&(rp->data1))), length); p += length; } return (table); } /* * escape sequence table for stateful code set sequence */ itm_tbl_hdr_t * escseq_table(itm_data_t *name, itmc_obj_t *obj_list) { itm_num_t num; itmc_obj_t *ol; itm_data_t *ep; itm_escapeseq_hdr_t *eh; itm_tbl_hdr_t *table; itm_size_t len_max = 0; itm_size_t len_min; itm_num_t i; itm_size_t table_size; ol = obj_list; len_min = ((itm_data_t *)(ol->obj))->size; for (num = 0; NULL != ol; ol = ol->next, num++) { ep = (itm_data_t *)(ol->obj); if (ep->size < len_min) len_min = ep->size; if (ep->size > len_max) len_max = ep->size; } if (num == 0) { itm_error(gettext ("escape sequence is defined without sequence\n")); error_deferred += 1; return (NULL); } else if (0 == len_min) { itm_error(gettext("null sequence\n")); error_deferred += 1; return (NULL); } table_size = ((sizeof (itm_tbl_hdr_t)) + (sizeof (itm_escapeseq_hdr_t)) + (sizeof (itm_data_t) * num)); table_size = ITMROUNDUP(table_size); table = malloc_vital(table_size); table->type = ITM_TBL_ESCAPESEQ; if (NULL != name) table->name.itm_ptr = (itm_place2_t)name; table->size = table_size; table->number = num; eh = (itm_escapeseq_hdr_t *)(table + 1); eh->len_max = len_max; eh->len_min = len_min; for (ol = obj_list, ep = (itm_data_t *)(eh + 1); ol != NULL; ol = ol->next, ep++) { *ep = *((itm_data_t *)(ol->obj)); if ((sizeof (itm_place_t)) < ep->size) { (void) obj_register(ITMC_OBJ_DATA, NULL, (void *)(ep->place.itm_ptr), ep->size, &(ep->place), OBJ_REG_TAIL); } } (void) qsort((itm_data_t *)(eh + 1), num, sizeof (itm_data_t), (int (*)(const void *, const void *))data_compare); for (i = 0, ep = (itm_data_t *)(eh + 1); i < num - 1; i++, ep++) { if (0 <= data_compare(ep, (ep + 1))) { itm_error( gettext( "same escape sequences are defined: " "0x%1$s 0x%2$s\n"), data_to_hexadecimal(ep), data_to_hexadecimal(ep + 1)); error_deferred += 1; return (NULL); } } return (table); } itm_tbl_hdr_t * map_table(itm_data_t *name, itmc_map_t *map_list, itmc_map_attr_t *attr) { itm_size_t num; itm_size_t num2; itmc_map_t *ml; itmc_data_pair_t **tpp; itm_tbl_hdr_t *table; long source_len = 0; long result_len = 0; long source_fixed_len = 1; long pass_through = 0; long default_count = 0; itm_data_t *default_data = NULL; long error_deferred_local = 0; unsigned long dense_encoded_map_ent; unsigned long simple_indexed_map_ent; itm_size_t source_start; itm_size_t source_end; unsigned long u; unsigned char *byte_seq_min; unsigned char *byte_seq_max; unsigned char *p; long i; itmc_map_type_t map_type = ITMC_MAP_UNKNOWN; itmc_map_name_type_t *map_name_type; long hash_factor; long result_len_specfied = 0; size_t j; long n; itmc_data_pair_t **dp1; itm_num_t error_count = 0; if (attr != NULL) { map_type = check_map_type(attr); } if (ITMC_MAP_UNKNOWN == map_type) { map_type = ITMC_MAP_AUTOMATIC; } hash_factor = ((NULL != attr) && (attr->hash_factor != 0)) ? attr->hash_factor : 200; map_name_type = cmd_opt.map_name_type; for (; map_name_type; map_name_type = map_name_type->next) { if ('\0' == *(map_name_type->name)) { map_type = map_name_type->type; hash_factor = map_name_type->hash_factor; break; } } map_name_type = cmd_opt.map_name_type; if ((NULL != name) && (NULL != cmd_opt.map_name_type)) { p = NSPTR(name); for (; map_name_type; map_name_type = map_name_type->next) { if (0 == strcmp(map_name_type->name, (char *)p)) { map_type = map_name_type->type; hash_factor = map_name_type->hash_factor; break; } } } if (NULL != attr) { if (MAXSEQUENCE < attr->resultlen) { itm_error( gettext("output_byte_length must be less than %1$d\n"), MAXSEQUENCE); error_deferred += 1; return (NULL); } result_len_specfied = attr->resultlen; } else { result_len_specfied = 0; } for (num = 0, ml = map_list; ml; ml = ml->next, num++) { /* default */ if (0 == ml->data_pair.data0.size) { if (0 == ml->data_pair.data1.size) { pass_through += 1; default_data = (itm_data_t *)(-1); } else { default_count += 1; default_data = &(ml->data_pair.data1); } --num; } else if (0 == ml->data_pair.data1.size) { /* error source sequence */ continue; } /* fixed length */ if ((0 < source_len) && (0 < ml->data_pair.data0.size) && (source_len != ml->data_pair.data0.size)) { source_fixed_len = 0; } /* maximum length */ if (source_len < ml->data_pair.data0.size) { source_len = ml->data_pair.data0.size; } if (result_len < ml->data_pair.data1.size) { result_len = ml->data_pair.data1.size; } /* map source has range */ if (0 < ml->data_pair.range.size) { if (ml->data_pair.range.size != ml->data_pair.data0.size) { itm_error( gettext("length of source range must be " "the same: 0x%1$s 0x%2$s\n"), data_to_hexadecimal(&(ml->data_pair.data0)), data_to_hexadecimal( &(ml->data_pair.range))); error_deferred += 1; return (NULL); } if (0 <= data_compare(&(ml->data_pair.data0), &((ml->data_pair.range)))) { itm_error( gettext("source range error: 0x%1$s 0x%2$s\n"), data_to_hexadecimal( &(ml->data_pair.data0)), data_to_hexadecimal( &(ml->data_pair.range))); error_deferred += 1; return (NULL); } j = map_table_resultlen(ml); if (result_len < j) { result_len = j; } } } if (num == 0) { itm_error( gettext("no mapping pair\n")); error_deferred += 1; return (NULL); } if (0 != result_len_specfied) { if (result_len > result_len_specfied) { itm_error( gettext("result value length is " "over specifed output_byte_length(%1$ld)\n"), result_len_specfied); error_deferred += 1; return (NULL); } result_len = result_len_specfied; } byte_seq_min = malloc_vital((sizeof (unsigned char)) * source_len); byte_seq_max = malloc_vital((sizeof (unsigned char)) * source_len); for (num = 0, ml = map_list; ml; ml = ml->next, num++) { if (0 == ml->data_pair.data0.size) { continue; } p = (unsigned char *)(NSPTR(&((ml->data_pair).data0))); for (i = 0; i < source_len; i++) { *(byte_seq_min + i) = *(p + i); *(byte_seq_max + i) = *(p + i); } break; } for (num = 0, ml = map_list; ml; ml = ml->next, num++) { if (0 == ml->data_pair.data0.size) { num--; continue; } if (ml->data_pair.range.size > 0) { map_range_adjust_byte_seq(byte_seq_min, byte_seq_max, source_len, &(ml->data_pair)); } else { p = (unsigned char *)(NSPTR(&((ml->data_pair).data0))); for (i = 0; i < source_len; i++) { if (*(p + i) < *(byte_seq_min + i)) { *(byte_seq_min + i) = *(p + i); } if (*(byte_seq_max + i) < *(p + i)) { *(byte_seq_max + i) = *(p + i); } } } } for (dense_encoded_map_ent = 1, i = 0; i < source_len; i++) { u = dense_encoded_map_ent; dense_encoded_map_ent *= (*(byte_seq_max + i) - *(byte_seq_min + i) + 1); if (dense_encoded_map_ent < u) { dense_encoded_map_ent = (ulong_t)(~0); break; } } #if defined(DEBUG) if (TRACE('m')) { int i; TRACE_MESSAGE('m', ("map_table: ent=%lu num=%lu ", dense_encoded_map_ent, num)); TRACE_MESSAGE('m', ("byte_seq_min=0x")); for (i = 0; i < source_len; i++) { TRACE_MESSAGE('m', ("%02x", *(byte_seq_min + i))); } TRACE_MESSAGE('m', (" byte_seq_max=0x")); for (i = 0; i < source_len; i++) { TRACE_MESSAGE('m', ("%02x", *(byte_seq_max + i))); } TRACE_MESSAGE('m', ("\n")); } #endif /* DEBUG */ tpp = malloc_vital((sizeof (itmc_data_pair_t *)) * num); for (num = 0, num2 = 0, ml = map_list; ml; ml = ml->next) { if (0 < ml->data_pair.data0.size) { itm_num_t range_num; *(tpp + num) = &(ml->data_pair); num++; range_num = 1; if (ml->data_pair.range.size > 0) { range_num += map_table_num_range(&(ml->data_pair)); } num2 += range_num; if (0 == ml->data_pair.data1.size) { /* specified error sequence */ error_count += range_num; } } } (void) qsort(tpp, num, sizeof (itmc_data_pair_t *), (int (*)(const void *, const void *))data_pair_compare); /* check if map_pair range and next map_pair are overrapped */ for (n = 0, dp1 = tpp; n < (num-1); n++, dp1++) { if (((*(dp1+0))->range.size != 0) && (0 <= data_compare(&((*(dp1+0))->range), &((*(dp1+1))->data0)))) { itm_error( gettext("ranges of source sequences " "overrapped: %1$s %2$s\n"), data_to_hexadecimal(&((*(dp1+0))->range)), data_to_hexadecimal(&((*(dp1+1))->data0))); error_deferred += 1; return (NULL); } } if (1 < default_count) { itm_error( gettext("default is specified %1$d times in a map\n"), default_count); error_deferred_local += 1; } if ((1 == default_count) && (!source_fixed_len)) { itm_error( gettext("default is specified," " but length of source data is not fixed\n")); error_deferred_local += 1; } if ((1 <= pass_through) && (source_len != result_len)) { itm_error( gettext("\"default no_change_copy\" is " "specified, but size does not match\n")); error_deferred_local += 1; } if (error_deferred_local) { error_deferred += error_deferred_local; return (NULL); } if (source_fixed_len) { source_start = data_to_long(&((*(tpp + 0))->data0)); source_end = data_to_long(&((*(tpp + num - 1))->data0)); if (0 < (*(tpp + num - 1))->range.size) { source_end = data_to_long(&((*(tpp + num - 1))->range)); } simple_indexed_map_ent = source_end - source_start + 1; TRACE_MESSAGE('m', ("map_table: simple_indexed_map_ent=%lu\n", simple_indexed_map_ent)); switch (map_type) { case ITMC_MAP_AUTOMATIC: if ((source_len <= 2) && (((ulong_t)(~0) == dense_encoded_map_ent) || (simple_indexed_map_ent < (dense_encoded_map_ent * 2)))) { /* * for small source sequence, * if dense table is not so large * compared with simple table, * use simple. */ map_type = ITMC_MAP_SIMPLE_INDEX; } else if (cmd_opt.large_table) { if ((sizeof (long)) < source_len) { itm_error( gettext("length of source is too long " "for large table: %ld\n"), source_len); error_deferred += 1; return (NULL); } map_type = ITMC_MAP_SIMPLE_INDEX; } else if (((ulong_t)(~0) == dense_encoded_map_ent) || ((0xffff < dense_encoded_map_ent) && ((num2 * 8) < dense_encoded_map_ent))) { /* * if dense can be used and not too large * ( less than (hash table entry * 8), * use dense. */ map_type = ITMC_MAP_SIMPLE_HASH; } else { map_type = ITMC_MAP_DENSE_ENCODING; } break; case ITMC_MAP_SIMPLE_INDEX: if ((sizeof (long)) < source_len) { itm_error( gettext("length of source is too long " "for index lookup: %ld\n"), source_len); error_deferred += 1; return (NULL); } break; case ITMC_MAP_SIMPLE_HASH: for (i = 2, u = 256; i < (sizeof (long)); i++) { u *= 256; } if (u < num2) { itm_error( gettext("map is too large for hashing: %lu\n"), num2); error_deferred += 1; return (NULL); } break; case ITMC_MAP_DENSE_ENCODING: for (i = 2, u = 256; i < (sizeof (long)); i++) { u *= 256; } if (u < dense_encoded_map_ent) { itm_error( gettext( "map is too large for dense encoding: " "%lu\n"), dense_encoded_map_ent); error_deferred += 1; return (NULL); } break; case ITMC_MAP_BINARY_SEARCH: for (i = 2, u = 256; i < (sizeof (long)); i++) { u *= 256; } if (u < num2) { itm_error( gettext("length of source is too long for " "binary search: %ld\n"), source_len); error_deferred += 1; return (NULL); } break; default: break; } switch (map_type) { case ITMC_MAP_SIMPLE_INDEX: table = map_table_indexed_fixed( tpp, num, default_data, result_len, error_count); break; case ITMC_MAP_SIMPLE_HASH: table = map_table_hash(tpp, num, default_data, hash_factor, result_len, num2, error_count); break; case ITMC_MAP_DENSE_ENCODING: table = map_table_dense_encoding(tpp, num, default_data, dense_encoded_map_ent, byte_seq_min, byte_seq_max, result_len, error_count); break; case ITMC_MAP_BINARY_SEARCH: table = map_table_lookup_fixed(tpp, num, default_data, result_len, num2); break; } } else { table = map_table_lookup_var(); } if ((NULL != name) && (NULL != table)) { table->name.itm_ptr = (itm_place2_t)name; } return (table); } static itmc_map_type_t check_map_type(itmc_map_attr_t *attr) { int i; if (NULL == attr->type) { return (0); } for (i = 0; NULL != map_type_name[i].name; i++) { if (0 == strncmp(((char *)&(attr->type->place)), map_type_name[i].name, attr->type->size)) { return (map_type_name[i].type); } } return (0); } static itm_tbl_hdr_t * map_table_indexed_fixed( itmc_data_pair_t **tpp, itm_size_t num, itm_data_t *default_data, long resultlen, itm_num_t error_count) { itm_tbl_hdr_t *header; itm_map_idx_fix_hdr_t *sub_hdr; char *table; char *error_table; itm_size_t source_start; itm_size_t source_end; itm_size_t entry_num; itm_size_t table_size; itm_size_t j; itm_size_t i; itm_size_t k; char *p; itm_data_t *source; TRACE_MESSAGE('m', ("map_table_range : %ld\n", num)); source = &((*(tpp + 0))->data0); assert((sizeof (itm_place_t)) >= source->size); if ((1 == source->size) && (1 == resultlen)) { source_start = 0; source_end = 255; } else { source_start = data_to_long(&((*(tpp + 0))->data0)); source_end = data_to_long(&((*(tpp + num - 1))->data0)); if (0 < (*(tpp + num - 1))->range.size) source_end = data_to_long(&((*(tpp + num - 1))->range)); } entry_num = source_end - source_start + 1; table_size = ((sizeof (itm_tbl_hdr_t)) + (sizeof (itm_map_idx_fix_hdr_t)) + (resultlen * entry_num)); if (0 < error_count) { table_size += entry_num; } if (NULL == default_data) { if ((num < entry_num) || (error_count <= 0)) { table_size += entry_num; } } else if ((itm_data_t *)(-1) != default_data) { table_size += resultlen; } table_size = ITMROUNDUP(table_size); header = malloc_vital(table_size); sub_hdr = (itm_map_idx_fix_hdr_t *)(header + 1); table = (char *)(sub_hdr + 1); if ((1 == (*tpp)->data0.size) && (1 == (*tpp)->data1.size)) { header->type = ITM_TBL_MAP_INDEX_FIXED_1_1; } else { header->type = ITM_TBL_MAP_INDEX_FIXED; } header->name.itm_ptr = 0; header->size = table_size; header->number = entry_num; sub_hdr->source_len = (*tpp)->data0.size; sub_hdr->result_len = resultlen; sub_hdr->start.itm_ptr = source_start; sub_hdr->end.itm_ptr = source_end; sub_hdr->error_num = error_count; /* > 0; so pad4 = 0 */ if (NULL != default_data) { if ((itm_data_t *)(-1) == default_data) { sub_hdr->default_error = -1; #if !defined(_LP64) sub_hdr->pad3_num = (pad_t)(~0); #endif } else { sub_hdr->default_error = 0; } } else { if (num < entry_num) { sub_hdr->default_error = 1; } else { sub_hdr->default_error = 2; } } error_table = (table + (resultlen * entry_num)); if (-1 == sub_hdr->default_error) { if (source->size != resultlen) { itm_error( gettext("\"default no_change_copy\" is " "specified, but size does not match\n")); exit(ITMC_STATUS_BT); } for (i = 0, j = 0; i < (entry_num); i++, j += resultlen) { for (k = 0; k < resultlen; k++) { *(table + j + k) = (((source_start + i) >> ((resultlen - k - 1) * 8)) & 0x00ff); } } } else if (0 == sub_hdr->default_error) { error_table += resultlen; if (default_data->size <= (sizeof (itm_place_t))) { for (i = 0, j = 0; i < (entry_num + 1); /* last one is for default */ i++, j += resultlen) { (void) memcpy(table + j + (resultlen - default_data->size), (void *)(&(default_data->place.itm_64d)), default_data->size); } } else { for (i = 0, j = 0; i < (entry_num + 1); /* last one is for default */ i++, j += resultlen) { (void) memcpy(table + j + (resultlen - default_data->size), (void *)(default_data->place.itm_ptr), default_data->size); } } } if (1 == sub_hdr->default_error) { (void) memset(error_table, 1, entry_num); for (i = 0; i < num; i++) { if (0 == (*(tpp + i))->data1.size) { continue; /* error sequence */ } j = data_to_long(&((*(tpp + i))->data0)) - source_start; k = ((*(tpp + i))->range.size) == 0 ? j : data_to_long(&((*(tpp + i))->range)) - source_start; for (; j <= k; j++) { *(error_table + j) = 0; } } } else if (0 < error_count) { (void) memset(error_table, 0, entry_num); for (i = 0; i < num; i++) { if (0 == (*(tpp + i))->data1.size) { /* error sequence */ j = data_to_long(&((*(tpp + i))->data0)) - source_start; k = ((*(tpp + i))->range.size) == 0 ? j : data_to_long(&((*(tpp + i))->range)) - source_start; for (; j <= k; j++) { *(error_table + j) = 1; } } } } p = malloc_vital(sizeof (uchar_t *) * resultlen); for (i = 0; i < num; i++) { j = data_to_long(&((*(tpp + i))->data0)) - source_start; if (0 != (*(tpp + i))->range.size) k = data_to_long(&((*(tpp + i))->range)) - source_start; else k = j; (void) memset(p, 0, sizeof (uchar_t *) * resultlen); (void) memcpy(p + (resultlen - (*(tpp + i))->data1.size), ((caddr_t)NSPTR(&((*(tpp + i))->data1))), (*(tpp + i))->data1.size); map_range_make_result(table, j, k, p, resultlen); } free(p); return (header); } static itm_tbl_hdr_t * map_table_lookup_fixed( itmc_data_pair_t **tpp, itm_size_t num, itm_data_t *default_data, long resultlen, itm_size_t num2) { itm_tbl_hdr_t *header; itm_map_lookup_hdr_t *sub_hdr; char *table; itm_size_t table_size; itm_size_t j; itm_size_t i; itm_size_t k; itm_size_t h; itm_data_t *source; uchar_t *source_data; uchar_t *result_data; TRACE_MESSAGE('m', ("map_table_lookup_fixed : %ld(%ld) 0x%lx\n", num, num2, default_data)); source = &((*(tpp + 0))->data0); table_size = ((sizeof (itm_tbl_hdr_t)) + (sizeof (itm_map_idx_fix_hdr_t)) + ((source->size + 1 + resultlen) * num2)); if ((NULL != default_data) && (((itm_data_t *)(-1)) != default_data)) { table_size += (source->size + 1 + resultlen); } table_size = ITMROUNDUP(table_size); header = malloc_vital(table_size); sub_hdr = (itm_map_lookup_hdr_t *)(header + 1); table = (char *)(sub_hdr + 1); header->type = ITM_TBL_MAP_LOOKUP; header->name.itm_ptr = 0; header->size = table_size; header->number = num2; if (NULL != default_data) { if ((itm_data_t *)(-1) == default_data) { #if !defined(_LP64) sub_hdr->pad3_num = (pad_t)(~0); #endif sub_hdr->default_error = -1; } else { sub_hdr->default_error = 0; } } else { sub_hdr->default_error = 2; } sub_hdr->source_len = source->size; sub_hdr->result_len = resultlen; /* specified map */ source_data = malloc_vital(source->size); result_data = malloc_vital(resultlen); for (i = 0, j = 0; i < num; i++) { (void) memcpy(table + j, NSPTR(&((*(tpp + i))->data0)), source->size); j += source->size; if (0 == (*(tpp + i))->data1.size) { *(table + j) = 1; /* specified error */ j += 1; } else { /* *(table + j) = 0; ** valid */ j += 1; (void) memcpy(table + j + (resultlen - (*(tpp + i))->data1.size), NSPTR(&((*(tpp + i))->data1)), (*(tpp + i))->data1.size); } j += resultlen; if ((*(tpp + i))->range.size != 0) { (void) memcpy(source_data, NSPTR(&((*(tpp + i))->data0)), source->size); (void) memset(result_data, 0, resultlen); (void) memcpy(result_data + (resultlen - (*(tpp + i))->data1.size), NSPTR(&((*(tpp + i))->data1)), (*(tpp + i))->data1.size); h = map_table_num_range((*(tpp + i))); for (k = 0; k < h; k++) { uchar_t *dp; itm_size_t m; for (m = 0, dp = (uchar_t *) (source_data + source->size - 1); m < source->size; m++, dp--) { if (0xff != *dp) { (*dp) += (char)1; for (++dp; m > 0; m--, dp++) { (*dp) = 0x00; } break; } } (void) memcpy(table + j, source_data, source->size); j += source->size; if (0 == (*(tpp + i))->data1.size) { *(table + j) = 1; /* specified error */ j += 1; } else { /* *(table + j) = 0; ** valid */ j += 1; for (m = 0, dp = (uchar_t *) (result_data + resultlen - 1); m < resultlen; m++, dp--) { if (0xff != *dp) { (*dp) += 1; for (++dp; m > 0; m--, dp++) { (*dp) = 0x00; } break; } } (void) memcpy(table + j, result_data, resultlen); } j += resultlen; } } } free(source_data); free(result_data); /* default */ if ((NULL != default_data) && (((itm_data_t *)(-1)) != default_data)) { (void) memset(table + j, 0, source->size + 1 + resultlen); (void) memcpy(table + j + source->size + 1 + (resultlen - default_data->size), NSPTR(default_data), default_data->size); } return (header); } static itm_tbl_hdr_t * map_table_hash( itmc_data_pair_t **tpp, itm_size_t num, itm_data_t *default_data, long hash_factor, long resultlen, itm_size_t num2, itm_num_t error_count) { itm_tbl_hdr_t *header; itm_map_hash_hdr_t *sub_hdr; itm_size_t table_size; char *error_table; char *hash_table; itm_size_t hash_table_num; char *of_table; itm_size_t of_table_num; itm_size_t pair_size; itm_size_t i; itm_size_t j; itm_size_t k; char *p; itm_data_t *source; long hash_value; #if defined(DEBUG) long hash_none; long hash_one; long hash_conflict; #endif /* DEBUG */ uchar_t *source_data; uchar_t *result_data; uchar_t *dp; itm_size_t m; itm_size_t n; itm_size_t h; TRACE_MESSAGE('m', ("map_table_hash : %ld(%ld) 0x%lx\n", num, num2, default_data)); source = &((*(tpp + 0))->data0); pair_size = (source->size + 1 + resultlen); if (100 <= hash_factor) { hash_table_num = (num2 * (hash_factor / 100.0)); } else { hash_table_num = (num2 * 2); } if (hash_table_num < 256) { hash_table_num = 256; } source_data = malloc_vital(source->size); result_data = malloc_vital(resultlen); hash_table = malloc_vital(hash_table_num); for (i = 0, of_table_num = 0; i < num; i++) { hash_value = hash(NSPTR(&((*(tpp + i))->data0)), (*(tpp + i))->data0.size, hash_table_num); if (0 == *(hash_table + hash_value)) { *(hash_table + hash_value) = 1; } else { *(hash_table + hash_value) = 2; of_table_num += 1; } if ((*(tpp + i))->range.size != 0) { (void) memcpy(source_data, NSPTR(&((*(tpp + i))->data0)), source->size); h = map_table_num_range((*(tpp + i))); for (n = 0; n < h; n++) { for (m = 0, dp = (uchar_t *) (source_data + source->size - 1); m < source->size; m++, dp--) { if (0xff != *dp) { (*dp) += 1; for (++dp; m > 0; m--, dp++) { (*dp) = 0x00; } break; } } hash_value = hash((char *)source_data, source->size, hash_table_num); if (0 == *(hash_table + hash_value)) { *(hash_table + hash_value) = 1; } else { *(hash_table + hash_value) = 2; of_table_num += 1; } } } } #if defined(DEBUG) if (TRACE('s')) { hash_none = 0; hash_one = 0; hash_conflict = 0; j = 0; for (i = 0; i < hash_table_num; i++) { if (2 == *(hash_table + i)) { (void) putchar('2'); hash_conflict += 1; } else if (1 == *(hash_table + i)) { (void) putchar('1'); hash_one += 1; } else if (0 == *(hash_table + i)) { (void) putchar('-'); hash_none += 1; } else { (void) putchar('*'); } if (63 <= j) { j = 0; (void) putchar('\n'); } else { j += 1; } } (void) putchar('\n'); (void) printf("null=%ld one=%ld conflict=%ld\n", hash_none, hash_one, hash_conflict); } #endif /* DEBUG */ free(hash_table); table_size = ((sizeof (itm_tbl_hdr_t)) + (sizeof (itm_map_hash_hdr_t)) + (hash_table_num) + (pair_size * hash_table_num) + (pair_size * of_table_num)); if ((NULL != default_data) && (((itm_data_t *)(-1)) != default_data)) { table_size += pair_size; } table_size = ITMROUNDUP(table_size); header = malloc_vital(table_size); sub_hdr = (itm_map_hash_hdr_t *)(header + 1); error_table = (char *)(sub_hdr + 1); hash_table = error_table + hash_table_num; of_table = hash_table + (pair_size * hash_table_num); header->type = ITM_TBL_MAP_HASH; header->name.itm_ptr = 0; header->size = table_size; header->number = num2; if (NULL != default_data) { if ((itm_data_t *)(-1) == default_data) { sub_hdr->default_error = -1; #if !defined(_LP64) sub_hdr->pad7_num = (pad_t)(~0); #endif } else { sub_hdr->default_error = 0; } } else { sub_hdr->default_error = 2; } sub_hdr->source_len = source->size; sub_hdr->result_len = resultlen; sub_hdr->hash_tbl_size = (pair_size * hash_table_num); sub_hdr->hash_tbl_num = hash_table_num; sub_hdr->hash_of_size = (pair_size * of_table_num); sub_hdr->hash_of_num = of_table_num; sub_hdr->error_num = error_count; /* > 0; so pad4 = 0 */ /* specified map */ for (i = 0, j = 0, k = 0; i < num; i++) { hash_value = hash(NSPTR(&((*(tpp + i))->data0)), (*(tpp + i))->data0.size, hash_table_num); p = error_table + hash_value; if (*p) { /* conflict */ if (*p < 63) { *p += 1; } p = of_table + k; k += pair_size; } else { *p = 1; p = hash_table + (pair_size * hash_value); } (void) memcpy(p, NSPTR(&((*(tpp + i))->data0)), source->size); p += source->size; if (0 == (*(tpp + i))->data1.size) { (*p) = 1; /* specified error */ p++; } else { /* (*p) = 0; ** valid */ p++; (void) memset(p, 0, (resultlen - (*(tpp + i))->data1.size)); (void) memcpy(p + (resultlen - (*(tpp + i))->data1.size), NSPTR(&((*(tpp + i))->data1)), (*(tpp + i))->data1.size); } if ((*(tpp + i))->range.size != 0) { (void) memcpy(source_data, NSPTR(&((*(tpp + i))->data0)), source->size); (void) memset(result_data, 0, (resultlen - (*(tpp + i))->data1.size)); (void) memcpy(result_data + (resultlen - (*(tpp + i))->data1.size), NSPTR(&((*(tpp + i))->data1)), (*(tpp + i))->data1.size); h = map_table_num_range((*(tpp + i))); for (n = 0; n < h; n++) { for (m = 0, dp = (uchar_t *) (source_data + source->size - 1); m < source->size; m++, dp--) { if (0xff != *dp) { (*dp) += 1; for (++dp; m > 0; m--, dp++) { (*dp) = 0x00; } break; } } hash_value = hash((char *)source_data, source->size, hash_table_num); p = error_table + hash_value; if (*p) { /* conflict */ if (*p < 63) { *p += 1; } p = of_table + k; k += pair_size; } else { *p = 1; p = hash_table + (pair_size * hash_value); } (void) memcpy(p, source_data, source->size); p += source->size; if (0 == (*(tpp + i))->data1.size) { (*p) = 1; /* specified error */ p += 1; } else { /* (*p) = 0; ** valid */ p += 1; for (m = 0, dp = (uchar_t *) (result_data + resultlen - 1); m < resultlen; m++, dp--) { if (0xff != *dp) { (*dp) += 1; for (++dp; m > 0; m--, dp++) { (*dp) = 0x00; } break; } } (void) memcpy(p, result_data, resultlen); } } } } free(source_data); free(result_data); /* default */ if ((NULL != default_data) && (((itm_data_t *)(-1)) != default_data)) { j = ((pair_size * hash_table_num) + (pair_size * of_table_num)); (void) memcpy(hash_table + j + (resultlen - default_data->size), NSPTR(default_data), default_data->size); } #if defined(ENABLE_TRACE) for (i = 0, p = of_table; i < of_table_num; i++, p += 5) { (void) printf("0x%02x%02x%02x%02x 0x%02x\n", ((unsigned char)(*(p + 0))), ((unsigned char)(*(p + 1))), ((unsigned char)(*(p + 2))), ((unsigned char)(*(p + 3))), ((unsigned char)(*(p + 4)))); } #endif return (header); } static itm_tbl_hdr_t * map_table_dense_encoding( itmc_data_pair_t **tpp, itm_size_t num, itm_data_t *default_data, unsigned long entry_num, unsigned char *byte_seq_min, unsigned char *byte_seq_max, long resultlen, itm_num_t error_count) { itm_tbl_hdr_t *header; itm_map_dense_enc_hdr_t *sub_hdr; char *table; char *error_table; itm_size_t table_size; itm_size_t j; itm_size_t i; itm_size_t k; char *p; itm_data_t *source; unsigned char *byte_seq_def; TRACE_MESSAGE('m', ("map_table_dense_encoding : %ld\n", num)); source = &((*(tpp + 0))->data0); table_size = ((sizeof (itm_tbl_hdr_t)) + (sizeof (itm_map_dense_enc_hdr_t)) + (source->size + source->size) + (resultlen * entry_num)); if (0 < error_count) { table_size += entry_num; } if (NULL == default_data) { if ((num < entry_num) || (error_count <= 0)) { table_size += entry_num; } } else if ((itm_data_t *)(-1) != default_data) { table_size += resultlen; } table_size = ITMROUNDUP(table_size); header = malloc_vital(table_size); sub_hdr = (itm_map_dense_enc_hdr_t *)(header + 1); table = (char *)(sub_hdr + 1) + source->size + source->size; header->type = ITM_TBL_MAP_DENSE_ENC; header->name.itm_ptr = 0; header->size = table_size; header->number = entry_num; sub_hdr->source_len = (*tpp)->data0.size; sub_hdr->result_len = resultlen; sub_hdr->error_num = error_count; /* > 0; so pad4 = 0 */ if (NULL != default_data) { if ((itm_data_t *)(-1) == default_data) { sub_hdr->default_error = -1; #if !defined(_LP64) sub_hdr->pad3_num = (pad_t)(~0); #endif } else { sub_hdr->default_error = 0; } } else { if (num < entry_num) { sub_hdr->default_error = 1; } else { sub_hdr->default_error = 2; } } (void) memcpy((char *)(sub_hdr + 1), byte_seq_min, source->size); (void) memcpy((char *)(sub_hdr + 1) + source->size, byte_seq_max, source->size); if (-1 == sub_hdr->default_error) { byte_seq_def = malloc_vital((sizeof (unsigned char *)) * resultlen); if (source->size != resultlen) { itm_error( gettext("\"default no_change_copy\" is " "specified, but size does not match\n")); exit(ITMC_STATUS_BT); } put_dense_encoding_default( table, byte_seq_min, byte_seq_max, byte_seq_def, resultlen - 1, 0, 0); free(byte_seq_def); } else if (0 == sub_hdr->default_error) { if (default_data->size <= (sizeof (itm_place_t))) { for (i = 0, j = 0; i < (entry_num + 1); /* 1:default data */ i++, j += resultlen) { (void) memcpy(table + j + (resultlen - default_data->size), (void *)(&(default_data->place.itm_64d)), default_data->size); } } else { for (i = 0, j = 0; i < (entry_num + 1); /* 1:default data */ i++, j += resultlen) { (void) memcpy(table + j + (resultlen - default_data->size), (void *)(default_data->place.itm_ptr), default_data->size); } } } if (1 == sub_hdr->default_error) { (void) memset(table + (resultlen * entry_num), 1, entry_num); error_table = (table + (resultlen * entry_num)); for (i = 0; i < num; i++) { if (0 == (*(tpp + i))->data1.size) { continue; /* error sequence */ } j = hash_dense_encoding(NSPTR(&((*(tpp + i))->data0)), (*(tpp + i))->data0.size, byte_seq_min, byte_seq_max); k = ((*(tpp + i))->range.size) == 0 ? j : hash_dense_encoding(NSPTR(&((*(tpp + i))->range)), (*(tpp + i))->data0.size, byte_seq_min, byte_seq_max); for (; j <= k; j++) { *(error_table + j) = 0; } } } else if (0 < error_count) { error_table = (table + (resultlen * entry_num)); if (0 == sub_hdr->default_error) { error_table += resultlen; } (void) memset(error_table, 0, entry_num); for (i = 0; i < num; i++) { if (0 == (*(tpp + i))->data1.size) { j = hash_dense_encoding( NSPTR(&((*(tpp + i))->data0)), (*(tpp + i))->data0.size, byte_seq_min, byte_seq_max); k = ((*(tpp + i))->range.size) == 0 ? j : hash_dense_encoding( NSPTR(&((*(tpp + i))->range)), (*(tpp + i))->data0.size, byte_seq_min, byte_seq_max); for (; j <= k; j++) { *(error_table + j) = 1; /* specified */ } } } } p = malloc_vital(resultlen); for (i = 0; i < num; i++) { j = hash_dense_encoding(NSPTR(&((*(tpp + i))->data0)), (*(tpp + i))->data0.size, byte_seq_min, byte_seq_max); if (0 != (*(tpp + i))->range.size) k = hash_dense_encoding( NSPTR(&((*(tpp + i))->range)), (*(tpp + i))->range.size, byte_seq_min, byte_seq_max); else k = j; (void) memset(p, 0, (resultlen - (*(tpp + i))->data1.size)); (void) memcpy(p + (resultlen - (*(tpp + i))->data1.size), ((caddr_t)NSPTR(&((*(tpp + i))->data1))), (*(tpp + i))->data1.size); map_range_make_result(table, j, k, p, resultlen); } free(p); return (header); } static void put_dense_encoding_default( char *table, unsigned char *byte_seq_min, unsigned char *byte_seq_max, unsigned char *byte_seq_def, long pos_max, long position, long dense_encoded_value) { uchar_t i; if (position < pos_max) { for (i = *(byte_seq_min + position); i <= *(byte_seq_max + position); i++) { *(byte_seq_def + position) = i; put_dense_encoding_default( table, byte_seq_min, byte_seq_max, byte_seq_def, pos_max, position + 1, ((dense_encoded_value + i) * (*(byte_seq_max + position) - *(byte_seq_min + position) + 1))); } return; } for (i = *(byte_seq_min + position); i <= *(byte_seq_max + position); i++) { *(byte_seq_def + position) = i; (void) memcpy(table + ((pos_max + 1) * (dense_encoded_value + i - 1)), byte_seq_def, pos_max + 1); } } char * dense_enc_index_to_byte_seq( long value, long length, unsigned char *byte_seq_min, unsigned char *byte_seq_max) { static char *buf; static long buf_len; char *p; int i; int l; int residue; if (buf_len < (2 + (length * 2) + 1)) { free(buf); buf_len = (2 + (length * 2) + 1) + 16; buf = malloc_vital(buf_len); } *(buf + (length * 2)) = '\0'; *(buf + 0) = '0'; *(buf + 1) = 'x'; p = buf + 2; for (i = length - 1; 0 <= i; --i) { residue = value % (*(byte_seq_max + i) - *(byte_seq_min + i) + 1); value /= (*(byte_seq_max + i) - *(byte_seq_min + i) + 1); residue += *(byte_seq_min + i); l = ((0xf0 & residue) >> 4); if (l < 10) { *(p + (i * 2)) = ('0' + l); } else { *(p + (i * 2)) = ('a' + l - 10); } l = (0x0f & residue); if (l < 10) { *(p + (i * 2) + 1) = ('0' + l); } else { *(p + (i * 2) + 1) = ('a' + l - 10); } } return (buf); } itm_tbl_hdr_t * map_table_lookup_var() { itm_error(gettext( "length of all source sequences must be the same\n")); error_deferred += 1; return (NULL); } static void map_range_adjust_byte_seq( unsigned char *byte_seq_min, unsigned char *byte_seq_max, long source_len, itmc_data_pair_t *pair) { unsigned char *p, *p2; int i; int flag; p = (unsigned char *)(NSPTR(&((pair)->data0))); p2 = (unsigned char *)(NSPTR(&((pair)->range))); flag = 0; for (i = 0; i < source_len; i++) { if (flag != 0) { break; } if (*(p + i) != *(p2 + i)) flag = 1; if (*(p + i) < *(byte_seq_min + i)) { *(byte_seq_min + i) = *(p + i); } if (*(byte_seq_max + i) < *(p2 + i)) { *(byte_seq_max + i) = *(p2 + i); } } for (; i < source_len; i++) { *(byte_seq_min + i) = 0x00; *(byte_seq_max + i) = 0xff; } } /* * result value + (source range value - source base value) * and just caluculate its length */ static size_t map_table_resultlen(itmc_map_t *ml) { size_t j; size_t len; int m; uchar_t *c1; uchar_t *c2; uchar_t *c3; j = ml->data_pair.data0.size; if (j < ml->data_pair.data1.size) j = ml->data_pair.data1.size; if (j < ml->data_pair.range.size) j = ml->data_pair.range.size; c1 = (uchar_t *)(NSPTR(&((ml->data_pair).data0))) + ml->data_pair.data0.size - 1; c2 = (uchar_t *)(NSPTR(&((ml->data_pair).data1))) + ml->data_pair.data1.size - 1; c3 = (uchar_t *)(NSPTR(&((ml->data_pair.range)))) + ml->data_pair.range.size - 1; m = 0; for (len = 0; len < j; len++, c1--, c2--, c3--) { if (len < ml->data_pair.data0.size) m -= *c1; if (len < ml->data_pair.data1.size) m += *c2; if (len < ml->data_pair.range.size) m += *c3; m >>= 8; } if (m > 0) { len += 1; } TRACE_MESSAGE('g', ("map_table_resutlen: source(0x%s..0x%s), " "result(0x%s.... len= %ld)\n", data_to_hexadecimal(&(ml->data_pair.data0)), data_to_hexadecimal(&(ml->data_pair.range)), data_to_hexadecimal(&(ml->data_pair.data1)), len)); return (len); } /* * */ static void map_range_make_result( char *table, itm_size_t range_start, itm_size_t range_end, char *result_data, itm_size_t result_size) { itm_size_t i; itm_size_t j; itm_size_t p; uchar_t *dp; /* unsigned for ++ operation */ for (i = range_start, p = i * result_size; i <= range_end; i++, p += result_size) { (void) memcpy(table + p, result_data, result_size); for (j = 0, dp = (uchar_t *)(result_data + result_size - 1); j < result_size; j++, dp--) { if (0xff != *dp) { (*dp) += 1; for (++dp; j > 0; j--, dp++) { (*dp) = 0x00; } break; } } } } /* * */ static size_t map_table_num_range(itmc_data_pair_t *pair) { size_t i, j; itm_num_t num; itm_num_t num2; uchar_t *c1; uchar_t *c2; assert(0 < pair->range.size); j = pair->data0.size; if (j < pair->range.size) j = pair->range.size; c1 = ((uchar_t *)(NSPTR(&(pair->data0)))) + pair->data0.size - 1; c2 = ((uchar_t *)(NSPTR(&(pair->range)))) + pair->range.size - 1; num = 0; for (i = 0; i < j; i++, c1--, c2--) { if (i < pair->range.size) num2 = *c2; if (i < pair->data0.size) num2 -= *c1; TRACE_MESSAGE('G', (" num += %d(=%d-%d)\n ", *c2 - *c1, *c2, *c1)); num2 <<= (i*8); num += num2; } TRACE_MESSAGE('g', ("map_table_num_range: source(0x%s..0x%s), " "num= %ld\n", data_to_hexadecimal(&(pair->data0)), data_to_hexadecimal(&(pair->range)), num)); return (num); } /* * */ itmc_map_t * map_list_append(itmc_map_t *map_list, itmc_map_t *map_pair) { if (0 == map_pair) { return (map_list); } map_pair->next = NULL; map_pair->last = map_pair; if (map_list) { map_list->last->next = map_pair; map_list->last = map_pair; return (map_list); } else { return (map_pair); } } itmc_obj_t * op_self(itm_op_type_t type) { return (op_unit(type, NULL, 0, NULL, 0, NULL, 0)); } itmc_obj_t * op_unary(itm_op_type_t type, void *data, size_t data_size) { return (op_unit(type, data, data_size, NULL, 0, NULL, 0)); } itmc_obj_t * op_unit(itm_op_type_t type, void *data0, size_t data0_size, void *data1, size_t data1_size, void *data2, size_t data2_size) { itm_op_t *op; itmc_obj_t *obj; op = malloc_vital(sizeof (itm_op_t)); op->type = type; op->data.operand[0].itm_ptr = (itm_place2_t)(data0); op->data.operand[1].itm_ptr = (itm_place2_t)(data1); op->data.operand[2].itm_ptr = (itm_place2_t)(data2); obj = malloc_vital(sizeof (itmc_obj_t)); obj->type = ITMC_OBJ_OP; obj->name = NULL; obj->obj = op; obj->ref[0] = obj->ref[1] = obj->ref[2] = NULL; if (NULL != data0) { obj->ref[0] = obj_register(ITMC_OBJ_EXPR, NULL, data0, data0_size, &(op->data.operand[0]), OBJ_REG_TAIL); } if (NULL != data1) { obj->ref[1] = obj_register(ITMC_OBJ_EXPR, NULL, data1, data1_size, &(op->data.operand[1]), OBJ_REG_TAIL); } if (NULL != data2) { obj->ref[2] = obj_register(ITMC_OBJ_EXPR, NULL, data2, data2_size, &(op->data.operand[2]), OBJ_REG_TAIL); } obj->next = NULL; obj->last = NULL; return (obj); } itmc_obj_t * op_self_num(itm_op_type_t type, itm_num_t data) { itm_op_t *op; itmc_obj_t *obj; op = malloc_vital(sizeof (itm_op_t)); op->type = type; op->data.itm_opnum = data; #if !defined(_LP64) op->data.itm_oppad = (data < 0) ? (pad_t)(~0) : 0; #endif obj = malloc_vital(sizeof (itmc_obj_t)); obj->type = ITMC_OBJ_OP; obj->name = NULL; obj->obj = op; obj->ref[0] = obj->ref[1] = obj->ref[2] = NULL; return (obj); } itm_expr_t * expr_self_num(itm_expr_type_t type, itm_num_t data) { itm_expr_t *expr; expr = malloc_vital(sizeof (itm_expr_t)); expr->type = type; expr->data.itm_exnum = data; #if !defined(_LP64) expr->data.itm_expad = (data < 0) ? (pad_t)(~0) : 0; #endif return (expr); } itm_expr_t * expr_self(itm_expr_type_t type, itm_data_t *data) { itm_expr_t *expr; itmc_name_t *name; expr = malloc_vital(sizeof (itm_expr_t)); expr->type = type; if (NULL == data) { expr->data.value.size = 0; expr->data.value.place.itm_ptr = 0; } else { expr->data.value = *(data); } switch (type) { case ITM_EXPR_NAME: /* register */ name = name_lookup(data, ITMC_OBJ_REGISTER); if (&name_lookup_error == name) { return (NULL); } else if (NULL == name) { if (reg_id >= MAXREGID) { itm_error( gettext( "more than %d variables are used\n"), MAXREGID); exit(ITMC_STATUS_BT2); } name = name_register(data, ITMC_OBJ_REGISTER, NULL); name->reg_id = (reg_id++); } expr->type = ITM_EXPR_REG; expr->data.itm_exnum = name->reg_id; #if !defined(_LP64) expr->data.itm_expad = (expr->data.itm_exnum < 0) ? (pad_t)(~0) : 0; #endif break; case ITM_EXPR_SEQ: if ((sizeof (itm_place_t)) < data->size) { (void) obj_register(ITMC_OBJ_DATA, NULL, (void *)(data->place.itm_ptr), data->size, &(expr->data.value.place), OBJ_REG_TAIL); } break; } return (expr); } itm_expr_t * expr_unary(itm_expr_type_t type, itm_expr_t *data0) { itm_expr_t *expr; expr = malloc_vital(sizeof (itm_expr_t)); expr->type = type; expr->data.operand[0].itm_ptr = (itm_place2_t)(data0); (void) obj_register(ITMC_OBJ_EXPR, NULL, data0, sizeof (itm_expr_t), &(expr->data.operand[0]), OBJ_REG_TAIL); return (expr); } itm_expr_t * expr_binary(itm_expr_type_t type, itm_expr_t *data0, itm_expr_t *data1) { itm_expr_t *expr; itm_num_t num; unsigned char *p; int i; expr = malloc_vital(sizeof (itm_expr_t)); expr->type = type; if (ITM_EXPR_SEQ == data0->type) { p = (unsigned char *)NSPTR(&(data0->data.value)); for (i = 0, num = 0; i < data0->data.value.size; i++, p++) { num = ((num << 8) | *p); } data0 = expr_self_num(ITM_EXPR_INT, num); } if (ITM_EXPR_SEQ == data1->type) { p = (unsigned char *)NSPTR(&(data1->data.value)); for (i = 0, num = 0; i < data1->data.value.size; i++, p++) { num = ((num << 8) | *p); } data1 = expr_self_num(ITM_EXPR_INT, num); } expr->data.operand[0].itm_ptr = (itm_place2_t)(data0); expr->data.operand[1].itm_ptr = (itm_place2_t)(data1); (void) obj_register(ITMC_OBJ_EXPR, NULL, data0, sizeof (itm_expr_t), &(expr->data.operand[0]), OBJ_REG_TAIL); (void) obj_register(ITMC_OBJ_EXPR, NULL, data1, sizeof (itm_expr_t), &(expr->data.operand[1]), OBJ_REG_TAIL); return (expr); } itm_expr_t * expr_binary2(itm_expr_type_t type, itm_expr_t *data0, itm_expr_t *data1) { itm_expr_t *expr; itm_num_t num; unsigned char *p; int i; if ((NULL == data0) || (NULL == data1)) { return (NULL); } expr = malloc_vital(sizeof (itm_expr_t)); expr->type = type; switch (data0->type) { case ITM_EXPR_SEQ: p = (unsigned char *)NSPTR(&(data0->data.value)); for (i = 0, num = 0; i < data0->data.value.size; i++, p++) { num = ((num << 8) | *p); } data0 = expr_self_num(ITM_EXPR_INT, num); expr->data.operand[0].itm_ptr = (itm_place2_t)(data0); (void) obj_register(ITMC_OBJ_EXPR, NULL, data0, sizeof (itm_expr_t), &(expr->data.operand[0]), OBJ_REG_TAIL); break; case ITM_EXPR_INT: case ITM_EXPR_REG: case ITM_EXPR_IN_VECTOR_D: expr->data.operand[0] = data0->data.operand[0]; break; default: expr->data.operand[0].itm_ptr = (itm_place2_t)(data0); (void) obj_register(ITMC_OBJ_EXPR, NULL, data0, sizeof (itm_expr_t), &(expr->data.operand[0]), OBJ_REG_TAIL); break; } switch (data1->type) { case ITM_EXPR_SEQ: p = (unsigned char *)NSPTR(&(data1->data.value)); for (i = 0, num = 0; i < data1->data.value.size; i++, p++) { num = ((num << 8) | *p); } data1 = expr_self_num(ITM_EXPR_INT, num); expr->data.operand[1].itm_ptr = (itm_place2_t)(data1); (void) obj_register(ITMC_OBJ_EXPR, NULL, data1, sizeof (itm_expr_t), &(expr->data.operand[1]), OBJ_REG_TAIL); break; case ITM_EXPR_INT: case ITM_EXPR_REG: case ITM_EXPR_IN_VECTOR_D: expr->data.operand[1] = data1->data.operand[0]; break; default: expr->data.operand[1].itm_ptr = (itm_place2_t)(data1); (void) obj_register(ITMC_OBJ_EXPR, NULL, data1, sizeof (itm_expr_t), &(expr->data.operand[1]), OBJ_REG_TAIL); break; } return (expr); } itm_expr_t * expr_assign(itm_expr_type_t type, itm_data_t *data0, itm_expr_t *data1) { itm_expr_t *expr; itmc_name_t *name; expr = malloc_vital(sizeof (itm_expr_t)); expr->type = type; expr->data.operand[1].itm_ptr = (itm_place2_t)(data1); name = name_lookup(data0, ITMC_OBJ_REGISTER); if (&name_lookup_error == name) { free(expr); exit(ITMC_STATUS_BT); } else if (NULL == name) { name = name_register(data0, ITMC_OBJ_REGISTER, NULL); name->reg_id = (reg_id++); } expr->data.operand[0].itm_ptr = name->reg_id; (void) obj_register(ITMC_OBJ_EXPR, NULL, data1, sizeof (itm_expr_t), &(expr->data.operand[1]), OBJ_REG_TAIL); return (expr); } itm_expr_t * expr_seq_to_int(itm_expr_t *expr) { itm_num_t num; unsigned char *p; int i; if (ITM_EXPR_SEQ == expr->type) { if ((sizeof (itm_place_t)) < expr->data.value.size) { p = (unsigned char *)(expr->data.value.place.itm_ptr); } else { p = (unsigned char *)&(expr->data.value.place.itm_64d); } for (i = 0, num = 0; i < expr->data.value.size; i++, p++) { num = ((num << 8) | *p); } free(expr); expr = expr_self_num(ITM_EXPR_INT, num); } return (expr); } itmc_name_t * name_lookup(itm_data_t *name, itm_type_t type) { itmc_name_t *p; TRACE_MESSAGE('N', ("name_lookup\t: \"%-16s\" %2ld %2ld %2ld\n", name_to_str(name), name->size, type, name_id)); if (0 == name->size) return (NULL); for (p = name_first; p; p = p->next) { if ((name->size != p->name.size) || (memcmp(NSPTR(name), NSPTR(&(p->name)), name->size))) { continue; } if ((type != p->type) && (((ITMC_OBJ_ACTION != type) && (ITMC_OBJ_ACTION != p->type)) || ((ITMC_OBJ_ACTION == type) && (ITMC_OBJ_DIREC != p->type) && (ITMC_OBJ_OP != p->type) && (ITMC_OBJ_MAP != p->type)) || ((ITMC_OBJ_ACTION == p->type) && (ITMC_OBJ_DIREC != type) && (ITMC_OBJ_OP != type) && (ITMC_OBJ_MAP != type)))) { itm_error( gettext("name type conflict: \"%1$s\" " "%2$s %3$s\n"), name_to_str(name), itm_name_type_name[type], itm_name_type_name[p->type]); error_deferred += 1; return (&name_lookup_error); } else { return (p); } } return (NULL); } itmc_name_t * name_refer(itm_data_t *name, itm_type_t type, itmc_ref_t *refp) { itmc_name_t *p; itmc_ref_link_t *rl; p = name_lookup(name, type); TRACE_MESSAGE('N', ("name_refer\t: \"%-16s\" %2ld %2ld %08p %2d %08p\n", name_to_str(name), name->size, type, refp, name_id, p)); if (&name_lookup_error == p) { return (NULL); } rl = malloc_vital(sizeof (itmc_ref_link_t)); rl->ref = refp; rl->next = NULL; if (NULL != p) { if (p->ref_last) { p->ref_last->next = rl; } else { p->ref_first = rl; } p->ref_last = rl; } else { p = malloc_vital(sizeof (itmc_name_t)); p->id = (name_id++); p->reg_id = 0; p->name = *name; p->type = type; #if !defined(_LP64) p->reloc.itm_pad = 0; #endif p->reloc.itm_ptr = 0; p->ref_first = rl; p->ref_last = rl; p->next = NULL; if (name_last) { name_last->next = p; } else { name_first = p; } name_last = p; } return (p); } itmc_name_t * name_register(itm_data_t *name, itm_type_t type, itmc_ref_t *refp) { itmc_name_t *p; TRACE_MESSAGE('N', ("name_register\t: \"%-16s\" %2ld %2ld %08p %2ld\n", name_to_str(name), name->size, type, refp, name_id)); p = name_lookup(name, type); if (&name_lookup_error == p) { return (NULL); } if (NULL != p) { if (NULL != p->object) { itm_error(gettext( "same names are specified: %1$s\n"), name_to_str(name)); error_deferred += 1; return (NULL); } p->object = refp; } else { p = malloc_vital(sizeof (itmc_name_t)); p->id = (name_id++); p->reg_id = 0; p->name = *name; p->type = type; p->object = refp; p->reloc.itm_ptr = 0; #if !defined(_LP64) p->reloc.itm_pad = 0; #endif p->ref_first = NULL; p->ref_last = NULL; p->next = NULL; if (name_last) { name_last->next = p; } else { name_first = p; } name_last = p; } return (p); } int data_compare(const itm_data_t *d0, const itm_data_t *d1) { if (d0->size < d1->size) { if (memcmp(NSPTR(d0), NSPTR(d1), d0->size) < 0) { return (-1); } else { return (1); } } else if (d0->size == d1->size) { return (memcmp(NSPTR(d0), NSPTR(d1), d0->size)); } else /* (d0->size > d1->size) */ { if (memcmp(NSPTR(d0), NSPTR(d1), d1->size) <= 0) { return (-1); } else { return (1); } } } int data_pair_compare(itmc_data_pair_t **p0, itmc_data_pair_t **p1) { int r; itm_data_t *d0; itm_data_t *d1; uchar_t *c0; uchar_t *c1; size_t s; int i; d0 = &((*p0)->data0); d1 = &((*p1)->data0); c0 = NSPTR(d0); c1 = NSPTR(d1); if (d0->size == d1->size) { s = d0->size; } else if (d0->size < d1->size) { s = d1->size - d0->size; for (i = 0; i < s; i++, c1++) { if (0x00 != *c1) { return (-1); } } s = d0->size; } else { assert(d0->size > d1->size); s = d0->size - d1->size; for (i = 0; i < s; i++, c0++) { if (0x00 != *c0) { return (1); } } s = d1->size; } r = memcmp(c0, c1, s); if (0 == r) { itm_data_t *d; if (c0 == NSPTR(d0)) { d = d0; } else { assert(c1 == NSPTR(d0)); d = d1; } itm_error(gettext( "distinct source values are specified: 0x%1$s\n"), data_to_hexadecimal(d)); error_deferred += 1; } return (r); } static long data_to_long(itm_data_t *data) { long l; int i; unsigned char *p; if ((sizeof (itm_place_t)) < data->size) { return (0); } for (l = 0, i = 0, p = (unsigned char *)&(data->place); i < data->size; i++, p++) { l <<= 8; l |= *p; } return (l); }