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