xref: /titanic_51/usr/src/cmd/geniconvtbl/geniconvtbl.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1999, 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <strings.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/mman.h>
38 #include <synch.h>
39 
40 #if defined(DEBUG)
41 #include <stdarg.h>
42 #endif /* !DEBUG */
43 
44 #include "iconv_tm.h"
45 #include "hash.h"
46 
47 
48 /*
49  * Debug
50  */
51 #if defined(DEBUG)
52 
53 static void	trace_init(void);
54 static void	trace_message(char *, ...);
55 
56 static char	trace_option[128];
57 
58 #define	TRACE(c)		(*(trace_option + (c & 0x007f)))
59 #define	TRACE_MESSAGE(c, args)	((TRACE(c))? trace_message args: (void)0)
60 
61 #else /* !DEBUG */
62 
63 #define	trace_init()
64 #define	TRACE()
65 #define	TRACE_MESSAGE(c, args)
66 
67 #endif /* !DEBUG */
68 
69 
70 /*
71  * ITM reference information
72  */
73 typedef struct _itm_ref {
74 	char		*name;		/* ITM file name */
75 	itm_hdr_t	*hdr;		/* address of ITM */
76 	size_t		len;		/* length of ITM */
77 } itm_ref_t;
78 
79 
80 /*
81  * struct _icv_state; to keep status
82  */
83 typedef struct _icv_state {
84 	struct _itm_ref	*itm;		/* reference to ITM */
85 	itm_hdr_t	*itm_hdr;	/* address of ITM */
86 	itm_tbl_hdr_t	*direc;		/* current direction */
87 	itm_place_t	default_action;	/* default action */
88 	itm_num_t	*regs;		/* register */
89 	itm_num_t	reg_num;	/* number of register */
90 #if defined(OP_DEPTH_MAX)
91 	int		op_depth;	/* depth of operation */
92 #endif /* OP_DEPTH_MAX */
93 } icv_state_t;
94 
95 
96 /*
97  * function prototype
98  */
99 void *	_icv_open(const char *);
100 void	_icv_close(icv_state_t *);
101 size_t	_icv_iconv(icv_state_t *, const unsigned char **,
102 		    size_t *, unsigned char **, size_t *);
103 
104 static size_t	map_i_f(itm_tbl_hdr_t *,
105 			const unsigned char **, size_t *,
106 			unsigned char **, size_t *, long);
107 static size_t	map_l_f(itm_tbl_hdr_t *,
108 			const unsigned char **, size_t *,
109 			unsigned char **, size_t *, long);
110 static size_t	map_h_l(itm_tbl_hdr_t *,
111 			const unsigned char **, size_t *,
112 			unsigned char **, size_t *, long);
113 static size_t	map_d_e_l(itm_tbl_hdr_t *,
114 			const unsigned char **, size_t *,
115 			unsigned char **, size_t *, long);
116 static size_t	eval_cond_tbl(icv_state_t *, itm_place_t,
117 			const unsigned char **, size_t *,
118 			size_t, itm_direc_t *);
119 static size_t	eval_op_tbl(icv_state_t *, itm_place_t,
120 			const unsigned char **, size_t *,
121 			unsigned char **, size_t *);
122 static size_t	eval_op(icv_state_t *, itm_place2_t,
123 			const unsigned char **, size_t *,
124 			unsigned char **, size_t *);
125 
126 static itm_num_t	eval_expr(icv_state_t *, itm_place_t,
127 				size_t, const unsigned char *, size_t);
128 
129 static void		itm_ref_free(int, void *, void *, void *, size_t);
130 static itm_ref_t	*itm_ref_inc(const char *);
131 static void		itm_ref_dec(itm_ref_t *);
132 
133 static void		op_init_default(icv_state_t *);
134 static void		op_reset_default(icv_state_t *);
135 static void		regs_init(icv_state_t *);
136 
137 
138 /*
139  * macro definition
140  */
141 
142 #define	ADDR(place)	((void *)(((char *)(ist->itm_hdr)) +\
143 				((itm_place2_t)(place.itm_ptr))))
144 #define	ADDR2(place2)	((void *)(((char *)(ist->itm_hdr)) +\
145 				((itm_place2_t)(place2))))
146 #define	DADDR(n)	(((n)->size <= (sizeof ((n)->place.itm_64d))) ?	\
147 				((unsigned char *)(&((n)->place.itm_64d))) :\
148 				((unsigned char *)(ADDR((n)->place))))
149 
150 #define	REG(n)		(*(ist->regs + (n)))
151 #define	DISCARD(c)	(((*inbuf) = (void *)((*inbuf) + (c))),\
152 			((*inbytesleft) -= (c)))
153 #define	GET(c)		((c) = **inbuf, (*inbuf)++, (*inbytesleft)--)
154 #define	PUT(c)		(**outbuf = (c), (*outbuf)++, (*outbytesleft)--)
155 
156 #define	RETVALERR	((size_t)(-1))
157 #define	RETVALDIR	((size_t)(-2))
158 #define	RETVALBRK	((size_t)(-3))
159 #define	RETVALRET	((size_t)(-4))
160 
161 #define	UPDATE_ARGS()	(*inbuf = ip, \
162 			 *inbytesleft = ileft, \
163 			 *outbuf = op, \
164 			 *outbytesleft = oleft)
165 
166 /*
167  * Open; called from iconv_open()
168  */
169 void *
170 _icv_open(const char	*itm)
171 {
172 	icv_state_t	*ist;
173 	itm_hdr_t	*hdr;
174 	itm_ref_t	*itm_ref;
175 	int		r;
176 
177 	/*
178 	 * for debug
179 	 */
180 	trace_init();
181 
182 	/*
183 	 * _icv_open() primaty task
184 	 */
185 	itm_ref = itm_ref_inc(itm);
186 	if (NULL == itm_ref) {
187 		return ((void *)(-1));
188 	}
189 
190 	if (NULL == (ist = malloc(sizeof (icv_state_t)))) {
191 		r = errno;
192 		itm_ref_dec(itm_ref);
193 		errno = r;
194 		return	(NULL);
195 	}
196 
197 	ist->itm = itm_ref;
198 	ist->itm_hdr = ist->itm->hdr;
199 	ist->reg_num = ist->itm->hdr->reg_num;
200 
201 	hdr =  ist->itm->hdr;
202 	ist->direc = ADDR(hdr->direc_init_tbl);
203 	ist->default_action.itm_64d = 0;
204 #if defined(OP_DEPTH_MAX)
205 	ist->op_depth = 0;
206 #endif /* OP_DEPTH_MAX */
207 
208 
209 	/*
210 	 * brief sanity check
211 	 */
212 	if (hdr->itm_size.itm_ptr <= hdr->direc_init_tbl.itm_ptr) {
213 		_icv_close(ist);
214 		errno = ELIBBAD;
215 		return ((void *)(-1));
216 	}
217 
218 
219 	/* allocate register region */
220 	if (hdr->reg_num <= 0) {
221 		ist->regs = NULL;
222 	} else {
223 		ist->regs = malloc((sizeof (itm_num_t)) * hdr->reg_num);
224 		if (NULL == ist->regs) {
225 			r = errno;
226 			_icv_close(ist);
227 			errno = r;
228 			return ((void *)(-1));
229 		}
230 		(void) memset(ist->regs, 0,
231 			(sizeof (itm_num_t)) * hdr->reg_num);
232 	}
233 
234 
235 	/* evaluate init operation */
236 	if (0 != ist->itm_hdr->op_init_tbl.itm_ptr) {
237 		const unsigned char	*ip = NULL;
238 		size_t			ileft = 0;
239 		unsigned char		*op = NULL;
240 		size_t			oleft = 0;
241 		(void) eval_op_tbl(ist,
242 			    ist->itm_hdr->op_init_tbl,
243 			    &ip,
244 			    &ileft,
245 			    &op, &oleft);
246 	} else {
247 		op_init_default(ist);
248 	}
249 
250 	return	(ist);
251 }
252 
253 
254 /*
255  * Close; called from iconv_close
256  */
257 void
258 _icv_close(icv_state_t		*ist)
259 {
260 	if (NULL == ist) {
261 		errno = EBADF;
262 		return;
263 	}
264 	itm_ref_dec(ist->itm);
265 	free(ist->regs);
266 	free(ist);
267 }
268 
269 
270 /*
271  * Actual conversion; called from iconv()
272  */
273 size_t
274 _icv_iconv(
275 	icv_state_t		*ist,
276 	const unsigned char	**inbuf,
277 	size_t			*inbytesleft,
278 	unsigned char		**outbuf,
279 	size_t			*outbytesleft)
280 {
281 	size_t			retval;
282 	itm_hdr_t		*hdr;
283 	itm_type_t		type;
284 	const unsigned char	*ip;
285 	size_t			ileft;
286 	itm_place_t		action;
287 
288 	if (NULL == ist) {
289 		errno = EBADF;
290 		TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n", errno));
291 		return ((size_t)(-1));
292 	}
293 	if (NULL == inbuf) {
294 		ip = NULL;
295 		inbuf = &ip;
296 	}
297 	if (NULL == inbytesleft) {
298 		ileft = 0;
299 		inbytesleft = &ileft;
300 	}
301 
302 	hdr = ist->itm_hdr;
303 
304 	retval = 0;
305 
306 	TRACE_MESSAGE('i', ("_icv_iconv(inbuf=%p inbytesleft=%ld "
307 			    "outbuf=%p outbytesleft=%ld)\n",
308 			    (NULL == inbuf) ? 0 : *inbuf,
309 			    (NULL == inbytesleft) ? 0 : *inbytesleft,
310 			    (NULL == outbuf) ? 0 : *outbuf,
311 			    (NULL == outbytesleft) ? 0 : *outbytesleft));
312 
313 	/*
314 	 * If (NULL == inbuf || NULL == *inbuf) then this conversion is
315 	 * placed into initial state.
316 	 */
317 	if ((NULL == inbuf) || (NULL == *inbuf)) {
318 		if (0 != hdr->op_reset_tbl.itm_ptr) {
319 			ist->direc = ADDR(hdr->direc_init_tbl);
320 			retval = eval_op_tbl(ist,
321 						hdr->op_reset_tbl,
322 						inbuf, inbytesleft,
323 						outbuf, outbytesleft);
324 			if ((size_t)(-1) == retval) {
325 				return	(retval);
326 			}
327 		} else {
328 			op_reset_default(ist);
329 		}
330 		return ((size_t)(0));
331 	}
332 
333 	if (ITM_TBL_MAP_INDEX_FIXED_1_1 == ist->direc->type) {
334 		itm_map_idx_fix_hdr_t	*map_hdr;
335 		char			*map;
336 		const unsigned char	*ip;
337 		size_t			ileft;
338 		unsigned char		*op;
339 		size_t			oleft;
340 
341 		map_hdr = (itm_map_idx_fix_hdr_t *)(ist->direc + 1);
342 		map = (char *)(map_hdr + 1);
343 
344 		if (1 == map_hdr->default_error) {
345 			retval = map_i_f(ist->direc,
346 					inbuf, inbytesleft,
347 					outbuf, outbytesleft, 0);
348 			return	(retval);
349 		}
350 
351 		ip = *inbuf;
352 		ileft = *inbytesleft;
353 		op = *outbuf;
354 		oleft = *outbytesleft;
355 
356 		while (1 <= ileft) {
357 			if (oleft < 1) {
358 				UPDATE_ARGS();
359 				errno = E2BIG;
360 				TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n",
361 						errno));
362 				return ((size_t)-1);
363 			}
364 			*(op++) = *(map + *(ip++));
365 			ileft--;
366 			oleft--;
367 
368 		}
369 		UPDATE_ARGS();
370 		return (0);
371 	} else if (ITM_TBL_MAP_INDEX_FIXED == ist->direc->type) {
372 		retval = map_i_f(ist->direc,
373 				inbuf, inbytesleft,
374 				outbuf, outbytesleft, 0);
375 		return	(retval);
376 	} else if (ITM_TBL_MAP_HASH == ist->direc->type) {
377 		retval = map_h_l(ist->direc,
378 				inbuf, inbytesleft,
379 				outbuf, outbytesleft, 0);
380 		return	(retval);
381 	} else if (ITM_TBL_MAP_DENSE_ENC == ist->direc->type) {
382 		retval = map_d_e_l(ist->direc,
383 				inbuf, inbytesleft,
384 				outbuf, outbytesleft, 0);
385 		return	(retval);
386 	} else if (ITM_TBL_MAP_LOOKUP == ist->direc->type) {
387 		retval = map_l_f(ist->direc,
388 				inbuf, inbytesleft,
389 				outbuf, outbytesleft, 0);
390 		return	(retval);
391 	}
392 
393 #if defined(OP_DEPTH_MAX)
394 	ist->op_depth = 0;
395 #endif /* OP_DEPTH_MAX */
396 
397 
398 	/*
399 	 * Main loop; basically 1 loop per 1 output character
400 	 */
401 retry_cond_eval:
402 	while (0 < *inbytesleft) {
403 		itm_tbl_hdr_t	*direc_hdr;
404 		itm_direc_t	*direc;
405 		long		i;
406 
407 		direc_hdr = ist->direc;
408 		direc = (itm_direc_t *)(ist->direc + 1);
409 		for (i = 0; /* NULL */; i++, direc++) {
410 			if (i >= direc_hdr->number) {
411 				if (0 == ist->default_action.itm_ptr) {
412 					errno = EILSEQ;
413 					TRACE_MESSAGE('e',
414 						("_icv_iconv:error=%d\n",
415 						errno));
416 					return ((size_t)(-1));
417 				}
418 
419 
420 
421 				action = ist->default_action;
422 				type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
423 				TRACE_MESSAGE('E',
424 				("escape seq (default action=%6p, type=%ld) "
425 				"excuting\n", action.itm_ptr, type));
426 			} else if (0 != direc->condition.itm_ptr) {
427 				retval = eval_cond_tbl(ist, direc->condition,
428 							inbuf, inbytesleft,
429 							*outbytesleft,
430 							direc);
431 				if ((size_t)(0) == retval) {
432 					continue;
433 				} else if ((size_t)(-1) == retval) {
434 					return	(retval);
435 				} else if ((size_t)(2) == retval) {
436 					goto retry_cond_eval;
437 				}
438 				action = direc->action;
439 				type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
440 			} else {
441 				action = direc->action;
442 				type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
443 			}
444 
445 			TRACE_MESSAGE('a',
446 				("inbytesleft=%ld; type=%ld:action=%p\n",
447 				*inbytesleft, type, action.itm_ptr));
448 			switch (ITM_TBL_MASK & type) {
449 			case ITM_TBL_OP:
450 				retval = eval_op_tbl(ist, action,
451 						inbuf, inbytesleft,
452 						outbuf, outbytesleft);
453 				if ((size_t)(-1) == retval) {
454 					return	(retval);
455 				}
456 				break;
457 			case ITM_TBL_DIREC:
458 				ist->direc = ADDR(action);
459 				break;
460 			case ITM_TBL_MAP:
461 				switch (type) {
462 				case ITM_TBL_MAP_INDEX_FIXED_1_1:
463 				case ITM_TBL_MAP_INDEX_FIXED:
464 					retval = map_i_f(
465 						    ADDR(action),
466 						    inbuf, inbytesleft,
467 						    outbuf, outbytesleft,
468 						    1);
469 					break;
470 				case ITM_TBL_MAP_HASH:
471 					retval = map_h_l(ADDR(action),
472 						    inbuf, inbytesleft,
473 						    outbuf, outbytesleft, 1);
474 					break;
475 				case ITM_TBL_MAP_DENSE_ENC:
476 					retval = map_d_e_l(ADDR(action),
477 						    inbuf, inbytesleft,
478 						    outbuf, outbytesleft, 1);
479 					break;
480 				case ITM_TBL_MAP_LOOKUP:
481 					retval = map_l_f(
482 						    ADDR(action),
483 						    inbuf, inbytesleft,
484 						    outbuf, outbytesleft,
485 						    1);
486 					break;
487 				default:
488 					errno = ELIBBAD;
489 					TRACE_MESSAGE('e',
490 					("_icv_iconv:error=%d\n", errno));
491 					return ((size_t)(-1));
492 
493 				}
494 				if ((size_t)(-1) == retval) {
495 					return	(retval);
496 				}
497 				break;
498 			default:	/* never */
499 				errno = ELIBBAD;
500 				TRACE_MESSAGE('e',
501 				("_icv_iconv:error=%d\n", errno));
502 				return ((size_t)(-1));
503 			}
504 			break;
505 		}
506 	}
507 	return	(retval);
508 }
509 
510 
511 
512 /*
513  * map-indexed-fixed
514  */
515 static size_t
516 map_i_f(
517 	itm_tbl_hdr_t		*tbl_hdr,
518 	const unsigned char	**inbuf,
519 	size_t			*inbytesleft,
520 	unsigned char		**outbuf,
521 	size_t			*outbytesleft,
522 	long			once)
523 {
524 	itm_map_idx_fix_hdr_t	*map_hdr;
525 	long			i;
526 	unsigned char		c;
527 	unsigned long		j;
528 	const unsigned char	*p;
529 
530 	TRACE_MESSAGE('i', ("map_i_f\n"));
531 
532 	map_hdr = (itm_map_idx_fix_hdr_t *)(tbl_hdr + 1);
533 
534 	do {
535 		if (*inbytesleft < map_hdr->source_len) {
536 			errno = EINVAL;
537 			TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
538 			return ((size_t)(-1));
539 		}
540 
541 		j = 0;
542 		for (i = 0; i < map_hdr->source_len; i++) {
543 			GET(c);
544 			j = ((j << 8) | c);
545 		}
546 
547 		if (((j < map_hdr->start.itm_ptr) ||
548 			(map_hdr->end.itm_ptr < j)) &&
549 		    (0 < map_hdr->default_error)) {
550 			errno = EILSEQ;
551 			(*inbuf) = (void*) ((*inbuf) - map_hdr->source_len);
552 			(*inbytesleft) += map_hdr->source_len;
553 			TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
554 			return ((size_t)(-1));
555 		}
556 
557 		if (*outbytesleft < map_hdr->result_len) {
558 			errno = E2BIG;
559 			(*inbuf) = (void *)((*inbuf) - map_hdr->source_len);
560 			(*inbytesleft) += map_hdr->source_len;
561 			TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
562 			return ((size_t)(-1));
563 		}
564 
565 		if ((j < map_hdr->start.itm_ptr) ||
566 			(map_hdr->end.itm_ptr < j)) {
567 			if (0 == map_hdr->default_error) {
568 				p = (((unsigned char *)(map_hdr + 1)) +
569 					(map_hdr->result_len *
570 					(tbl_hdr->number)));
571 				for (i = 0; i < map_hdr->result_len; i++) {
572 					PUT(*(p + i));
573 				}
574 			} else {
575 				p = ((*inbuf) - map_hdr->source_len);
576 				for (i = 0; i < map_hdr->source_len; i++) {
577 					PUT(*(p + i));
578 				}
579 			}
580 		} else {
581 			char	*map_error;
582 			map_error = (((char *)(map_hdr + 1)) +
583 				    (map_hdr->result_len *
584 				    (tbl_hdr->number)) +
585 				    (j - map_hdr->start.itm_ptr));
586 			if (0 == map_hdr->default_error) {
587 				map_error = (void *)
588 					(map_error + map_hdr->result_len);
589 			}
590 			if (((1 == map_hdr->default_error) ||
591 			    (0 < map_hdr->error_num)) &&
592 			    (0 != *(map_error))) {
593 				errno = EILSEQ;
594 				(*inbuf) = (void *)
595 					((*inbuf) - map_hdr->source_len);
596 				(*inbytesleft) += map_hdr->source_len;
597 				TRACE_MESSAGE('e',
598 				("map_i_f:error=%d\n", errno));
599 				return ((size_t)(-1));
600 			}
601 			p = (((unsigned char *)(map_hdr + 1)) +
602 				(map_hdr->result_len *
603 				(j - map_hdr->start.itm_ptr)));
604 			for (i = 0; i < map_hdr->result_len; i++) {
605 				PUT(*(p + i));
606 			}
607 		}
608 	} while ((0 < *inbytesleft) && (0 == once));
609 
610 	return (size_t)(0);
611 }
612 
613 
614 /*
615  * map-lookup-fixed
616  */
617 static size_t
618 map_l_f(
619 	itm_tbl_hdr_t	*tbl_hdr,
620 	const unsigned char	**inbuf,
621 	size_t		*inbytesleft,
622 	unsigned char	**outbuf,
623 	size_t		*outbytesleft,
624 	long		once)
625 {
626 	itm_map_lookup_hdr_t	*map_hdr;
627 	long			i;
628 	unsigned char		*map;
629 	const unsigned char	*p;
630 	long			high;
631 	long			mid;
632 	long			low;
633 	long			result;
634 	itm_size_t		pair_size;
635 
636 	TRACE_MESSAGE('i', ("map_l_f\n"));
637 
638 	map_hdr = (itm_map_lookup_hdr_t *)(tbl_hdr + 1);
639 	map = (unsigned char *)(map_hdr + 1);
640 	pair_size = map_hdr->source_len + 1 + map_hdr->result_len;
641 
642 	do {
643 		if (*inbytesleft < map_hdr->source_len) {
644 			errno = EINVAL;
645 			TRACE_MESSAGE('e', ("map_l_f:error=%d\n", errno));
646 			return ((size_t)(-1));
647 		}
648 
649 		for (low = 0, high = tbl_hdr->number; low < high; ) {
650 			mid = (low + high) / 2;
651 			p = map + (pair_size * mid);
652 			for (i = 0, result = 0; i < map_hdr->source_len;
653 			    i++, p++) {
654 				if (*(unsigned char *)(*inbuf + i) < *p) {
655 					result = -1;
656 					break;
657 				}
658 				if (*p < *(unsigned char *)(*inbuf + i)) {
659 					result = 1;
660 					break;
661 				}
662 			}
663 			if (result < 0) {
664 				high = mid;
665 			} else if (0 < result) {
666 				low = mid + 1;
667 			} else { /* 0 == result */
668 				break;
669 			}
670 		}
671 
672 		if (0 != result) {
673 			if (map_hdr->default_error < 0) {
674 				p = *inbuf;
675 			} else if (0 == map_hdr->default_error) {
676 				p = map + (pair_size * tbl_hdr->number) +
677 					map_hdr->source_len + 1;
678 			} else if (0 < map_hdr->default_error) {
679 				errno = EILSEQ;
680 				TRACE_MESSAGE('e', ("map_l_f:error=%d\n",
681 				errno));
682 				return ((size_t)(-1));
683 			}
684 		} else {
685 			if (0 != (*p)) {
686 				errno = EILSEQ;
687 				TRACE_MESSAGE('e', ("map_l_f:error=%d\n",
688 				errno));
689 				return ((size_t)(-1));
690 			}
691 			p++;
692 		}
693 
694 		if (*outbytesleft < map_hdr->result_len) {
695 			errno = E2BIG;
696 			TRACE_MESSAGE('e', ("map_l_f:error=%d\n", errno));
697 			return ((size_t)(-1));
698 		}
699 		DISCARD(map_hdr->source_len);
700 
701 		for (i = 0; i < map_hdr->result_len; i++) {
702 			PUT(*(p + i));
703 		}
704 	} while ((0 < *inbytesleft) && (0 == once));
705 
706 	return ((size_t)(0));
707 }
708 
709 
710 /*
711  * map-hash-lookup
712  */
713 static size_t
714 map_h_l(
715 	itm_tbl_hdr_t	*tbl_hdr,
716 	const unsigned char	**inbuf,
717 	size_t		*inbytesleft,
718 	unsigned char	**outbuf,
719 	size_t		*outbytesleft,
720 	long		once)
721 {
722 	itm_map_hash_hdr_t	*map_hdr;
723 	long			i;
724 	unsigned char	*map_error;
725 	unsigned char	*map_hash;
726 	unsigned char	*map_of;
727 	const unsigned char	*p;
728 	const unsigned char	*q;
729 	long			high;
730 	long			mid;
731 	long			low;
732 	long			result;
733 	itm_size_t		pair_size;
734 	itm_size_t		hash_value;
735 	itm_size_t		source_len;
736 	itm_size_t		result_len;
737 
738 	TRACE_MESSAGE('i', ("map_hash\n"));
739 
740 	map_hdr = (itm_map_hash_hdr_t *)(tbl_hdr + 1);
741 	map_error = (unsigned char *)(map_hdr + 1);
742 	map_hash = (map_error + map_hdr->hash_tbl_num);
743 	map_of = map_hash + map_hdr->hash_tbl_size;
744 	pair_size = map_hdr->source_len + 1 + map_hdr->result_len;
745 	source_len = map_hdr->source_len;
746 	result_len = map_hdr->result_len;
747 
748 	do {
749 		if (*inbytesleft < source_len) {
750 			errno = EINVAL;
751 			TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno));
752 			return ((size_t)(-1));
753 		}
754 
755 		result = 1;
756 		q = *inbuf;
757 		hash_value = hash((const char *)(q),
758 				source_len, map_hdr->hash_tbl_num);
759 		p = map_hash + (pair_size * hash_value);
760 		if (1 == *(map_error + hash_value)) {
761 			for (i = 0, result = 0; i < source_len; i++) {
762 				if (*(q + i) != *(p++)) {
763 					result = -2;
764 					break;
765 				}
766 			}
767 			TRACE_MESSAGE('G',
768 			("(h=%d): find pair without conflict\n",
769 			hash_value));
770 		} else if (0 == *(map_error + hash_value)) {
771 			TRACE_MESSAGE('G',
772 			("(h=%d): No Pair\n",
773 			hash_value));
774 			result = -3;
775 		} else /* if (0 < *(map_error + hash_value)) */ {
776 			for (i = 0, result = 0; i < source_len; i++) {
777 				if (*(q + i) != *(p++)) {
778 					result = 1;
779 					break;
780 				}
781 			}
782 			if (0 < result) {
783 				for (low = 0, high = map_hdr->hash_of_num;
784 				    low < high; /* NOP */) {
785 					mid = (low + high) / 2;
786 					p = map_of + (pair_size * mid);
787 					for (i = 0, result = 0;
788 					    i < source_len;
789 					    i++, p++) {
790 						if (*(q + i) < *p) {
791 							result = -1;
792 							break;
793 						}
794 						if (*p < *(q + i)) {
795 							result = 1;
796 							break;
797 						}
798 					}
799 					if (result < 0) {
800 						high = mid;
801 					} else if (0 < result) {
802 						low = mid + 1;
803 					} else { /* 0 == result */
804 						TRACE_MESSAGE('G',
805 						("(h=%d): "
806 						"find data on out ot "
807 						"hashtable with CONFLICT\n",
808 						hash_value));
809 						break;
810 					}
811 				}
812 			}
813 		}
814 		if (0 != result) {
815 			if (map_hdr->default_error < 0) {
816 				p = q;
817 			} else if (0 == map_hdr->default_error) {
818 				p = map_of + map_hdr->hash_of_size;
819 			} else if (0 < map_hdr->default_error) {
820 				TRACE_MESSAGE('G',
821 				("(h=%d): NO PAIR\n",
822 				hash_value));
823 				errno = EILSEQ;
824 				TRACE_MESSAGE('e',
825 				("map_h_l:error=%d\n", errno));
826 				return ((size_t)(-1));
827 			}
828 		} else {
829 			if (0 != (*p)) {
830 				errno = EILSEQ;
831 				TRACE_MESSAGE('G',
832 				("	      : error pair\n"));
833 				TRACE_MESSAGE('e', ("map_l_f:error\n",
834 				errno));
835 				return ((size_t)(-1));
836 			}
837 			p++;
838 		}
839 
840 		if (*outbytesleft < result_len) {
841 			errno = E2BIG;
842 			TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno));
843 			return ((size_t)(-1));
844 		}
845 		DISCARD(source_len);
846 
847 		for (i = 0; i < result_len; i++) {
848 			PUT(*(p + i));
849 		}
850 	} while ((0 < *inbytesleft) && (0 == once));
851 
852 	return ((size_t)(0));
853 }
854 
855 
856 /*
857  * map-dense_encoding-lookup
858  */
859 static size_t
860 map_d_e_l(
861 	itm_tbl_hdr_t		*tbl_hdr,
862 	const unsigned char	**inbuf,
863 	size_t			*inbytesleft,
864 	unsigned char		**outbuf,
865 	size_t			*outbytesleft,
866 	long			once)
867 {
868 	itm_map_dense_enc_hdr_t	*map_hdr;
869 	long			i;
870 	itm_num_t		j;
871 	const unsigned char	*p;
872 	unsigned char		*map_ptr;
873 	unsigned char		*map_error;
874 	unsigned char		*byte_seq_min;
875 	unsigned char		*byte_seq_max;
876 
877 	TRACE_MESSAGE('i', ("map_d_e_l\n"));
878 
879 	map_hdr = (itm_map_dense_enc_hdr_t *)(tbl_hdr + 1);
880 	map_ptr = ((unsigned char *)(map_hdr + 1) +
881 			map_hdr->source_len + map_hdr->source_len);
882 	map_error = (map_ptr + (tbl_hdr->number * map_hdr->result_len));
883 	if (0 == map_hdr->default_error) {
884 		map_error = (void *)(map_error + map_hdr->result_len);
885 	}
886 	byte_seq_min = (unsigned char *)(map_hdr + 1);
887 	byte_seq_max = byte_seq_min + map_hdr->source_len;
888 
889 	do {
890 		if (*inbytesleft < map_hdr->source_len) {
891 			errno = EINVAL;
892 			TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
893 			return ((size_t)(-1));
894 		}
895 
896 		j = hash_dense_encoding(*inbuf, map_hdr->source_len,
897 					byte_seq_min, byte_seq_max);
898 
899 		if (((j < 0) || (tbl_hdr->number < j)) &&
900 		    (0 < map_hdr->default_error)) {
901 			errno = EILSEQ;
902 			TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
903 			return ((size_t)(-1));
904 		}
905 
906 		if (*outbytesleft < map_hdr->result_len) {
907 			errno = E2BIG;
908 			TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
909 			return ((size_t)(-1));
910 		}
911 
912 		if ((j < 0) || (tbl_hdr->number < j)) {
913 			if (0 == map_hdr->default_error) {
914 				p = (map_ptr +
915 				(tbl_hdr->number * map_hdr->result_len));
916 				for (i = 0; i < map_hdr->result_len; i++) {
917 					PUT(*(p + i));
918 				}
919 			} else {
920 				p = *inbuf;
921 				for (i = 0; i < map_hdr->source_len; i++) {
922 					PUT(*(p + i));
923 				}
924 			}
925 		} else {
926 			if ((1 == map_hdr->default_error) ||
927 			    (0 < map_hdr->error_num)) {
928 				if (0 != *(map_error + j)) {
929 					errno = EILSEQ;
930 					TRACE_MESSAGE('e',
931 					("map_d_e_l:error=%d\n", errno));
932 					return ((size_t)(-1));
933 				}
934 			}
935 			p = (map_ptr + (map_hdr->result_len * j));
936 			for (i = 0; i < map_hdr->result_len; i++) {
937 				PUT(*(p + i));
938 			}
939 		}
940 		DISCARD(map_hdr->source_len);
941 	} while ((0 < *inbytesleft) && (0 == once));
942 
943 	return ((size_t)(0));
944 }
945 
946 
947 
948 /*
949  * Evaluate condition table
950  *
951  */
952 static size_t
953 eval_cond_tbl(
954 	icv_state_t		*ist,
955 	itm_place_t		cond_place,
956 	const unsigned char	**inbuf,
957 	size_t			*inbytesleft,
958 	size_t			outbytesleft,
959 	itm_direc_t		*direc
960 )
961 {
962 	itm_tbl_hdr_t		*cond_hdr;
963 	itm_cond_t		*cond;
964 	long			i;
965 	long			j;
966 	long			k;
967 	size_t			retval;
968 	itm_tbl_hdr_t		*rth;
969 	itm_range_hdr_t		*rtsh;
970 	unsigned char		*p;
971 	itm_tbl_hdr_t		*eth;
972 	itm_escapeseq_hdr_t	*eh;
973 	itm_data_t		*d;
974 	const unsigned char	*ip;
975 	size_t			ileft;
976 
977 	retval = 0;
978 	ip =	*inbuf;
979 	ileft = *inbytesleft;
980 	cond_hdr = ADDR(cond_place);
981 	cond = (itm_cond_t *)(cond_hdr + 1);
982 	for (i = 0; i < cond_hdr->number; i++, cond++) {
983 		switch (cond->type) {
984 		case ITM_COND_BETWEEN:
985 			rth = ADDR(cond->operand.place);
986 			rtsh = (itm_range_hdr_t *)(rth + 1);
987 			if (ileft < rtsh->len) {
988 				errno = EINVAL;
989 				TRACE_MESSAGE('e',
990 				("eval_cond_tbl:error=%d\n", errno));
991 				retval = ((size_t)(-1));
992 				goto eval_cond_return;
993 			}
994 			p = (unsigned char *)(rtsh + 1);
995 			retval = 0;
996 			for (j = 0; j < rth->number;
997 			    j++,  p = (void *)(p + (2 * rtsh->len))) {
998 				retval = 1;
999 				for (k = 0; k < rtsh->len; k++) {
1000 					if ((*(ip + k) < *(p + k)) ||
1001 					    (*(p + rtsh->len + k) <
1002 					    *(ip + k))) {
1003 						retval = 0;
1004 						break;
1005 					}
1006 				}
1007 				if (1 == retval) {
1008 					break;
1009 				}
1010 			}
1011 			if (0 == retval) {
1012 				TRACE_MESSAGE('b',
1013 				("out of between (%p) len= rtsh=%ld\n",
1014 				*ip, rtsh->len));
1015 				goto eval_cond_return;
1016 			}
1017 			break; /* continue */
1018 		case ITM_COND_ESCAPESEQ:
1019 			/*
1020 			 * if escape sequence occur,
1021 			 * change ist->default_action and return 2.
1022 			 * never return 1.
1023 			 */
1024 			retval = 0;
1025 			eth = ADDR(cond->operand.place);
1026 			eh = (itm_escapeseq_hdr_t *)(eth + 1);
1027 			if (NULL == ist->default_action.itm_ptr) {
1028 				ist->default_action = direc->action;
1029 				TRACE_MESSAGE('E',
1030 				("escape seq (default action=%6p, "
1031 				"type=%ld) set\n",
1032 				direc->action.itm_ptr,
1033 				((itm_tbl_hdr_t *)(ADDR(direc->action)))
1034 				->type));
1035 			}
1036 			retval = 0;
1037 			if (*inbytesleft < eh->len_min) {
1038 				break;
1039 			}
1040 			for (j = 0, d = (itm_data_t *)(eh + 1);
1041 			    j < eth->number;
1042 			    j++, d++) {
1043 				if (*inbytesleft < d->size) {
1044 					continue;
1045 				}
1046 				if (0 == memcmp(*inbuf, DADDR(d), d->size)) {
1047 					TRACE_MESSAGE('E',
1048 					("escape seq: discard=%ld chars\n",
1049 					d->size));
1050 					TRACE_MESSAGE('E', (
1051 					"escape seq (default action=%6p, "
1052 					"type=%ld) set\n",
1053 					direc->action.itm_ptr,
1054 					((itm_tbl_hdr_t *)
1055 					(ADDR(direc->action)))->type));
1056 					ist->default_action = direc->action;
1057 					DISCARD(d->size);
1058 					retval = 2;
1059 					goto eval_cond_return;
1060 				}
1061 			}
1062 			if (0 == retval) {
1063 				goto eval_cond_return;
1064 			}
1065 			break; /* continue */
1066 		case ITM_COND_EXPR:
1067 			retval = eval_expr(ist, cond->operand.place,
1068 					*inbytesleft, ip, outbytesleft);
1069 			if (0 == retval) {
1070 				goto eval_cond_return;
1071 			} else {
1072 				retval = 1;
1073 			}
1074 			break; /* continue */
1075 		default:
1076 			TRACE_MESSAGE('e', ("eval_cond_tbl:illegal cond=%d\n",
1077 			cond->type));
1078 			retval = (size_t)-1;
1079 			goto eval_cond_return;
1080 		}
1081 	}
1082 
1083 eval_cond_return:
1084 	return (retval);
1085 }
1086 
1087 /*
1088  * Evaluate operation table
1089  *
1090  */
1091 static size_t
1092 eval_op_tbl(
1093 	icv_state_t	*ist,
1094 	itm_place_t	op_tbl_place,
1095 	const unsigned char	**inbuf,
1096 	size_t		*inbytesleft,
1097 	unsigned char	**outbuf,
1098 	size_t		*outbytesleft)
1099 {
1100 	itm_tbl_hdr_t	*op_hdr;
1101 	itm_op_t	*operation;
1102 	itm_place2_t	op_place;
1103 	size_t		retval;
1104 	long		i;
1105 
1106 	retval = 0;
1107 
1108 #if defined(OP_DEPTH_MAX)
1109 	if (OP_DEPTH_MAX <= ist->op_depth) {
1110 		errno = ELIBBAD;
1111 		TRACE_MESSAGE('e', ("eval_op_tbl:error=%d\n", errno));
1112 		return	(RETVALERR);
1113 	}
1114 	ist->op_depth += 1;
1115 #endif /* OP_DEPTH_MAX */
1116 
1117 	op_hdr = ADDR(op_tbl_place);
1118 	operation = (itm_op_t *)(op_hdr + 1);
1119 
1120 	op_place = op_tbl_place.itm_ptr + (sizeof (itm_tbl_hdr_t));
1121 	for (i = 0; i < op_hdr->number; i++, operation++,
1122 	    op_place += (sizeof (itm_op_t))) {
1123 		TRACE_MESSAGE('O', ("eval_op_tbl: %ld %p\n", i, op_place));
1124 		retval = eval_op(ist, op_place,
1125 				inbuf, inbytesleft,
1126 				outbuf, outbytesleft);
1127 		if (((long)(retval)) < 0) {
1128 #if defined(OP_DEPTH_MAX)
1129 			ist->op_depth -= 1;
1130 #endif /* OP_DEPTH_MAX */
1131 			switch (retval) {
1132 			case RETVALERR:
1133 				return	(retval);
1134 			case RETVALRET:
1135 				if (0 == op_hdr->name.itm_ptr) {
1136 					return	(RETVALRET);
1137 				} else {
1138 					return (0);
1139 				}
1140 			}
1141 		}
1142 	}
1143 #if defined(OP_DEPTH_MAX)
1144 	ist->op_depth -= 1;
1145 #endif /* OP_DEPTH_MAX */
1146 	return	(retval);
1147 }
1148 
1149 
1150 /*
1151  * Evaluate single operation
1152  *
1153  */
1154 static size_t
1155 eval_op(
1156 	icv_state_t		*ist,
1157 	itm_place2_t		op_place,
1158 	const unsigned char	**inbuf,
1159 	size_t			*inbytesleft,
1160 	unsigned char		**outbuf,
1161 	size_t			*outbytesleft)
1162 {
1163 	size_t			retval;
1164 	itm_num_t		num;
1165 	itm_op_t		*operation;
1166 	itm_expr_t		*expr;
1167 	itm_num_t		c;
1168 	itm_num_t		i;
1169 	itm_size_t		z;
1170 	unsigned char		*p;
1171 	itm_expr_t		*expr0;
1172 
1173 #define	EVAL_EXPR(n)							\
1174 	(expr0 = ADDR(operation->data.operand[(n)]),			\
1175 	(itm_num_t)((expr0->type == ITM_EXPR_INT) ?		       	\
1176 		expr0->data.itm_exnum :					\
1177 		((expr0->type == ITM_EXPR_REG) ?			\
1178 		REG(expr0->data.itm_exnum) :				\
1179 		((expr0->type == ITM_EXPR_IN_VECTOR_D) ?		\
1180 		((expr0->data.itm_exnum < 0) ?				\
1181 		(((-1) == expr0->data.itm_exnum) ? *inbytesleft : 0) :	\
1182 		((expr0->data.itm_exnum < *inbytesleft) ?		\
1183 		(*(uchar_t *)(*inbuf + expr0->data.itm_exnum)) : 0)):	\
1184 		eval_expr(ist, operation->data.operand[(n)],		\
1185 		*inbytesleft, *inbuf, *outbytesleft)))))
1186 
1187 	retval = 0;
1188 
1189 	operation = (itm_op_t *)ADDR2(op_place);
1190 
1191 	switch (operation->type) {
1192 	case ITM_OP_EXPR:
1193 		num = eval_expr(ist, operation->data.operand[0],
1194 				*inbytesleft, *inbuf, *outbytesleft);
1195 		TRACE_MESSAGE('o', ("ITM_OP_EXPR: %ld\n", retval));
1196 		break;
1197 	case ITM_OP_ERROR:
1198 		num = eval_expr(ist, operation->data.operand[0],
1199 				*inbytesleft, *inbuf, *outbytesleft);
1200 		errno = (int)num;
1201 		TRACE_MESSAGE('o', ("ITM_OP_ERROR: %ld\n", num));
1202 		retval = (size_t)(-1);
1203 		break;
1204 	case ITM_OP_ERROR_D:
1205 		errno = (int)operation->data.itm_opnum;
1206 		TRACE_MESSAGE('o', ("ITM_OP_ERROR_D: %d\n", errno));
1207 		retval = (size_t)(-1);
1208 		break;
1209 	case ITM_OP_OUT:
1210 		expr = ADDR(operation->data.operand[0]);
1211 		if ((*outbytesleft) == 0) {
1212 			errno = E2BIG;
1213 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1214 			return ((size_t)(-1));
1215 		}
1216 		c = eval_expr(ist, operation->data.operand[0],
1217 				*inbytesleft, *inbuf, *outbytesleft);
1218 		PUT((uchar_t)c);
1219 		retval = *inbytesleft;
1220 		TRACE_MESSAGE('o', ("ITM_OP_OUT: %ld %ld\n", c, *inbytesleft));
1221 		break;
1222 	case ITM_OP_OUT_D:
1223 		expr = ADDR(operation->data.operand[0]);
1224 		if ((*outbytesleft) == 0) {
1225 			errno = E2BIG;
1226 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1227 			return ((size_t)(-1));
1228 		}
1229 		PUT(0xff & (expr->data.itm_exnum));
1230 		break;
1231 	case ITM_OP_OUT_S:
1232 		expr = ADDR(operation->data.operand[0]);
1233 		if ((*outbytesleft) == 0) {
1234 			errno = E2BIG;
1235 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1236 			return ((size_t)(-1));
1237 		}
1238 		z = expr->data.value.size;
1239 		if (*outbytesleft < z) {
1240 			errno = E2BIG;
1241 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1242 			return ((size_t)(-1));
1243 		}
1244 		p = DADDR(&(expr->data.value));
1245 		for (; 0 < z; --z, p++) {
1246 			PUT(*p);
1247 		}
1248 		break;
1249 	case ITM_OP_OUT_R:
1250 		expr = ADDR(operation->data.operand[0]);
1251 		if ((*outbytesleft) == 0) {
1252 			errno = E2BIG;
1253 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1254 			return ((size_t)(-1));
1255 		}
1256 		c = REG(expr->data.itm_exnum);
1257 		PUT((uchar_t)c);
1258 		break;
1259 	case ITM_OP_OUT_INVD:
1260 		expr = ADDR(operation->data.operand[0]);
1261 		if ((*outbytesleft) == 0) {
1262 			errno = E2BIG;
1263 			TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1264 			return ((size_t)(-1));
1265 		}
1266 		z = (((0 <= expr->data.itm_exnum) &&
1267 			(expr->data.itm_exnum < *inbytesleft)) ?
1268 			(*((unsigned char *)(*inbuf + expr->data.itm_exnum))) :
1269 			(((-1) == expr->data.itm_exnum) ? *inbytesleft : 0));
1270 		PUT((uchar_t)z);
1271 		break;
1272 	case ITM_OP_DISCARD:
1273 #if defined(EVAL_EXPR)
1274 		num = EVAL_EXPR(0);
1275 #else /* !defined(EVAL_EXPR) */
1276 		num = eval_expr(ist, operation->data.operand[0],
1277 				*inbytesleft, *inbuf, *outbytesleft);
1278 #endif /* defined(EVAL_EXPR) */
1279 		TRACE_MESSAGE('o', ("ITM_OP_DISCARD: %ld\n", num));
1280 #if defined(DISCARD)
1281 		DISCARD((num <= *inbytesleft) ? ((ulong_t)num) :
1282 						*inbytesleft);
1283 #else /* defined(DISCARD) */
1284 		for (num = ((num <= *inbytesleft) ? num : *inbytesleft);
1285 		    0 < num; --num) {
1286 			GET(c);
1287 		}
1288 #endif /* defined(DISCARD) */
1289 		break;
1290 	case ITM_OP_DISCARD_D:
1291 		num = operation->data.itm_opnum;
1292 		TRACE_MESSAGE('o', ("ITM_OP_DISCARD_D: %ld\n", num));
1293 #if defined(DISCARD)
1294 		DISCARD((num <= *inbytesleft) ? num : *inbytesleft);
1295 #else /* defined(DISCARD) */
1296 		for (num = ((num <= *inbytesleft) ? num : *inbytesleft);
1297 		    0 < num; --num) {
1298 			GET(c);
1299 		}
1300 #endif /* defined(DISCARD) */
1301 		break;
1302 	case ITM_OP_IF:
1303 		c = eval_expr(ist, operation->data.operand[0],
1304 				*inbytesleft, *inbuf, *outbytesleft);
1305 		TRACE_MESSAGE('o', ("ITM_OP_IF: %ld\n", c));
1306 		if (c) {
1307 			retval = eval_op_tbl(ist,
1308 					    operation->data.operand[1],
1309 					    inbuf, inbytesleft,
1310 					    outbuf, outbytesleft);
1311 		}
1312 		break;
1313 	case ITM_OP_IF_ELSE:
1314 		c = eval_expr(ist, operation->data.operand[0],
1315 				*inbytesleft, *inbuf, *outbytesleft);
1316 		TRACE_MESSAGE('o', ("ITM_OP_IF_ELSE: %ld\n", c));
1317 		if (c) {
1318 			retval = eval_op_tbl(ist,
1319 						operation->data.operand[1],
1320 						inbuf, inbytesleft,
1321 						outbuf, outbytesleft);
1322 		} else {
1323 			retval = eval_op_tbl(ist,
1324 						operation->data.operand[2],
1325 						inbuf, inbytesleft,
1326 						outbuf, outbytesleft);
1327 		}
1328 		break;
1329 	case ITM_OP_DIRECTION:
1330 		TRACE_MESSAGE('o', ("ITM_OP_DIRECTION: %p\n",
1331 			operation->data.operand[0].itm_ptr));
1332 		ist->direc = ADDR(operation->data.operand[0]);
1333 		return ((size_t)(-2));
1334 	case ITM_OP_MAP:
1335 		TRACE_MESSAGE('o', ("ITM_OP_MAP: %p\n",
1336 				operation->data.operand[0].itm_ptr));
1337 		i = 0;
1338 		if (0 != operation->data.operand[1].itm_ptr) {
1339 #if defined(EVAL_EXPR)
1340 			i = EVAL_EXPR(1);
1341 #else /* !defined(EVAL_EXPR) */
1342 			i = eval_expr(ist, operation->data.operand[1],
1343 				*inbytesleft, *inbuf, *outbytesleft);
1344 #endif /* defined(EVAL_EXPR) */
1345 			(*inbytesleft) -= i;
1346 			(*inbuf) += i;
1347 		}
1348 
1349 		retval = map_i_f(ADDR(operation->data.operand[0]),
1350 				inbuf, inbytesleft,
1351 				outbuf, outbytesleft, 1);
1352 		if ((size_t)(-1) == retval) {
1353 			(*outbytesleft) += i;
1354 			(*outbuf) -= i;
1355 		}
1356 		break;
1357 	case ITM_OP_OPERATION:
1358 		TRACE_MESSAGE('o', ("ITM_OP_OPERATION: %p\n",
1359 				operation->data.operand[0].itm_ptr));
1360 		retval = eval_op_tbl(ist,
1361 				operation->data.operand[0],
1362 				inbuf, inbytesleft,
1363 				outbuf, outbytesleft);
1364 
1365 		break;
1366 	case ITM_OP_INIT:
1367 		TRACE_MESSAGE('o', ("ITM_OP_INIT: %p\n",
1368 				ist->itm_hdr->op_init_tbl));
1369 		if (0 != ist->itm_hdr->op_init_tbl.itm_ptr) {
1370 			retval = eval_op_tbl(ist,
1371 						ist->itm_hdr->op_init_tbl,
1372 						inbuf, inbytesleft,
1373 						outbuf, outbytesleft);
1374 		} else {
1375 			op_init_default(ist);
1376 			retval = (size_t)-2;
1377 		}
1378 		break;
1379 	case ITM_OP_RESET:
1380 		TRACE_MESSAGE('o', ("ITM_OP_RESET: %p\n",
1381 				ist->itm_hdr->op_reset_tbl));
1382 		if (0 != ist->itm_hdr->op_reset_tbl.itm_ptr) {
1383 			retval = eval_op_tbl(ist,
1384 						ist->itm_hdr->op_reset_tbl,
1385 						inbuf, inbytesleft,
1386 						outbuf, outbytesleft);
1387 		} else {
1388 			op_reset_default(ist);
1389 			retval = (size_t)-2;
1390 		}
1391 		break;
1392 	case ITM_OP_BREAK:
1393 		TRACE_MESSAGE('o', ("ITM_OP_BREAK\n"));
1394 		return	(RETVALBRK);
1395 	case ITM_OP_RETURN:
1396 		TRACE_MESSAGE('o', ("ITM_OP_RETURN\n"));
1397 		return	(RETVALRET);
1398 	case ITM_OP_PRINTCHR:
1399 		c = eval_expr(ist, operation->data.operand[0],
1400 				*inbytesleft, *inbuf, *outbytesleft);
1401 		(void) fputc((uchar_t)c, stderr);
1402 		TRACE_MESSAGE('o',
1403 		("ITM_OP_PRINTCHR: %ld %ld\n", c, *inbytesleft));
1404 		break;
1405 	case ITM_OP_PRINTHD:
1406 		c = eval_expr(ist, operation->data.operand[0],
1407 				 *inbytesleft, *inbuf, *outbytesleft);
1408 		(void) fprintf(stderr, "%lx", c);
1409 		TRACE_MESSAGE('o',
1410 		("ITM_OP_PRINTHD: %ld %ld\n", c, *inbytesleft));
1411 		break;
1412 	case ITM_OP_PRINTINT:
1413 		c = eval_expr(ist, operation->data.operand[0],
1414 				*inbytesleft, *inbuf, *outbytesleft);
1415 		(void) fprintf(stderr, "%ld", c);
1416 		TRACE_MESSAGE('o',
1417 		("ITM_OP_PRINTINT: %ld %ld\n", c, *inbytesleft));
1418 		break;
1419 	default: /* never */
1420 		errno = ELIBBAD;
1421 		TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1422 		return (size_t)(-1);
1423 	}
1424 	return	(retval);
1425 
1426 #undef EVAL_EXPR
1427 }
1428 
1429 
1430 /*
1431  * Evaluate expression
1432  */
1433 static itm_num_t
1434 eval_expr(
1435 	icv_state_t		*ist,
1436 	itm_place_t		expr_place,
1437 	size_t			inbytesleft,
1438 	const unsigned char	*inbuf,
1439 	size_t			outbytesleft)
1440 {
1441 	itm_expr_t		*expr;
1442 	itm_expr_t		*expr_op;
1443 	itm_num_t		num;
1444 	unsigned char		*p;
1445 	long			i;
1446 	itm_expr_t		*expr0;
1447 	itm_num_t		num00;
1448 	itm_num_t		num01;
1449 
1450 #define	EVAL_EXPR_E(n) (eval_expr(ist, expr->data.operand[(n)],		\
1451 					inbytesleft, inbuf, outbytesleft))
1452 #define	EVAL_EXPR_D(n)	((itm_num_t)(expr->data.operand[(n)].itm_ptr))
1453 #define	EVAL_EXPR_R(n)	(REG((itm_num_t)(expr->data.operand[(n)].itm_ptr)))
1454 #define	EVAL_EXPR_INVD(n)						\
1455 	((num0 ## n) = ((itm_num_t)(expr->data.operand[(n)].itm_ptr)),	\
1456 	((num0 ## n) < 0) ?						\
1457 	(((-1) == (num0 ## n)) ? inbytesleft : 0) :			\
1458 	(((num0 ## n) < inbytesleft) ?					\
1459 	(*(unsigned char *)(inbuf + (num0 ## n))) : 0))
1460 #define	EVAL_EXPR(n)							\
1461 	(expr0 = ADDR(expr->data.operand[(n)]),				\
1462 	(itm_num_t)((expr0->type == ITM_EXPR_INT) ?		       	\
1463 	expr0->data.itm_exnum :						\
1464 	((expr0->type == ITM_EXPR_REG) ?				\
1465 	REG(expr0->data.itm_exnum) :					\
1466 	((expr0->type == ITM_EXPR_IN_VECTOR_D) ?			\
1467 	((expr0->data.itm_exnum < 0) ?					\
1468 	(((-1) == expr0->data.itm_exnum) ? inbytesleft : 0) :		\
1469 	((expr0->data.itm_exnum < inbytesleft) ?			\
1470 	(*(uchar_t *)(inbuf + expr0->data.itm_exnum)) : 0)) :		\
1471 	eval_expr(ist, expr->data.operand[(n)],				\
1472 	inbytesleft, inbuf, outbytesleft)))))
1473 
1474 #define	EVAL_OP_BIN_PROTO(op, name, name0, name1)			\
1475 	case ITM_EXPR_##name##_##name0##_##name1:			\
1476 		return (EVAL_EXPR_##name0(0) op EVAL_EXPR_##name1(1));
1477 
1478 #define	EVAL_OP_BIN1(op, name)					\
1479 		EVAL_OP_BIN_PROTO(op, name, E, E)		\
1480 		EVAL_OP_BIN_PROTO(op, name, E, D)		\
1481 		EVAL_OP_BIN_PROTO(op, name, E, R)		\
1482 		EVAL_OP_BIN_PROTO(op, name, E, INVD)
1483 
1484 #define	EVAL_OP_BIN2(op, name)					\
1485 		EVAL_OP_BIN_PROTO(op, name, D, E)		\
1486 		EVAL_OP_BIN_PROTO(op, name, D, D)		\
1487 		EVAL_OP_BIN_PROTO(op, name, D, R)		\
1488 		EVAL_OP_BIN_PROTO(op, name, D, INVD)
1489 
1490 #define	EVAL_OP_BIN3(op, name)					\
1491 		EVAL_OP_BIN_PROTO(op, name, R, E)		\
1492 		EVAL_OP_BIN_PROTO(op, name, R, D)		\
1493 		EVAL_OP_BIN_PROTO(op, name, R, R)		\
1494 		EVAL_OP_BIN_PROTO(op, name, R, INVD)
1495 
1496 #define	EVAL_OP_BIN4(op, name)					\
1497 		EVAL_OP_BIN_PROTO(op, name, INVD, E)		\
1498 		EVAL_OP_BIN_PROTO(op, name, INVD, D)		\
1499 		EVAL_OP_BIN_PROTO(op, name, INVD, R)		\
1500 		EVAL_OP_BIN_PROTO(op, name, INVD, INVD)
1501 
1502 #define	EVAL_OP_BIN_PROTECT_PROTO(op, name, name0, name1)	\
1503 	case ITM_EXPR_##name##_##name0##_##name1:		\
1504 		num = EVAL_EXPR_##name1(1);			\
1505 		if (0 != num) {					\
1506 			return (EVAL_EXPR_##name0(0) op num);	\
1507 		} else {					\
1508 			return (0);				\
1509 		}
1510 
1511 #define	EVAL_OP_BIN_PROTECT1(op, name)				\
1512 		EVAL_OP_BIN_PROTECT_PROTO(op, name, E, E)	\
1513 		EVAL_OP_BIN_PROTECT_PROTO(op, name, E, D)	\
1514 		EVAL_OP_BIN_PROTECT_PROTO(op, name, E, R)	\
1515 		EVAL_OP_BIN_PROTECT_PROTO(op, name, E, INVD)
1516 
1517 #define	EVAL_OP_BIN_PROTECT2(op, name)				\
1518 		EVAL_OP_BIN_PROTECT_PROTO(op, name, D, E)	\
1519 		EVAL_OP_BIN_PROTECT_PROTO(op, name, D, D)	\
1520 		EVAL_OP_BIN_PROTECT_PROTO(op, name, D, R)	\
1521 		EVAL_OP_BIN_PROTECT_PROTO(op, name, D, INVD)
1522 
1523 #define	EVAL_OP_BIN_PROTECT3(op, name)				\
1524 		EVAL_OP_BIN_PROTECT_PROTO(op, name, R, E)	\
1525 		EVAL_OP_BIN_PROTECT_PROTO(op, name, R, D)	\
1526 		EVAL_OP_BIN_PROTECT_PROTO(op, name, R, R)	\
1527 		EVAL_OP_BIN_PROTECT_PROTO(op, name, R, INVD)
1528 
1529 #define	EVAL_OP_BIN_PROTECT4(op, name)				\
1530 		EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, E)	\
1531 		EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, D)	\
1532 		EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, R)	\
1533 		EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, INVD)
1534 
1535 	expr = ADDR(expr_place);
1536 
1537 	switch (expr->type) {
1538 	case ITM_EXPR_NONE:		/* not used */
1539 		return (0);
1540 	case ITM_EXPR_NOP:		/* not used */
1541 		return (0);
1542 	case ITM_EXPR_NAME:		/* not used */
1543 		return (0);
1544 	case ITM_EXPR_INT:		/* integer */
1545 		return (expr->data.itm_exnum);
1546 	case ITM_EXPR_SEQ:		/* byte sequence */
1547 		if ((sizeof (itm_place_t)) < expr->data.value.size) {
1548 			p = (unsigned char *)ADDR(expr->data.value.place);
1549 		} else {
1550 			p = (unsigned char *)&(expr->data.value.place);
1551 		}
1552 		for (i = 0, num = 0; i < expr->data.value.size; i++, p++) {
1553 			num = ((num << 8) | *p);
1554 		}
1555 		return	(num);
1556 	case ITM_EXPR_REG:		/* register */
1557 		return (REG(expr->data.itm_exnum));
1558 	case ITM_EXPR_IN_VECTOR:	/* in[expr] */
1559 		num = EVAL_EXPR(0);
1560 		if ((0 <= num) && (num < inbytesleft)) {
1561 			return (*((unsigned char *)(inbuf + num)));
1562 		} else if ((-1) == num) {
1563 			return	(inbytesleft);
1564 		} else {
1565 			return (0);
1566 		}
1567 	case ITM_EXPR_IN_VECTOR_D:	/* in[DECIMAL] */
1568 		num = expr->data.itm_exnum;
1569 		if ((0 <= num) && (num < inbytesleft)) {
1570 			return (*((unsigned char *)(inbuf + num)));
1571 		} else if ((-1) == num) {
1572 			return	(inbytesleft);
1573 		} else {
1574 			return (0);
1575 		}
1576 	case ITM_EXPR_OUT:		/* out */
1577 		return	(outbytesleft);
1578 	case ITM_EXPR_TRUE:		/* true */
1579 		return (1);
1580 	case ITM_EXPR_FALSE:		/* false */
1581 		return (0);
1582 	case ITM_EXPR_UMINUS:		/* unary minus */
1583 		return ((-1) * EVAL_EXPR(0));
1584 #define	PLUS_FOR_CSTYLE_CLEAN +
1585 #define	MINUS_FOR_CSTYLE_CLEAN -
1586 #define	MUL_FOR_CSTYLE_CLEAN *
1587 #define	DIV_FOR_CSTYLE_CLEAN /
1588 #define	MOD_FOR_CSTYLE_CLEAN %
1589 #define	SHIFT_L_FOR_CSTYLE_CLEAN <<
1590 #define	SHIFT_R_FOR_CSTYLE_CLEAN >>
1591 #define	OR_FOR_CSTYLE_CLEAN |
1592 #define	XOR_FOR_CSTYLE_CLEAN ^
1593 #define	AND_FOR_CSTYLE_CLEAN &
1594 #define	EQ_FOR_CSTYLE_CLEAN ==
1595 #define	NE_FOR_CSTYLE_CLEAN !=
1596 #define	GT_FOR_CSTYLE_CLEAN >
1597 #define	GE_FOR_CSTYLE_CLEAN >=
1598 #define	LT_FOR_CSTYLE_CLEAN <
1599 #define	LE_FOR_CSTYLE_CLEAN <=
1600 	EVAL_OP_BIN1(PLUS_FOR_CSTYLE_CLEAN, PLUS)	/* A + B */
1601 	EVAL_OP_BIN2(PLUS_FOR_CSTYLE_CLEAN, PLUS)	/* A + B */
1602 	EVAL_OP_BIN3(PLUS_FOR_CSTYLE_CLEAN, PLUS)	/* A + B */
1603 	EVAL_OP_BIN4(PLUS_FOR_CSTYLE_CLEAN, PLUS)	/* A + B */
1604 
1605 	EVAL_OP_BIN1(MINUS_FOR_CSTYLE_CLEAN, MINUS)	/* A - B */
1606 	EVAL_OP_BIN2(MINUS_FOR_CSTYLE_CLEAN, MINUS)	/* A - B */
1607 	EVAL_OP_BIN3(MINUS_FOR_CSTYLE_CLEAN, MINUS)	/* A - B */
1608 	EVAL_OP_BIN4(MINUS_FOR_CSTYLE_CLEAN, MINUS)	/* A - B */
1609 
1610 	EVAL_OP_BIN1(MUL_FOR_CSTYLE_CLEAN, MUL)		/* A * B */
1611 	EVAL_OP_BIN2(MUL_FOR_CSTYLE_CLEAN, MUL)		/* A * B */
1612 	EVAL_OP_BIN3(MUL_FOR_CSTYLE_CLEAN, MUL)		/* A * B */
1613 	EVAL_OP_BIN4(MUL_FOR_CSTYLE_CLEAN, MUL)		/* A * B */
1614 
1615 	EVAL_OP_BIN_PROTECT1(DIV_FOR_CSTYLE_CLEAN, DIV)	/* A / B */
1616 	EVAL_OP_BIN_PROTECT2(DIV_FOR_CSTYLE_CLEAN, DIV)	/* A / B */
1617 	EVAL_OP_BIN_PROTECT3(DIV_FOR_CSTYLE_CLEAN, DIV)	/* A / B */
1618 	EVAL_OP_BIN_PROTECT4(DIV_FOR_CSTYLE_CLEAN, DIV)	/* A / B */
1619 
1620 	EVAL_OP_BIN_PROTECT1(MOD_FOR_CSTYLE_CLEAN, MOD)	/* A % B */
1621 	EVAL_OP_BIN_PROTECT2(MOD_FOR_CSTYLE_CLEAN, MOD)	/* A % B */
1622 	EVAL_OP_BIN_PROTECT3(MOD_FOR_CSTYLE_CLEAN, MOD)	/* A % B */
1623 	EVAL_OP_BIN_PROTECT4(MOD_FOR_CSTYLE_CLEAN, MOD)	/* A % B */
1624 
1625 	EVAL_OP_BIN1(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L)	/* A << B */
1626 	EVAL_OP_BIN2(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L)	/* A << B */
1627 	EVAL_OP_BIN3(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L)	/* A << B */
1628 	EVAL_OP_BIN4(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L)	/* A << B */
1629 
1630 	EVAL_OP_BIN1(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R)	/* A >> B */
1631 	EVAL_OP_BIN2(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R)	/* A >> B */
1632 	EVAL_OP_BIN3(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R)	/* A >> B */
1633 	EVAL_OP_BIN4(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R)	/* A >> B */
1634 
1635 	EVAL_OP_BIN1(OR_FOR_CSTYLE_CLEAN, OR)		/* A |	B */
1636 	EVAL_OP_BIN2(OR_FOR_CSTYLE_CLEAN, OR)		/* A |	B */
1637 	EVAL_OP_BIN3(OR_FOR_CSTYLE_CLEAN, OR)		/* A |	B */
1638 	EVAL_OP_BIN4(OR_FOR_CSTYLE_CLEAN, OR)		/* A |	B */
1639 
1640 	EVAL_OP_BIN1(XOR_FOR_CSTYLE_CLEAN, XOR)		/* A ^	B */
1641 	EVAL_OP_BIN2(XOR_FOR_CSTYLE_CLEAN, XOR)		/* A ^	B */
1642 	EVAL_OP_BIN3(XOR_FOR_CSTYLE_CLEAN, XOR)		/* A ^	B */
1643 	EVAL_OP_BIN4(XOR_FOR_CSTYLE_CLEAN, XOR)		/* A ^	B */
1644 
1645 	EVAL_OP_BIN1(AND_FOR_CSTYLE_CLEAN, AND)		/* A &	B */
1646 	EVAL_OP_BIN2(AND_FOR_CSTYLE_CLEAN, AND)		/* A &	B */
1647 	EVAL_OP_BIN3(AND_FOR_CSTYLE_CLEAN, AND)		/* A &	B */
1648 	EVAL_OP_BIN4(AND_FOR_CSTYLE_CLEAN, AND)		/* A &	B */
1649 
1650 	EVAL_OP_BIN1(EQ_FOR_CSTYLE_CLEAN, EQ)		/* A == B */
1651 	EVAL_OP_BIN2(EQ_FOR_CSTYLE_CLEAN, EQ)		/* A == B */
1652 	EVAL_OP_BIN3(EQ_FOR_CSTYLE_CLEAN, EQ)		/* A == B */
1653 	EVAL_OP_BIN4(EQ_FOR_CSTYLE_CLEAN, EQ)		/* A == B */
1654 
1655 	EVAL_OP_BIN1(NE_FOR_CSTYLE_CLEAN, NE)		/* A != B */
1656 	EVAL_OP_BIN2(NE_FOR_CSTYLE_CLEAN, NE)		/* A != B */
1657 	EVAL_OP_BIN3(NE_FOR_CSTYLE_CLEAN, NE)		/* A != B */
1658 	EVAL_OP_BIN4(NE_FOR_CSTYLE_CLEAN, NE)		/* A != B */
1659 
1660 	EVAL_OP_BIN1(GT_FOR_CSTYLE_CLEAN, GT)		/* A >	B */
1661 	EVAL_OP_BIN2(GT_FOR_CSTYLE_CLEAN, GT)		/* A >	B */
1662 	EVAL_OP_BIN3(GT_FOR_CSTYLE_CLEAN, GT)		/* A >	B */
1663 	EVAL_OP_BIN4(GT_FOR_CSTYLE_CLEAN, GT)		/* A >	B */
1664 
1665 	EVAL_OP_BIN1(GE_FOR_CSTYLE_CLEAN, GE)		/* A >= B */
1666 	EVAL_OP_BIN2(GE_FOR_CSTYLE_CLEAN, GE)		/* A >= B */
1667 	EVAL_OP_BIN3(GE_FOR_CSTYLE_CLEAN, GE)		/* A >= B */
1668 	EVAL_OP_BIN4(GE_FOR_CSTYLE_CLEAN, GE)		/* A >= B */
1669 
1670 	EVAL_OP_BIN1(LT_FOR_CSTYLE_CLEAN, LT)		/* A <	B */
1671 	EVAL_OP_BIN2(LT_FOR_CSTYLE_CLEAN, LT)		/* A <	B */
1672 	EVAL_OP_BIN3(LT_FOR_CSTYLE_CLEAN, LT)		/* A <	B */
1673 	EVAL_OP_BIN4(LT_FOR_CSTYLE_CLEAN, LT)		/* A <	B */
1674 
1675 	EVAL_OP_BIN1(LE_FOR_CSTYLE_CLEAN, LE)		/* A <= B */
1676 	EVAL_OP_BIN2(LE_FOR_CSTYLE_CLEAN, LE)		/* A <= B */
1677 	EVAL_OP_BIN3(LE_FOR_CSTYLE_CLEAN, LE)		/* A <= B */
1678 	EVAL_OP_BIN4(LE_FOR_CSTYLE_CLEAN, LE)		/* A <= B */
1679 
1680 	case ITM_EXPR_NOT:		/*   !A	  */
1681 		return (!(EVAL_EXPR(0)));
1682 	case ITM_EXPR_NEG:		/*   ~A	  */
1683 		return (~(EVAL_EXPR(0)));
1684 	case ITM_EXPR_LOR:		/* A || B */
1685 		if (0 != (num = EVAL_EXPR(0)))
1686 			return	(num);
1687 		if (0 != (num = EVAL_EXPR(1)))
1688 			return	(num);
1689 		return (0);
1690 	case ITM_EXPR_LAND:		/* A && B */
1691 		if (0 == EVAL_EXPR(0))
1692 			return (0);
1693 		if (0 == (num = EVAL_EXPR(1)))
1694 			return (0);
1695 		return	(num);
1696 	case ITM_EXPR_ASSIGN:		/* A  = B */
1697 		num = EVAL_EXPR(1);
1698 		if (expr->data.operand[0].itm_ptr < ist->itm_hdr->reg_num) {
1699 			return (*(ist->regs + expr->data.operand[0].itm_ptr)
1700 				= num);
1701 		} else {
1702 			return (0);
1703 		}
1704 	case ITM_EXPR_IN_EQ:		/* in == A */
1705 		expr_op = ADDR(expr->data.operand[0]);
1706 		switch (expr_op->type) {
1707 		case ITM_EXPR_SEQ:
1708 			if (inbytesleft < expr_op->data.value.size) {
1709 				return (0);
1710 			}
1711 			p = DADDR(&(expr_op->data.value));
1712 			for (i = 0; i < expr_op->data.value.size; i++, p++) {
1713 				if (*p != *(inbuf + i)) {
1714 					return (0);
1715 				}
1716 			}
1717 			return (1);
1718 		default:
1719 			num = EVAL_EXPR(0);
1720 			return (num == *((unsigned char *)inbuf));
1721 		}
1722 	default:
1723 		break;
1724 	}
1725 
1726 	return (0);
1727 
1728 #undef EVAL_EXPR_E
1729 #undef EVAL_EXPR_D
1730 #undef EVAL_EXPR_R
1731 #undef EVAL_EXPR_INVD
1732 #undef EVAL_EXPR
1733 }
1734 
1735 
1736 /*
1737  * maintain ITM reference information
1738  */
1739 static void
1740 itm_ref_free(int fd, void *ptr0, void *ptr1, void *ptr2, size_t len)
1741 {
1742 	int	r;
1743 	r = errno;
1744 	if (0 <= fd) {
1745 		(void) close(fd);
1746 	}
1747 	free(ptr0);
1748 	free(ptr1);
1749 	if (0 < len) {
1750 		(void) munmap(ptr2, len);
1751 	}
1752 	errno = r;
1753 }
1754 
1755 static itm_ref_t *
1756 itm_ref_inc(const char		*itm)
1757 {
1758 	itm_ref_t	*ref;
1759 	itm_hdr_t	*hdr;
1760 	struct stat	st;
1761 	int		fd;
1762 
1763 	fd = open(itm, O_RDONLY, 0);
1764 	if (fd == -1) {
1765 		itm_ref_free(-1, NULL, NULL, NULL, 0);
1766 		return	(NULL);
1767 	}
1768 
1769 	if (fstat(fd, &st) == -1) {
1770 		itm_ref_free(fd, NULL, NULL, NULL, 0);
1771 		return	(NULL);
1772 	}
1773 	hdr = (void *) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
1774 	if (MAP_FAILED == hdr) {
1775 		itm_ref_free(fd, NULL, NULL, NULL, 0);
1776 		return	(NULL);
1777 	}
1778 
1779 	(void) close(fd);
1780 
1781 	ref = malloc(sizeof (itm_ref_t));
1782 	if (NULL == ref) {
1783 		itm_ref_free(-1, NULL, NULL, hdr, st.st_size);
1784 		return	(NULL);
1785 	}
1786 	ref->name = malloc(strlen(itm) + 1);
1787 	if (NULL == ref->name) {
1788 		itm_ref_free(-1, ref, NULL, hdr, st.st_size);
1789 		return	(NULL);
1790 	}
1791 	(void) strcpy(ref->name, itm);
1792 	ref->hdr = hdr;
1793 	ref->len = st.st_size;
1794 
1795 	if ((hdr->ident[0] != ITM_IDENT_0) ||
1796 	    (hdr->ident[1] != ITM_IDENT_1) ||
1797 	    (hdr->ident[2] != ITM_IDENT_2) ||
1798 	    (hdr->ident[3] != ITM_IDENT_3) ||
1799 	    (hdr->spec[0] != ITM_SPEC_0) ||
1800 	    (hdr->spec[1] != ITM_SPEC_1) ||
1801 	    (hdr->spec[2] != ITM_SPEC_2) ||
1802 #if defined(_LITTLE_ENDIAN)
1803 #if defined(_LP64)
1804 	    ((hdr->spec[3] != ITM_SPEC_3_32_LITTLE_ENDIAN) &&
1805 	    (hdr->spec[3] != ITM_SPEC_3_64_LITTLE_ENDIAN)) ||
1806 #else
1807 	    (hdr->spec[3] != ITM_SPEC_3_32_LITTLE_ENDIAN) ||
1808 #endif
1809 #else
1810 #if defined(_LP64)
1811 	    ((hdr->spec[3] != ITM_SPEC_3_32_BIG_ENDIAN) &&
1812 	    (hdr->spec[3] != ITM_SPEC_3_64_BIG_ENDIAN)) ||
1813 #else
1814 	    (hdr->spec[3] != ITM_SPEC_3_32_BIG_ENDIAN) ||
1815 #endif
1816 #endif
1817 	    (hdr->version[0] != ITM_VER_0) ||
1818 	    (hdr->version[1] != ITM_VER_1) ||
1819 	    (hdr->version[2] != ITM_VER_2) ||
1820 	    (hdr->version[3] != ITM_VER_3) ||
1821 	    (((size_t)(hdr->itm_size.itm_ptr)) != st.st_size)) {
1822 		itm_ref_free(-1, ref, ref->name,
1823 				ref->hdr, ref->len);
1824 		errno = ELIBBAD;
1825 		TRACE_MESSAGE('e', ("itm_ref_inc:error=%d\n", errno));
1826 		return	(NULL);
1827 	}
1828 
1829 	return	(ref);
1830 }
1831 
1832 
1833 static void
1834 itm_ref_dec(itm_ref_t	*ref)
1835 {
1836 	(void) munmap((char *)(ref->hdr), ref->len);
1837 	free(ref->name);
1838 	free(ref);
1839 }
1840 
1841 
1842 static void
1843 op_init_default(icv_state_t	*ist)
1844 {
1845 	ist->direc = ADDR(ist->itm_hdr->direc_init_tbl);
1846 	regs_init(ist);
1847 }
1848 
1849 
1850 static void
1851 op_reset_default(icv_state_t	*ist)
1852 {
1853 	ist->direc = ADDR(ist->itm_hdr->direc_init_tbl);
1854 	regs_init(ist);
1855 }
1856 
1857 
1858 static void
1859 regs_init(icv_state_t	*ist)
1860 {
1861 	if (0 < ist->itm_hdr->reg_num) {
1862 		(void) memset(ist->regs, 0,
1863 			(sizeof (itm_num_t)) * ist->itm_hdr->reg_num);
1864 	}
1865 }
1866 
1867 
1868 #if defined(DEBUG)
1869 static void
1870 trace_init()
1871 {
1872 	char	*env_val;
1873 	char	*p;
1874 
1875 	env_val = getenv("ITM_INT_TRACE");
1876 	if (NULL == env_val)
1877 		return;
1878 
1879 	for (p = env_val; *p; p++) {
1880 		trace_option[(*p) & 0x007f] = 1;
1881 	}
1882 }
1883 
1884 static void
1885 trace_message(char	*format, ...)
1886 {
1887 	va_list	ap;
1888 
1889 	va_start(ap, format);
1890 
1891 	(void) vfprintf(stderr, format, ap);
1892 
1893 	va_end(ap);
1894 }
1895 #endif /* DEBUG */
1896