8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / geniconvtbl / geniconvtbl.c
blobd0f9d3cdc9d0846bd87891a8796a280276ff0fda
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
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>
39 #if defined(DEBUG)
40 #include <stdarg.h>
41 #endif /* !DEBUG */
43 #include "iconv_tm.h"
44 #include "hash.h"
48 * Debug
50 #if defined(DEBUG)
52 static void trace_init(void);
53 static void trace_message(char *, ...);
55 static char trace_option[128];
57 #define TRACE(c) (*(trace_option + (c & 0x007f)))
58 #define TRACE_MESSAGE(c, args) ((TRACE(c))? trace_message args: (void)0)
60 #else /* !DEBUG */
62 #define trace_init()
63 #define TRACE()
64 #define TRACE_MESSAGE(c, args)
66 #endif /* !DEBUG */
70 * ITM reference information
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;
80 * struct _icv_state; to keep status
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;
96 * function prototype
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 *);
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 *);
125 static itm_num_t eval_expr(icv_state_t *, itm_place_t,
126 size_t, const unsigned char *, size_t);
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 *);
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 *);
138 * macro definition
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))))
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)--)
155 #define RETVALERR ((size_t)(-1))
156 #define RETVALDIR ((size_t)(-2))
157 #define RETVALBRK ((size_t)(-3))
158 #define RETVALRET ((size_t)(-4))
160 #define UPDATE_ARGS() (*inbuf = ip, \
161 *inbytesleft = ileft, \
162 *outbuf = op, \
163 *outbytesleft = oleft)
166 * Open; called from iconv_open()
168 void *
169 _icv_open(const char *itm)
171 icv_state_t *ist;
172 itm_hdr_t *hdr;
173 itm_ref_t *itm_ref;
174 int r;
177 * for debug
179 trace_init();
182 * _icv_open() primaty task
184 itm_ref = itm_ref_inc(itm);
185 if (NULL == itm_ref) {
186 return ((void *)(-1));
189 if (NULL == (ist = malloc(sizeof (icv_state_t)))) {
190 r = errno;
191 itm_ref_dec(itm_ref);
192 errno = r;
193 return (NULL);
196 ist->itm = itm_ref;
197 ist->itm_hdr = ist->itm->hdr;
198 ist->reg_num = ist->itm->hdr->reg_num;
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 */
209 * brief sanity check
211 if (hdr->itm_size.itm_ptr <= hdr->direc_init_tbl.itm_ptr) {
212 _icv_close(ist);
213 errno = ELIBBAD;
214 return ((void *)(-1));
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));
229 (void) memset(ist->regs, 0,
230 (sizeof (itm_num_t)) * hdr->reg_num);
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);
246 return (ist);
251 * Close; called from iconv_close
253 void
254 _icv_close(icv_state_t *ist)
256 if (NULL == ist) {
257 errno = EBADF;
258 return;
260 itm_ref_dec(ist->itm);
261 free(ist->regs);
262 free(ist);
267 * Actual conversion; called from iconv()
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)
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;
284 if (NULL == ist) {
285 errno = EBADF;
286 TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n", errno));
287 return ((size_t)(-1));
289 if (NULL == inbuf) {
290 ip = NULL;
291 inbuf = &ip;
293 if (NULL == inbytesleft) {
294 ileft = 0;
295 inbytesleft = &ileft;
298 hdr = ist->itm_hdr;
300 retval = 0;
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));
309 * If (NULL == inbuf || NULL == *inbuf) then this conversion is
310 * placed into initial state.
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);
320 } else {
321 op_reset_default(ist);
323 return ((size_t)(0));
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;
334 map_hdr = (itm_map_idx_fix_hdr_t *)(ist->direc + 1);
335 map = (char *)(map_hdr + 1);
337 if (1 == map_hdr->default_error) {
338 retval = map_i_f(ist->direc, inbuf, inbytesleft,
339 outbuf, outbytesleft, 0);
340 return (retval);
343 ip = *inbuf;
344 ileft = *inbytesleft;
345 op = *outbuf;
346 oleft = *outbytesleft;
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);
356 *(op++) = *(map + *(ip++));
357 ileft--;
358 oleft--;
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);
381 #if defined(OP_DEPTH_MAX)
382 ist->op_depth = 0;
383 #endif /* OP_DEPTH_MAX */
387 * Main loop; basically 1 loop per 1 output character
389 retry_cond_eval:
390 while (0 < *inbytesleft) {
391 itm_tbl_hdr_t *direc_hdr;
392 itm_direc_t *direc;
393 long i;
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));
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;
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;
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);
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));
475 if ((size_t)(-1) == retval) {
476 return (retval);
478 break;
479 default: /* never */
480 errno = ELIBBAD;
481 TRACE_MESSAGE('e',
482 ("_icv_iconv:error=%d\n", errno));
483 return ((size_t)(-1));
485 break;
488 return (retval);
494 * map-indexed-fixed
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)
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;
511 TRACE_MESSAGE('i', ("map_i_f\n"));
513 map_hdr = (itm_map_idx_fix_hdr_t *)(tbl_hdr + 1);
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));
522 j = 0;
523 for (i = 0; i < map_hdr->source_len; i++) {
524 GET(c);
525 j = ((j << 8) | c);
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));
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));
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));
554 } else {
555 p = ((*inbuf) - map_hdr->source_len);
556 for (i = 0; i < map_hdr->source_len; i++) {
557 PUT(*(p + i));
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);
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));
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));
587 } while ((0 < *inbytesleft) && (0 == once));
589 return (size_t)(0);
594 * map-lookup-fixed
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)
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;
615 TRACE_MESSAGE('i', ("map_l_f\n"));
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;
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));
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;
637 if (*p < *(unsigned char *)(*inbuf + i)) {
638 result = 1;
639 break;
642 if (result < 0) {
643 high = mid;
644 } else if (0 < result) {
645 low = mid + 1;
646 } else { /* 0 == result */
647 break;
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));
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));
670 p++;
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));
678 DISCARD(map_hdr->source_len);
680 for (i = 0; i < map_hdr->result_len; i++) {
681 PUT(*(p + i));
683 } while ((0 < *inbytesleft) && (0 == once));
685 return ((size_t)(0));
690 * map-hash-lookup
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)
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;
717 TRACE_MESSAGE('i', ("map_hash\n"));
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;
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));
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;
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;
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;
771 if (*p < *(q + i)) {
772 result = 1;
773 break;
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;
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));
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));
810 p++;
813 if (*outbytesleft < result_len) {
814 errno = E2BIG;
815 TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno));
816 return ((size_t)(-1));
818 DISCARD(source_len);
820 for (i = 0; i < result_len; i++) {
821 PUT(*(p + i));
823 } while ((0 < *inbytesleft) && (0 == once));
825 return ((size_t)(0));
830 * map-dense_encoding-lookup
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)
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;
850 TRACE_MESSAGE('i', ("map_d_e_l\n"));
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);
859 byte_seq_min = (unsigned char *)(map_hdr + 1);
860 byte_seq_max = byte_seq_min + map_hdr->source_len;
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));
869 j = hash_dense_encoding(*inbuf, map_hdr->source_len,
870 byte_seq_min, byte_seq_max);
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));
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));
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));
892 } else {
893 p = *inbuf;
894 for (i = 0; i < map_hdr->source_len; i++) {
895 PUT(*(p + i));
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));
908 p = (map_ptr + (map_hdr->result_len * j));
909 for (i = 0; i < map_hdr->result_len; i++) {
910 PUT(*(p + i));
913 DISCARD(map_hdr->source_len);
914 } while ((0 < *inbytesleft) && (0 == once));
916 return ((size_t)(0));
922 * Evaluate condition table
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
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;
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;
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;
980 if (1 == retval) {
981 break;
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;
990 break; /* continue */
991 case ITM_COND_ESCAPESEQ:
993 * if escape sequence occur,
994 * change ist->default_action and return 2.
995 * never return 1.
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));
1008 retval = 0;
1009 if (*inbytesleft < eh->len_min) {
1010 break;
1012 for (j = 0, d = (itm_data_t *)(eh + 1);
1013 j < eth->number;
1014 j++, d++) {
1015 if (*inbytesleft < d->size) {
1016 continue;
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;
1034 if (0 == retval) {
1035 goto eval_cond_return;
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;
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;
1055 eval_cond_return:
1056 return (retval);
1060 * Evaluate operation table
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)
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;
1078 retval = 0;
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);
1086 ist->op_depth += 1;
1087 #endif /* OP_DEPTH_MAX */
1089 op_hdr = ADDR(op_tbl_place);
1090 operation = (itm_op_t *)(op_hdr + 1);
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);
1114 #if defined(OP_DEPTH_MAX)
1115 ist->op_depth -= 1;
1116 #endif /* OP_DEPTH_MAX */
1117 return (retval);
1122 * Evaluate single operation
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)
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;
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)))))
1160 retval = 0;
1162 operation = (itm_op_t *)ADDR2(op_place);
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));
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));
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));
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));
1217 p = DADDR(&(expr->data.value));
1218 for (; 0 < z; --z, p++) {
1219 PUT(*p);
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));
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));
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);
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);
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);
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);
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;
1316 * Based on what is the maptype, we call the corresponding
1317 * mapping function.
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:
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.
1346 errno = EBADF;
1347 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1348 retval = (size_t)-1;
1349 break;
1352 if ((size_t)(-1) == retval) {
1353 (*outbytesleft) += i;
1354 (*outbuf) -= i;
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);
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;
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;
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);
1418 return (retval);
1420 #undef EVAL_EXPR
1425 * Evaluate expression
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)
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;
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)))))
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));
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)
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)
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)
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)
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); \
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)
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)
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)
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)
1529 expr = ADDR(expr_place);
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);
1546 for (i = 0, num = 0; i < expr->data.value.size; i++, p++) {
1547 num = ((num << 8) | *p);
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);
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);
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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);
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);
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);
1711 return (1);
1712 default:
1713 num = EVAL_EXPR(0);
1714 return (num == *((unsigned char *)inbuf));
1716 default:
1717 break;
1720 return (0);
1722 #undef EVAL_EXPR_E
1723 #undef EVAL_EXPR_D
1724 #undef EVAL_EXPR_R
1725 #undef EVAL_EXPR_INVD
1726 #undef EVAL_EXPR
1731 * maintain ITM reference information
1733 static void
1734 itm_ref_free(int fd, void *ptr0, void *ptr1, void *ptr2, size_t len)
1736 int r;
1737 r = errno;
1738 if (0 <= fd) {
1739 (void) close(fd);
1741 free(ptr0);
1742 free(ptr1);
1743 if (0 < len) {
1744 (void) munmap(ptr2, len);
1746 errno = r;
1749 static itm_ref_t *
1750 itm_ref_inc(const char *itm)
1752 itm_ref_t *ref;
1753 itm_hdr_t *hdr;
1754 struct stat st;
1755 int fd;
1757 fd = open(itm, O_RDONLY, 0);
1758 if (fd == -1) {
1759 itm_ref_free(-1, NULL, NULL, NULL, 0);
1760 return (NULL);
1763 if (fstat(fd, &st) == -1) {
1764 itm_ref_free(fd, NULL, NULL, NULL, 0);
1765 return (NULL);
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);
1773 (void) close(fd);
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);
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);
1785 (void) strcpy(ref->name, itm);
1786 ref->hdr = hdr;
1787 ref->len = st.st_size;
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);
1822 return (ref);
1826 static void
1827 itm_ref_dec(itm_ref_t *ref)
1829 (void) munmap((char *)(ref->hdr), ref->len);
1830 free(ref->name);
1831 free(ref);
1835 static void
1836 op_init_default(icv_state_t *ist)
1838 ist->direc = ADDR(ist->itm_hdr->direc_init_tbl);
1839 regs_init(ist);
1843 static void
1844 op_reset_default(icv_state_t *ist)
1846 ist->direc = ADDR(ist->itm_hdr->direc_init_tbl);
1847 regs_init(ist);
1851 static void
1852 regs_init(icv_state_t *ist)
1854 if (0 < ist->itm_hdr->reg_num) {
1855 (void) memset(ist->regs, 0,
1856 (sizeof (itm_num_t)) * ist->itm_hdr->reg_num);
1861 #if defined(DEBUG)
1862 static void
1863 trace_init()
1865 char *env_val;
1866 char *p;
1868 env_val = getenv("ITM_INT_TRACE");
1869 if (NULL == env_val)
1870 return;
1872 for (p = env_val; *p; p++) {
1873 trace_option[(*p) & 0x007f] = 1;
1877 static void
1878 trace_message(char *format, ...)
1880 va_list ap;
1882 va_start(ap, format);
1884 (void) vfprintf(stderr, format, ap);
1886 va_end(ap);
1888 #endif /* DEBUG */