cmd-inet/usr.sbin: remove -Wno-implicit-function-declaration
[unleashed.git] / usr / src / cmd / geniconvtbl / geniconvtbl.c
blob03d261afb0a8f24048801a2b4a7f28b58c7ba07f
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 #include <stdio.h>
27 #include <stdlib.h>
28 #include <strings.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/mman.h>
35 #include <synch.h>
37 #if defined(DEBUG)
38 #include <stdarg.h>
39 #endif /* !DEBUG */
41 #include "iconv_tm.h"
42 #include "hash.h"
46 * Debug
48 #if defined(DEBUG)
50 static void trace_init(void);
51 static void trace_message(char *, ...);
53 static char trace_option[128];
55 #define TRACE(c) (*(trace_option + (c & 0x007f)))
56 #define TRACE_MESSAGE(c, args) ((TRACE(c))? trace_message args: (void)0)
58 #else /* !DEBUG */
60 #define trace_init()
61 #define TRACE()
62 #define TRACE_MESSAGE(c, args)
64 #endif /* !DEBUG */
68 * ITM reference information
70 typedef struct _itm_ref {
71 char *name; /* ITM file name */
72 itm_hdr_t *hdr; /* address of ITM */
73 size_t len; /* length of ITM */
74 } itm_ref_t;
78 * struct _icv_state; to keep status
80 typedef struct _icv_state {
81 struct _itm_ref *itm; /* reference to ITM */
82 itm_hdr_t *itm_hdr; /* address of ITM */
83 itm_tbl_hdr_t *direc; /* current direction */
84 itm_place_t default_action; /* default action */
85 itm_num_t *regs; /* register */
86 itm_num_t reg_num; /* number of register */
87 #if defined(OP_DEPTH_MAX)
88 int op_depth; /* depth of operation */
89 #endif /* OP_DEPTH_MAX */
90 } icv_state_t;
94 * function prototype
96 void * _icv_open(const char *);
97 void _icv_close(icv_state_t *);
98 size_t _icv_iconv(icv_state_t *, const unsigned char **,
99 size_t *, unsigned char **, size_t *);
101 static size_t map_i_f(itm_tbl_hdr_t *,
102 const unsigned char **, size_t *,
103 unsigned char **, size_t *, long);
104 static size_t map_l_f(itm_tbl_hdr_t *,
105 const unsigned char **, size_t *,
106 unsigned char **, size_t *, long);
107 static size_t map_h_l(itm_tbl_hdr_t *,
108 const unsigned char **, size_t *,
109 unsigned char **, size_t *, long);
110 static size_t map_d_e_l(itm_tbl_hdr_t *,
111 const unsigned char **, size_t *,
112 unsigned char **, size_t *, long);
113 static size_t eval_cond_tbl(icv_state_t *, itm_place_t,
114 const unsigned char **, size_t *,
115 size_t, itm_direc_t *);
116 static size_t eval_op_tbl(icv_state_t *, itm_place_t,
117 const unsigned char **, size_t *,
118 unsigned char **, size_t *);
119 static size_t eval_op(icv_state_t *, itm_place2_t,
120 const unsigned char **, size_t *,
121 unsigned char **, size_t *);
123 static itm_num_t eval_expr(icv_state_t *, itm_place_t,
124 size_t, const unsigned char *, size_t);
126 static void itm_ref_free(int, void *, void *, void *, size_t);
127 static itm_ref_t *itm_ref_inc(const char *);
128 static void itm_ref_dec(itm_ref_t *);
130 static void op_init_default(icv_state_t *);
131 static void op_reset_default(icv_state_t *);
132 static void regs_init(icv_state_t *);
136 * macro definition
139 #define ADDR(place) ((void *)(((char *)(ist->itm_hdr)) +\
140 ((itm_place2_t)(place.itm_ptr))))
141 #define ADDR2(place2) ((void *)(((char *)(ist->itm_hdr)) +\
142 ((itm_place2_t)(place2))))
143 #define DADDR(n) (((n)->size <= (sizeof ((n)->place.itm_64d))) ? \
144 ((unsigned char *)(&((n)->place.itm_64d))) :\
145 ((unsigned char *)(ADDR((n)->place))))
147 #define REG(n) (*(ist->regs + (n)))
148 #define DISCARD(c) (((*inbuf) = (void *)((*inbuf) + (c))),\
149 ((*inbytesleft) -= (c)))
150 #define GET(c) ((c) = **inbuf, (*inbuf)++, (*inbytesleft)--)
151 #define PUT(c) (**outbuf = (c), (*outbuf)++, (*outbytesleft)--)
153 #define RETVALERR ((size_t)(-1))
154 #define RETVALDIR ((size_t)(-2))
155 #define RETVALBRK ((size_t)(-3))
156 #define RETVALRET ((size_t)(-4))
158 #define UPDATE_ARGS() (*inbuf = ip, \
159 *inbytesleft = ileft, \
160 *outbuf = op, \
161 *outbytesleft = oleft)
164 * Open; called from iconv_open()
166 void *
167 _icv_open(const char *itm)
169 icv_state_t *ist;
170 itm_hdr_t *hdr;
171 itm_ref_t *itm_ref;
172 int r;
175 * for debug
177 trace_init();
180 * _icv_open() primaty task
182 itm_ref = itm_ref_inc(itm);
183 if (NULL == itm_ref) {
184 return ((void *)(-1));
187 if (NULL == (ist = malloc(sizeof (icv_state_t)))) {
188 r = errno;
189 itm_ref_dec(itm_ref);
190 errno = r;
191 return (NULL);
194 ist->itm = itm_ref;
195 ist->itm_hdr = ist->itm->hdr;
196 ist->reg_num = ist->itm->hdr->reg_num;
198 hdr = ist->itm->hdr;
199 ist->direc = ADDR(hdr->direc_init_tbl);
200 ist->default_action.itm_64d = 0;
201 #if defined(OP_DEPTH_MAX)
202 ist->op_depth = 0;
203 #endif /* OP_DEPTH_MAX */
207 * brief sanity check
209 if (hdr->itm_size.itm_ptr <= hdr->direc_init_tbl.itm_ptr) {
210 _icv_close(ist);
211 errno = ELIBBAD;
212 return ((void *)(-1));
216 /* allocate register region */
217 if (hdr->reg_num <= 0) {
218 ist->regs = NULL;
219 } else {
220 ist->regs = malloc((sizeof (itm_num_t)) * hdr->reg_num);
221 if (NULL == ist->regs) {
222 r = errno;
223 _icv_close(ist);
224 errno = r;
225 return ((void *)(-1));
227 (void) memset(ist->regs, 0,
228 (sizeof (itm_num_t)) * hdr->reg_num);
232 /* evaluate init operation */
233 if (0 != ist->itm_hdr->op_init_tbl.itm_ptr) {
234 const unsigned char *ip = NULL;
235 size_t ileft = 0;
236 unsigned char *op = NULL;
237 size_t oleft = 0;
238 (void) eval_op_tbl(ist, ist->itm_hdr->op_init_tbl, &ip,
239 &ileft, &op, &oleft);
240 } else {
241 op_init_default(ist);
244 return (ist);
249 * Close; called from iconv_close
251 void
252 _icv_close(icv_state_t *ist)
254 if (NULL == ist) {
255 errno = EBADF;
256 return;
258 itm_ref_dec(ist->itm);
259 free(ist->regs);
260 free(ist);
265 * Actual conversion; called from iconv()
267 size_t
268 _icv_iconv(
269 icv_state_t *ist,
270 const unsigned char **inbuf,
271 size_t *inbytesleft,
272 unsigned char **outbuf,
273 size_t *outbytesleft)
275 size_t retval;
276 itm_hdr_t *hdr;
277 itm_type_t type;
278 const unsigned char *ip;
279 size_t ileft;
280 itm_place_t action;
282 if (NULL == ist) {
283 errno = EBADF;
284 TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n", errno));
285 return ((size_t)(-1));
287 if (NULL == inbuf) {
288 ip = NULL;
289 inbuf = &ip;
291 if (NULL == inbytesleft) {
292 ileft = 0;
293 inbytesleft = &ileft;
296 hdr = ist->itm_hdr;
298 retval = 0;
300 TRACE_MESSAGE('i', ("_icv_iconv(inbuf=%p inbytesleft=%ld "
301 "outbuf=%p outbytesleft=%ld)\n", (NULL == inbuf) ? 0 : *inbuf,
302 (NULL == inbytesleft) ? 0 : *inbytesleft,
303 (NULL == outbuf) ? 0 : *outbuf,
304 (NULL == outbytesleft) ? 0 : *outbytesleft));
307 * If (NULL == inbuf || NULL == *inbuf) then this conversion is
308 * placed into initial state.
310 if ((NULL == inbuf) || (NULL == *inbuf)) {
311 if (0 != hdr->op_reset_tbl.itm_ptr) {
312 ist->direc = ADDR(hdr->direc_init_tbl);
313 retval = eval_op_tbl(ist, hdr->op_reset_tbl, inbuf,
314 inbytesleft, outbuf, outbytesleft);
315 if ((size_t)(-1) == retval) {
316 return (retval);
318 } else {
319 op_reset_default(ist);
321 return ((size_t)(0));
324 if (ITM_TBL_MAP_INDEX_FIXED_1_1 == ist->direc->type) {
325 itm_map_idx_fix_hdr_t *map_hdr;
326 char *map;
327 const unsigned char *ip;
328 size_t ileft;
329 unsigned char *op;
330 size_t oleft;
332 map_hdr = (itm_map_idx_fix_hdr_t *)(ist->direc + 1);
333 map = (char *)(map_hdr + 1);
335 if (1 == map_hdr->default_error) {
336 retval = map_i_f(ist->direc, inbuf, inbytesleft,
337 outbuf, outbytesleft, 0);
338 return (retval);
341 ip = *inbuf;
342 ileft = *inbytesleft;
343 op = *outbuf;
344 oleft = *outbytesleft;
346 while (1 <= ileft) {
347 if (oleft < 1) {
348 UPDATE_ARGS();
349 errno = E2BIG;
350 TRACE_MESSAGE('e', ("_icv_iconv: error=%d\n",
351 errno));
352 return ((size_t)-1);
354 *(op++) = *(map + *(ip++));
355 ileft--;
356 oleft--;
359 UPDATE_ARGS();
360 return (0);
361 } else if (ITM_TBL_MAP_INDEX_FIXED == ist->direc->type) {
362 retval = map_i_f(ist->direc, inbuf, inbytesleft,
363 outbuf, outbytesleft, 0);
364 return (retval);
365 } else if (ITM_TBL_MAP_HASH == ist->direc->type) {
366 retval = map_h_l(ist->direc, inbuf, inbytesleft,
367 outbuf, outbytesleft, 0);
368 return (retval);
369 } else if (ITM_TBL_MAP_DENSE_ENC == ist->direc->type) {
370 retval = map_d_e_l(ist->direc, inbuf, inbytesleft,
371 outbuf, outbytesleft, 0);
372 return (retval);
373 } else if (ITM_TBL_MAP_LOOKUP == ist->direc->type) {
374 retval = map_l_f(ist->direc, inbuf, inbytesleft,
375 outbuf, outbytesleft, 0);
376 return (retval);
379 #if defined(OP_DEPTH_MAX)
380 ist->op_depth = 0;
381 #endif /* OP_DEPTH_MAX */
385 * Main loop; basically 1 loop per 1 output character
387 retry_cond_eval:
388 while (0 < *inbytesleft) {
389 itm_tbl_hdr_t *direc_hdr;
390 itm_direc_t *direc;
391 long i;
393 direc_hdr = ist->direc;
394 direc = (itm_direc_t *)(ist->direc + 1);
395 for (i = 0; /* NULL */; i++, direc++) {
396 if (i >= direc_hdr->number) {
397 if (0 == ist->default_action.itm_ptr) {
398 errno = EILSEQ;
399 TRACE_MESSAGE('e',
400 ("_icv_iconv:error=%d\n", errno));
401 return ((size_t)(-1));
406 action = ist->default_action;
407 type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
408 TRACE_MESSAGE('E',
409 ("escape seq (default action=%6p, "
410 "type=%ld) executing\n",
411 action.itm_ptr, type));
412 } else if (0 != direc->condition.itm_ptr) {
413 retval = eval_cond_tbl(ist, direc->condition,
414 inbuf, inbytesleft, *outbytesleft, direc);
415 if ((size_t)(0) == retval) {
416 continue;
417 } else if ((size_t)(-1) == retval) {
418 return (retval);
419 } else if ((size_t)(2) == retval) {
420 goto retry_cond_eval;
422 action = direc->action;
423 type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
424 } else {
425 action = direc->action;
426 type = ((itm_tbl_hdr_t *)(ADDR(action)))->type;
429 TRACE_MESSAGE('a',
430 ("inbytesleft=%ld; type=%ld:action=%p\n",
431 *inbytesleft, type, action.itm_ptr));
432 switch (ITM_TBL_MASK & type) {
433 case ITM_TBL_OP:
434 retval = eval_op_tbl(ist, action,
435 inbuf, inbytesleft, outbuf, outbytesleft);
436 if ((size_t)(-1) == retval) {
437 return (retval);
439 break;
440 case ITM_TBL_DIREC:
441 ist->direc = ADDR(action);
442 break;
443 case ITM_TBL_MAP:
444 switch (type) {
445 case ITM_TBL_MAP_INDEX_FIXED_1_1:
446 case ITM_TBL_MAP_INDEX_FIXED:
447 retval = map_i_f(ADDR(action),
448 inbuf, inbytesleft,
449 outbuf, outbytesleft, 1);
450 break;
451 case ITM_TBL_MAP_HASH:
452 retval = map_h_l(ADDR(action),
453 inbuf, inbytesleft,
454 outbuf, outbytesleft, 1);
455 break;
456 case ITM_TBL_MAP_DENSE_ENC:
457 retval = map_d_e_l(ADDR(action),
458 inbuf, inbytesleft,
459 outbuf, outbytesleft, 1);
460 break;
461 case ITM_TBL_MAP_LOOKUP:
462 retval = map_l_f(ADDR(action),
463 inbuf, inbytesleft,
464 outbuf, outbytesleft, 1);
465 break;
466 default:
467 errno = ELIBBAD;
468 TRACE_MESSAGE('e',
469 ("_icv_iconv:error=%d\n", errno));
470 return ((size_t)(-1));
473 if ((size_t)(-1) == retval) {
474 return (retval);
476 break;
477 default: /* never */
478 errno = ELIBBAD;
479 TRACE_MESSAGE('e',
480 ("_icv_iconv:error=%d\n", errno));
481 return ((size_t)(-1));
483 break;
486 return (retval);
492 * map-indexed-fixed
494 static size_t
495 map_i_f(
496 itm_tbl_hdr_t *tbl_hdr,
497 const unsigned char **inbuf,
498 size_t *inbytesleft,
499 unsigned char **outbuf,
500 size_t *outbytesleft,
501 long once)
503 itm_map_idx_fix_hdr_t *map_hdr;
504 long i;
505 unsigned char c;
506 unsigned long j;
507 const unsigned char *p;
509 TRACE_MESSAGE('i', ("map_i_f\n"));
511 map_hdr = (itm_map_idx_fix_hdr_t *)(tbl_hdr + 1);
513 do {
514 if (*inbytesleft < map_hdr->source_len) {
515 errno = EINVAL;
516 TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
517 return ((size_t)(-1));
520 j = 0;
521 for (i = 0; i < map_hdr->source_len; i++) {
522 GET(c);
523 j = ((j << 8) | c);
526 if (((j < map_hdr->start.itm_ptr) ||
527 (map_hdr->end.itm_ptr < j)) &&
528 (0 < map_hdr->default_error)) {
529 errno = EILSEQ;
530 (*inbuf) = (void*) ((*inbuf) - map_hdr->source_len);
531 (*inbytesleft) += map_hdr->source_len;
532 TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
533 return ((size_t)(-1));
536 if (*outbytesleft < map_hdr->result_len) {
537 errno = E2BIG;
538 (*inbuf) = (void *)((*inbuf) - map_hdr->source_len);
539 (*inbytesleft) += map_hdr->source_len;
540 TRACE_MESSAGE('e', ("map_i_f:error=%d\n", errno));
541 return ((size_t)(-1));
544 if ((j < map_hdr->start.itm_ptr) ||
545 (map_hdr->end.itm_ptr < j)) {
546 if (0 == map_hdr->default_error) {
547 p = (((unsigned char *)(map_hdr + 1)) +
548 (map_hdr->result_len * (tbl_hdr->number)));
549 for (i = 0; i < map_hdr->result_len; i++) {
550 PUT(*(p + i));
552 } else {
553 p = ((*inbuf) - map_hdr->source_len);
554 for (i = 0; i < map_hdr->source_len; i++) {
555 PUT(*(p + i));
558 } else {
559 char *map_error;
560 map_error = (((char *)(map_hdr + 1)) +
561 (map_hdr->result_len * (tbl_hdr->number)) +
562 (j - map_hdr->start.itm_ptr));
563 if (0 == map_hdr->default_error) {
564 map_error = (void *)
565 (map_error + map_hdr->result_len);
567 if (((1 == map_hdr->default_error) ||
568 (0 < map_hdr->error_num)) &&
569 (0 != *(map_error))) {
570 errno = EILSEQ;
571 (*inbuf) = (void *)
572 ((*inbuf) - map_hdr->source_len);
573 (*inbytesleft) += map_hdr->source_len;
574 TRACE_MESSAGE('e',
575 ("map_i_f:error=%d\n", errno));
576 return ((size_t)(-1));
578 p = (((unsigned char *)(map_hdr + 1)) +
579 (map_hdr->result_len *
580 (j - map_hdr->start.itm_ptr)));
581 for (i = 0; i < map_hdr->result_len; i++) {
582 PUT(*(p + i));
585 } while ((0 < *inbytesleft) && (0 == once));
587 return (size_t)(0);
592 * map-lookup-fixed
594 static size_t
595 map_l_f(
596 itm_tbl_hdr_t *tbl_hdr,
597 const unsigned char **inbuf,
598 size_t *inbytesleft,
599 unsigned char **outbuf,
600 size_t *outbytesleft,
601 long once)
603 itm_map_lookup_hdr_t *map_hdr;
604 long i;
605 unsigned char *map;
606 const unsigned char *p;
607 long high;
608 long mid;
609 long low;
610 long result;
611 itm_size_t pair_size;
613 TRACE_MESSAGE('i', ("map_l_f\n"));
615 map_hdr = (itm_map_lookup_hdr_t *)(tbl_hdr + 1);
616 map = (unsigned char *)(map_hdr + 1);
617 pair_size = map_hdr->source_len + 1 + map_hdr->result_len;
619 do {
620 if (*inbytesleft < map_hdr->source_len) {
621 errno = EINVAL;
622 TRACE_MESSAGE('e', ("map_l_f:error=%d\n", errno));
623 return ((size_t)(-1));
626 for (low = 0, high = tbl_hdr->number; low < high; ) {
627 mid = (low + high) / 2;
628 p = map + (pair_size * mid);
629 for (i = 0, result = 0; i < map_hdr->source_len;
630 i++, p++) {
631 if (*(unsigned char *)(*inbuf + i) < *p) {
632 result = -1;
633 break;
635 if (*p < *(unsigned char *)(*inbuf + i)) {
636 result = 1;
637 break;
640 if (result < 0) {
641 high = mid;
642 } else if (0 < result) {
643 low = mid + 1;
644 } else { /* 0 == result */
645 break;
649 if (0 != result) {
650 if (map_hdr->default_error < 0) {
651 p = *inbuf;
652 } else if (0 == map_hdr->default_error) {
653 p = map + (pair_size * tbl_hdr->number) +
654 map_hdr->source_len + 1;
655 } else if (0 < map_hdr->default_error) {
656 errno = EILSEQ;
657 TRACE_MESSAGE('e', ("map_l_f:error=%d\n",
658 errno));
659 return ((size_t)(-1));
661 } else {
662 if (0 != (*p)) {
663 errno = EILSEQ;
664 TRACE_MESSAGE('e', ("map_l_f:error=%d\n",
665 errno));
666 return ((size_t)(-1));
668 p++;
671 if (*outbytesleft < map_hdr->result_len) {
672 errno = E2BIG;
673 TRACE_MESSAGE('e', ("map_l_f:error=%d\n", errno));
674 return ((size_t)(-1));
676 DISCARD(map_hdr->source_len);
678 for (i = 0; i < map_hdr->result_len; i++) {
679 PUT(*(p + i));
681 } while ((0 < *inbytesleft) && (0 == once));
683 return ((size_t)(0));
688 * map-hash-lookup
690 static size_t
691 map_h_l(
692 itm_tbl_hdr_t *tbl_hdr,
693 const unsigned char **inbuf,
694 size_t *inbytesleft,
695 unsigned char **outbuf,
696 size_t *outbytesleft,
697 long once)
699 itm_map_hash_hdr_t *map_hdr;
700 long i;
701 unsigned char *map_error;
702 unsigned char *map_hash;
703 unsigned char *map_of;
704 const unsigned char *p;
705 const unsigned char *q;
706 long high;
707 long mid;
708 long low;
709 long result;
710 itm_size_t pair_size;
711 itm_size_t hash_value;
712 itm_size_t source_len;
713 itm_size_t result_len;
715 TRACE_MESSAGE('i', ("map_hash\n"));
717 map_hdr = (itm_map_hash_hdr_t *)(tbl_hdr + 1);
718 map_error = (unsigned char *)(map_hdr + 1);
719 map_hash = (map_error + map_hdr->hash_tbl_num);
720 map_of = map_hash + map_hdr->hash_tbl_size;
721 pair_size = map_hdr->source_len + 1 + map_hdr->result_len;
722 source_len = map_hdr->source_len;
723 result_len = map_hdr->result_len;
725 do {
726 if (*inbytesleft < source_len) {
727 errno = EINVAL;
728 TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno));
729 return ((size_t)(-1));
732 result = 1;
733 q = *inbuf;
734 hash_value = hash((const char *)(q), source_len,
735 map_hdr->hash_tbl_num);
736 p = map_hash + (pair_size * hash_value);
737 if (1 == *(map_error + hash_value)) {
738 for (i = 0, result = 0; i < source_len; i++) {
739 if (*(q + i) != *(p++)) {
740 result = -2;
741 break;
744 TRACE_MESSAGE('G',
745 ("(h=%d): find pair without conflict\n",
746 hash_value));
747 } else if (0 == *(map_error + hash_value)) {
748 TRACE_MESSAGE('G', ("(h=%d): No Pair\n", hash_value));
749 result = -3;
750 } else /* if (0 < *(map_error + hash_value)) */ {
751 for (i = 0, result = 0; i < source_len; i++) {
752 if (*(q + i) != *(p++)) {
753 result = 1;
754 break;
757 if (0 < result) {
758 for (low = 0, high = map_hdr->hash_of_num;
759 low < high; /* NOP */) {
760 mid = (low + high) / 2;
761 p = map_of + (pair_size * mid);
762 for (i = 0, result = 0;
763 i < source_len;
764 i++, p++) {
765 if (*(q + i) < *p) {
766 result = -1;
767 break;
769 if (*p < *(q + i)) {
770 result = 1;
771 break;
774 if (result < 0) {
775 high = mid;
776 } else if (0 < result) {
777 low = mid + 1;
778 } else { /* 0 == result */
779 TRACE_MESSAGE('G', ("(h=%d): "
780 "find data on out of "
781 "hashtable with CONFLICT\n",
782 hash_value));
783 break;
788 if (0 != result) {
789 if (map_hdr->default_error < 0) {
790 p = q;
791 } else if (0 == map_hdr->default_error) {
792 p = map_of + map_hdr->hash_of_size;
793 } else if (0 < map_hdr->default_error) {
794 TRACE_MESSAGE('G', ("(h=%d): NO PAIR\n",
795 hash_value));
796 errno = EILSEQ;
797 TRACE_MESSAGE('e',
798 ("map_h_l:error=%d\n", errno));
799 return ((size_t)(-1));
801 } else {
802 if (0 != (*p)) {
803 errno = EILSEQ;
804 TRACE_MESSAGE('G', (" : error pair\n"));
805 TRACE_MESSAGE('e', ("map_l_f:error\n", errno));
806 return ((size_t)(-1));
808 p++;
811 if (*outbytesleft < result_len) {
812 errno = E2BIG;
813 TRACE_MESSAGE('e', ("map_h_l:error=%d\n", errno));
814 return ((size_t)(-1));
816 DISCARD(source_len);
818 for (i = 0; i < result_len; i++) {
819 PUT(*(p + i));
821 } while ((0 < *inbytesleft) && (0 == once));
823 return ((size_t)(0));
828 * map-dense_encoding-lookup
830 static size_t
831 map_d_e_l(
832 itm_tbl_hdr_t *tbl_hdr,
833 const unsigned char **inbuf,
834 size_t *inbytesleft,
835 unsigned char **outbuf,
836 size_t *outbytesleft,
837 long once)
839 itm_map_dense_enc_hdr_t *map_hdr;
840 long i;
841 itm_num_t j;
842 const unsigned char *p;
843 unsigned char *map_ptr;
844 unsigned char *map_error;
845 unsigned char *byte_seq_min;
846 unsigned char *byte_seq_max;
848 TRACE_MESSAGE('i', ("map_d_e_l\n"));
850 map_hdr = (itm_map_dense_enc_hdr_t *)(tbl_hdr + 1);
851 map_ptr = ((unsigned char *)(map_hdr + 1) + map_hdr->source_len +
852 map_hdr->source_len);
853 map_error = (map_ptr + (tbl_hdr->number * map_hdr->result_len));
854 if (0 == map_hdr->default_error) {
855 map_error = (void *)(map_error + map_hdr->result_len);
857 byte_seq_min = (unsigned char *)(map_hdr + 1);
858 byte_seq_max = byte_seq_min + map_hdr->source_len;
860 do {
861 if (*inbytesleft < map_hdr->source_len) {
862 errno = EINVAL;
863 TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
864 return ((size_t)(-1));
867 j = hash_dense_encoding(*inbuf, map_hdr->source_len,
868 byte_seq_min, byte_seq_max);
870 if (((j < 0) || (tbl_hdr->number < j)) &&
871 (0 < map_hdr->default_error)) {
872 errno = EILSEQ;
873 TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
874 return ((size_t)(-1));
877 if (*outbytesleft < map_hdr->result_len) {
878 errno = E2BIG;
879 TRACE_MESSAGE('e', ("map_d_e_l:error=%d\n", errno));
880 return ((size_t)(-1));
883 if ((j < 0) || (tbl_hdr->number < j)) {
884 if (0 == map_hdr->default_error) {
885 p = (map_ptr + (tbl_hdr->number *
886 map_hdr->result_len));
887 for (i = 0; i < map_hdr->result_len; i++) {
888 PUT(*(p + i));
890 } else {
891 p = *inbuf;
892 for (i = 0; i < map_hdr->source_len; i++) {
893 PUT(*(p + i));
896 } else {
897 if ((1 == map_hdr->default_error) ||
898 (0 < map_hdr->error_num)) {
899 if (0 != *(map_error + j)) {
900 errno = EILSEQ;
901 TRACE_MESSAGE('e',
902 ("map_d_e_l:error=%d\n", errno));
903 return ((size_t)(-1));
906 p = (map_ptr + (map_hdr->result_len * j));
907 for (i = 0; i < map_hdr->result_len; i++) {
908 PUT(*(p + i));
911 DISCARD(map_hdr->source_len);
912 } while ((0 < *inbytesleft) && (0 == once));
914 return ((size_t)(0));
920 * Evaluate condition table
923 static size_t
924 eval_cond_tbl(
925 icv_state_t *ist,
926 itm_place_t cond_place,
927 const unsigned char **inbuf,
928 size_t *inbytesleft,
929 size_t outbytesleft,
930 itm_direc_t *direc
933 itm_tbl_hdr_t *cond_hdr;
934 itm_cond_t *cond;
935 long i;
936 long j;
937 long k;
938 size_t retval;
939 itm_tbl_hdr_t *rth;
940 itm_range_hdr_t *rtsh;
941 unsigned char *p;
942 itm_tbl_hdr_t *eth;
943 itm_escapeseq_hdr_t *eh;
944 itm_data_t *d;
945 const unsigned char *ip;
946 size_t ileft;
948 retval = 0;
949 ip = *inbuf;
950 ileft = *inbytesleft;
951 cond_hdr = ADDR(cond_place);
952 cond = (itm_cond_t *)(cond_hdr + 1);
953 for (i = 0; i < cond_hdr->number; i++, cond++) {
954 switch (cond->type) {
955 case ITM_COND_BETWEEN:
956 rth = ADDR(cond->operand.place);
957 rtsh = (itm_range_hdr_t *)(rth + 1);
958 if (ileft < rtsh->len) {
959 errno = EINVAL;
960 TRACE_MESSAGE('e', ("eval_cond_tbl:error=%d\n",
961 errno));
962 retval = ((size_t)(-1));
963 goto eval_cond_return;
965 p = (unsigned char *)(rtsh + 1);
966 retval = 0;
967 for (j = 0; j < rth->number;
968 j++, p = (void *)(p + (2 * rtsh->len))) {
969 retval = 1;
970 for (k = 0; k < rtsh->len; k++) {
971 if ((*(ip + k) < *(p + k)) ||
972 (*(p + rtsh->len + k) <
973 *(ip + k))) {
974 retval = 0;
975 break;
978 if (1 == retval) {
979 break;
982 if (0 == retval) {
983 TRACE_MESSAGE('b',
984 ("out of between (%p) len= rtsh=%ld\n",
985 *ip, rtsh->len));
986 goto eval_cond_return;
988 break; /* continue */
989 case ITM_COND_ESCAPESEQ:
991 * if escape sequence occur,
992 * change ist->default_action and return 2.
993 * never return 1.
995 retval = 0;
996 eth = ADDR(cond->operand.place);
997 eh = (itm_escapeseq_hdr_t *)(eth + 1);
998 if (ist->default_action.itm_ptr == (uintptr_t)NULL) {
999 ist->default_action = direc->action;
1000 TRACE_MESSAGE('E',
1001 ("escape seq (default action=%6p, "
1002 "type=%ld) set\n",
1003 direc->action.itm_ptr, ((itm_tbl_hdr_t *)
1004 (ADDR(direc->action)))->type));
1006 retval = 0;
1007 if (*inbytesleft < eh->len_min) {
1008 break;
1010 for (j = 0, d = (itm_data_t *)(eh + 1);
1011 j < eth->number;
1012 j++, d++) {
1013 if (*inbytesleft < d->size) {
1014 continue;
1016 if (0 == memcmp(*inbuf, DADDR(d), d->size)) {
1017 TRACE_MESSAGE('E',
1018 ("escape seq: discard=%ld chars\n",
1019 d->size));
1020 TRACE_MESSAGE('E',
1021 ("escape seq (default "
1022 "action=%6p, type=%ld) set\n",
1023 direc->action.itm_ptr,
1024 ((itm_tbl_hdr_t *)
1025 (ADDR(direc->action)))->type));
1026 ist->default_action = direc->action;
1027 DISCARD(d->size);
1028 retval = 2;
1029 goto eval_cond_return;
1032 if (0 == retval) {
1033 goto eval_cond_return;
1035 break; /* continue */
1036 case ITM_COND_EXPR:
1037 retval = eval_expr(ist, cond->operand.place,
1038 *inbytesleft, ip, outbytesleft);
1039 if (0 == retval) {
1040 goto eval_cond_return;
1041 } else {
1042 retval = 1;
1044 break; /* continue */
1045 default:
1046 TRACE_MESSAGE('e', ("eval_cond_tbl:illegal cond=%d\n",
1047 cond->type));
1048 retval = (size_t)-1;
1049 goto eval_cond_return;
1053 eval_cond_return:
1054 return (retval);
1058 * Evaluate operation table
1061 static size_t
1062 eval_op_tbl(
1063 icv_state_t *ist,
1064 itm_place_t op_tbl_place,
1065 const unsigned char **inbuf,
1066 size_t *inbytesleft,
1067 unsigned char **outbuf,
1068 size_t *outbytesleft)
1070 itm_tbl_hdr_t *op_hdr;
1071 itm_op_t *operation;
1072 itm_place2_t op_place;
1073 size_t retval;
1074 long i;
1076 retval = 0;
1078 #if defined(OP_DEPTH_MAX)
1079 if (OP_DEPTH_MAX <= ist->op_depth) {
1080 errno = ELIBBAD;
1081 TRACE_MESSAGE('e', ("eval_op_tbl:error=%d\n", errno));
1082 return (RETVALERR);
1084 ist->op_depth += 1;
1085 #endif /* OP_DEPTH_MAX */
1087 op_hdr = ADDR(op_tbl_place);
1088 operation = (itm_op_t *)(op_hdr + 1);
1090 op_place = op_tbl_place.itm_ptr + (sizeof (itm_tbl_hdr_t));
1091 for (i = 0; i < op_hdr->number; i++, operation++,
1092 op_place += (sizeof (itm_op_t))) {
1093 TRACE_MESSAGE('O', ("eval_op_tbl: %ld %p\n", i, op_place));
1094 retval = eval_op(ist, op_place, inbuf, inbytesleft,
1095 outbuf, outbytesleft);
1096 if (((long)(retval)) < 0) {
1097 #if defined(OP_DEPTH_MAX)
1098 ist->op_depth -= 1;
1099 #endif /* OP_DEPTH_MAX */
1100 switch (retval) {
1101 case RETVALERR:
1102 return (retval);
1103 case RETVALRET:
1104 if (0 == op_hdr->name.itm_ptr) {
1105 return (RETVALRET);
1106 } else {
1107 return (0);
1112 #if defined(OP_DEPTH_MAX)
1113 ist->op_depth -= 1;
1114 #endif /* OP_DEPTH_MAX */
1115 return (retval);
1120 * Evaluate single operation
1123 static size_t
1124 eval_op(
1125 icv_state_t *ist,
1126 itm_place2_t op_place,
1127 const unsigned char **inbuf,
1128 size_t *inbytesleft,
1129 unsigned char **outbuf,
1130 size_t *outbytesleft)
1132 size_t retval;
1133 itm_num_t num;
1134 itm_op_t *operation;
1135 itm_expr_t *expr;
1136 itm_num_t c;
1137 itm_num_t i;
1138 itm_size_t z;
1139 unsigned char *p;
1140 itm_expr_t *expr0;
1141 itm_tbl_hdr_t *h;
1142 itm_type_t t;
1144 #define EVAL_EXPR(n) \
1145 (expr0 = ADDR(operation->data.operand[(n)]), \
1146 (itm_num_t)((expr0->type == ITM_EXPR_INT) ? \
1147 expr0->data.itm_exnum : \
1148 ((expr0->type == ITM_EXPR_REG) ? \
1149 REG(expr0->data.itm_exnum) : \
1150 ((expr0->type == ITM_EXPR_IN_VECTOR_D) ? \
1151 ((expr0->data.itm_exnum < 0) ? \
1152 (((-1) == expr0->data.itm_exnum) ? *inbytesleft : 0) : \
1153 ((expr0->data.itm_exnum < *inbytesleft) ? \
1154 (*(uchar_t *)(*inbuf + expr0->data.itm_exnum)) : 0)): \
1155 eval_expr(ist, operation->data.operand[(n)], \
1156 *inbytesleft, *inbuf, *outbytesleft)))))
1158 retval = 0;
1160 operation = (itm_op_t *)ADDR2(op_place);
1162 switch (operation->type) {
1163 case ITM_OP_EXPR:
1164 num = eval_expr(ist, operation->data.operand[0],
1165 *inbytesleft, *inbuf, *outbytesleft);
1166 TRACE_MESSAGE('o', ("ITM_OP_EXPR: %ld\n", retval));
1167 break;
1168 case ITM_OP_ERROR:
1169 num = eval_expr(ist, operation->data.operand[0],
1170 *inbytesleft, *inbuf, *outbytesleft);
1171 errno = (int)num;
1172 TRACE_MESSAGE('o', ("ITM_OP_ERROR: %ld\n", num));
1173 retval = (size_t)(-1);
1174 break;
1175 case ITM_OP_ERROR_D:
1176 errno = (int)operation->data.itm_opnum;
1177 TRACE_MESSAGE('o', ("ITM_OP_ERROR_D: %d\n", errno));
1178 retval = (size_t)(-1);
1179 break;
1180 case ITM_OP_OUT:
1181 expr = ADDR(operation->data.operand[0]);
1182 if ((*outbytesleft) == 0) {
1183 errno = E2BIG;
1184 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1185 return ((size_t)(-1));
1187 c = eval_expr(ist, operation->data.operand[0],
1188 *inbytesleft, *inbuf, *outbytesleft);
1189 PUT((uchar_t)c);
1190 retval = *inbytesleft;
1191 TRACE_MESSAGE('o', ("ITM_OP_OUT: %ld %ld\n", c, *inbytesleft));
1192 break;
1193 case ITM_OP_OUT_D:
1194 expr = ADDR(operation->data.operand[0]);
1195 if ((*outbytesleft) == 0) {
1196 errno = E2BIG;
1197 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1198 return ((size_t)(-1));
1200 PUT(0xff & (expr->data.itm_exnum));
1201 break;
1202 case ITM_OP_OUT_S:
1203 expr = ADDR(operation->data.operand[0]);
1204 if ((*outbytesleft) == 0) {
1205 errno = E2BIG;
1206 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1207 return ((size_t)(-1));
1209 z = expr->data.value.size;
1210 if (*outbytesleft < z) {
1211 errno = E2BIG;
1212 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1213 return ((size_t)(-1));
1215 p = DADDR(&(expr->data.value));
1216 for (; 0 < z; --z, p++) {
1217 PUT(*p);
1219 break;
1220 case ITM_OP_OUT_R:
1221 expr = ADDR(operation->data.operand[0]);
1222 if ((*outbytesleft) == 0) {
1223 errno = E2BIG;
1224 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1225 return ((size_t)(-1));
1227 c = REG(expr->data.itm_exnum);
1228 PUT((uchar_t)c);
1229 break;
1230 case ITM_OP_OUT_INVD:
1231 expr = ADDR(operation->data.operand[0]);
1232 if ((*outbytesleft) == 0) {
1233 errno = E2BIG;
1234 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1235 return ((size_t)(-1));
1237 z = (((0 <= expr->data.itm_exnum) &&
1238 (expr->data.itm_exnum < *inbytesleft)) ?
1239 (*((unsigned char *)(*inbuf + expr->data.itm_exnum))) :
1240 (((-1) == expr->data.itm_exnum) ? *inbytesleft : 0));
1241 PUT((uchar_t)z);
1242 break;
1243 case ITM_OP_DISCARD:
1244 #if defined(EVAL_EXPR)
1245 num = EVAL_EXPR(0);
1246 #else /* !defined(EVAL_EXPR) */
1247 num = eval_expr(ist, operation->data.operand[0],
1248 *inbytesleft, *inbuf, *outbytesleft);
1249 #endif /* defined(EVAL_EXPR) */
1250 TRACE_MESSAGE('o', ("ITM_OP_DISCARD: %ld\n", num));
1251 #if defined(DISCARD)
1252 DISCARD((num <= *inbytesleft) ? ((ulong_t)num) : *inbytesleft);
1253 #else /* defined(DISCARD) */
1254 for (num = ((num <= *inbytesleft) ? num : *inbytesleft);
1255 0 < num; --num) {
1256 GET(c);
1258 #endif /* defined(DISCARD) */
1259 break;
1260 case ITM_OP_DISCARD_D:
1261 num = operation->data.itm_opnum;
1262 TRACE_MESSAGE('o', ("ITM_OP_DISCARD_D: %ld\n", num));
1263 #if defined(DISCARD)
1264 DISCARD((num <= *inbytesleft) ? num : *inbytesleft);
1265 #else /* defined(DISCARD) */
1266 for (num = ((num <= *inbytesleft) ? num : *inbytesleft);
1267 0 < num; --num) {
1268 GET(c);
1270 #endif /* defined(DISCARD) */
1271 break;
1272 case ITM_OP_IF:
1273 c = eval_expr(ist, operation->data.operand[0],
1274 *inbytesleft, *inbuf, *outbytesleft);
1275 TRACE_MESSAGE('o', ("ITM_OP_IF: %ld\n", c));
1276 if (c) {
1277 retval = eval_op_tbl(ist, operation->data.operand[1],
1278 inbuf, inbytesleft, outbuf, outbytesleft);
1280 break;
1281 case ITM_OP_IF_ELSE:
1282 c = eval_expr(ist, operation->data.operand[0],
1283 *inbytesleft, *inbuf, *outbytesleft);
1284 TRACE_MESSAGE('o', ("ITM_OP_IF_ELSE: %ld\n", c));
1285 if (c) {
1286 retval = eval_op_tbl(ist, operation->data.operand[1],
1287 inbuf, inbytesleft, outbuf, outbytesleft);
1288 } else {
1289 retval = eval_op_tbl(ist, operation->data.operand[2],
1290 inbuf, inbytesleft, outbuf, outbytesleft);
1292 break;
1293 case ITM_OP_DIRECTION:
1294 TRACE_MESSAGE('o', ("ITM_OP_DIRECTION: %p\n",
1295 operation->data.operand[0].itm_ptr));
1296 ist->direc = ADDR(operation->data.operand[0]);
1297 return ((size_t)(-2));
1298 case ITM_OP_MAP:
1299 TRACE_MESSAGE('o', ("ITM_OP_MAP: %p\n",
1300 operation->data.operand[0].itm_ptr));
1301 i = 0;
1302 if (0 != operation->data.operand[1].itm_ptr) {
1303 #if defined(EVAL_EXPR)
1304 i = EVAL_EXPR(1);
1305 #else /* !defined(EVAL_EXPR) */
1306 i = eval_expr(ist, operation->data.operand[1],
1307 *inbytesleft, *inbuf, *outbytesleft);
1308 #endif /* defined(EVAL_EXPR) */
1309 (*inbytesleft) -= i;
1310 (*inbuf) += i;
1314 * Based on what is the maptype, we call the corresponding
1315 * mapping function.
1317 h = ADDR(operation->data.operand[0]);
1318 t = h->type;
1319 switch (t) {
1320 case ITM_TBL_MAP_INDEX_FIXED:
1321 case ITM_TBL_MAP_INDEX_FIXED_1_1:
1322 retval = map_i_f(h, inbuf, inbytesleft,
1323 outbuf, outbytesleft, 1);
1324 break;
1325 case ITM_TBL_MAP_HASH:
1326 retval = map_h_l(h, inbuf, inbytesleft,
1327 outbuf, outbytesleft, 1);
1328 break;
1329 case ITM_TBL_MAP_DENSE_ENC:
1330 retval = map_d_e_l(h, inbuf, inbytesleft,
1331 outbuf, outbytesleft, 1);
1332 break;
1333 case ITM_TBL_MAP_LOOKUP:
1334 retval = map_l_f(h, inbuf, inbytesleft,
1335 outbuf, outbytesleft, 1);
1336 break;
1337 default:
1339 * This should not be possible, but in case we
1340 * have an incorrect maptype, don't fall back to
1341 * map_i_f(). Instead, because it is an error, return
1342 * an error. See CR 6622765.
1344 errno = EBADF;
1345 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1346 retval = (size_t)-1;
1347 break;
1350 if ((size_t)(-1) == retval) {
1351 (*outbytesleft) += i;
1352 (*outbuf) -= i;
1354 break;
1355 case ITM_OP_OPERATION:
1356 TRACE_MESSAGE('o', ("ITM_OP_OPERATION: %p\n",
1357 operation->data.operand[0].itm_ptr));
1358 retval = eval_op_tbl(ist, operation->data.operand[0],
1359 inbuf, inbytesleft, outbuf, outbytesleft);
1361 break;
1362 case ITM_OP_INIT:
1363 TRACE_MESSAGE('o', ("ITM_OP_INIT: %p\n",
1364 ist->itm_hdr->op_init_tbl));
1365 if (0 != ist->itm_hdr->op_init_tbl.itm_ptr) {
1366 retval = eval_op_tbl(ist, ist->itm_hdr->op_init_tbl,
1367 inbuf, inbytesleft, outbuf, outbytesleft);
1368 } else {
1369 op_init_default(ist);
1370 retval = (size_t)-2;
1372 break;
1373 case ITM_OP_RESET:
1374 TRACE_MESSAGE('o', ("ITM_OP_RESET: %p\n",
1375 ist->itm_hdr->op_reset_tbl));
1376 if (0 != ist->itm_hdr->op_reset_tbl.itm_ptr) {
1377 retval = eval_op_tbl(ist, ist->itm_hdr->op_reset_tbl,
1378 inbuf, inbytesleft, outbuf, outbytesleft);
1379 } else {
1380 op_reset_default(ist);
1381 retval = (size_t)-2;
1383 break;
1384 case ITM_OP_BREAK:
1385 TRACE_MESSAGE('o', ("ITM_OP_BREAK\n"));
1386 return (RETVALBRK);
1387 case ITM_OP_RETURN:
1388 TRACE_MESSAGE('o', ("ITM_OP_RETURN\n"));
1389 return (RETVALRET);
1390 case ITM_OP_PRINTCHR:
1391 c = eval_expr(ist, operation->data.operand[0], *inbytesleft,
1392 *inbuf, *outbytesleft);
1393 (void) fputc((uchar_t)c, stderr);
1394 TRACE_MESSAGE('o', ("ITM_OP_PRINTCHR: %ld %ld\n",
1395 c, *inbytesleft));
1396 break;
1397 case ITM_OP_PRINTHD:
1398 c = eval_expr(ist, operation->data.operand[0], *inbytesleft,
1399 *inbuf, *outbytesleft);
1400 (void) fprintf(stderr, "%lx", c);
1401 TRACE_MESSAGE('o', ("ITM_OP_PRINTHD: %ld %ld\n",
1402 c, *inbytesleft));
1403 break;
1404 case ITM_OP_PRINTINT:
1405 c = eval_expr(ist, operation->data.operand[0], *inbytesleft,
1406 *inbuf, *outbytesleft);
1407 (void) fprintf(stderr, "%ld", c);
1408 TRACE_MESSAGE('o', ("ITM_OP_PRINTINT: %ld %ld\n",
1409 c, *inbytesleft));
1410 break;
1411 default: /* never */
1412 errno = ELIBBAD;
1413 TRACE_MESSAGE('e', ("eval_op:error=%d\n", errno));
1414 return (size_t)(-1);
1416 return (retval);
1418 #undef EVAL_EXPR
1423 * Evaluate expression
1425 static itm_num_t
1426 eval_expr(
1427 icv_state_t *ist,
1428 itm_place_t expr_place,
1429 size_t inbytesleft,
1430 const unsigned char *inbuf,
1431 size_t outbytesleft)
1433 itm_expr_t *expr;
1434 itm_expr_t *expr_op;
1435 itm_num_t num;
1436 unsigned char *p;
1437 long i;
1438 itm_expr_t *expr0;
1439 itm_num_t num00;
1440 itm_num_t num01;
1442 #define EVAL_EXPR_E(n) (eval_expr(ist, expr->data.operand[(n)], \
1443 inbytesleft, inbuf, outbytesleft))
1444 #define EVAL_EXPR_D(n) ((itm_num_t)(expr->data.operand[(n)].itm_ptr))
1445 #define EVAL_EXPR_R(n) (REG((itm_num_t)(expr->data.operand[(n)].itm_ptr)))
1446 #define EVAL_EXPR_INVD(n) \
1447 ((num0 ## n) = ((itm_num_t)(expr->data.operand[(n)].itm_ptr)), \
1448 ((num0 ## n) < 0) ? \
1449 (((-1) == (num0 ## n)) ? inbytesleft : 0) : \
1450 (((num0 ## n) < inbytesleft) ? \
1451 (*(unsigned char *)(inbuf + (num0 ## n))) : 0))
1452 #define EVAL_EXPR(n) \
1453 (expr0 = ADDR(expr->data.operand[(n)]), \
1454 (itm_num_t)((expr0->type == ITM_EXPR_INT) ? \
1455 expr0->data.itm_exnum : \
1456 ((expr0->type == ITM_EXPR_REG) ? \
1457 REG(expr0->data.itm_exnum) : \
1458 ((expr0->type == ITM_EXPR_IN_VECTOR_D) ? \
1459 ((expr0->data.itm_exnum < 0) ? \
1460 (((-1) == expr0->data.itm_exnum) ? inbytesleft : 0) : \
1461 ((expr0->data.itm_exnum < inbytesleft) ? \
1462 (*(uchar_t *)(inbuf + expr0->data.itm_exnum)) : 0)) : \
1463 eval_expr(ist, expr->data.operand[(n)], \
1464 inbytesleft, inbuf, outbytesleft)))))
1466 #define EVAL_OP_BIN_PROTO(op, name, name0, name1) \
1467 case ITM_EXPR_##name##_##name0##_##name1: \
1468 return (EVAL_EXPR_##name0(0) op EVAL_EXPR_##name1(1));
1470 #define EVAL_OP_BIN1(op, name) \
1471 EVAL_OP_BIN_PROTO(op, name, E, E) \
1472 EVAL_OP_BIN_PROTO(op, name, E, D) \
1473 EVAL_OP_BIN_PROTO(op, name, E, R) \
1474 EVAL_OP_BIN_PROTO(op, name, E, INVD)
1476 #define EVAL_OP_BIN2(op, name) \
1477 EVAL_OP_BIN_PROTO(op, name, D, E) \
1478 EVAL_OP_BIN_PROTO(op, name, D, D) \
1479 EVAL_OP_BIN_PROTO(op, name, D, R) \
1480 EVAL_OP_BIN_PROTO(op, name, D, INVD)
1482 #define EVAL_OP_BIN3(op, name) \
1483 EVAL_OP_BIN_PROTO(op, name, R, E) \
1484 EVAL_OP_BIN_PROTO(op, name, R, D) \
1485 EVAL_OP_BIN_PROTO(op, name, R, R) \
1486 EVAL_OP_BIN_PROTO(op, name, R, INVD)
1488 #define EVAL_OP_BIN4(op, name) \
1489 EVAL_OP_BIN_PROTO(op, name, INVD, E) \
1490 EVAL_OP_BIN_PROTO(op, name, INVD, D) \
1491 EVAL_OP_BIN_PROTO(op, name, INVD, R) \
1492 EVAL_OP_BIN_PROTO(op, name, INVD, INVD)
1494 #define EVAL_OP_BIN_PROTECT_PROTO(op, name, name0, name1) \
1495 case ITM_EXPR_##name##_##name0##_##name1: \
1496 num = EVAL_EXPR_##name1(1); \
1497 if (0 != num) { \
1498 return (EVAL_EXPR_##name0(0) op num); \
1499 } else { \
1500 return (0); \
1503 #define EVAL_OP_BIN_PROTECT1(op, name) \
1504 EVAL_OP_BIN_PROTECT_PROTO(op, name, E, E) \
1505 EVAL_OP_BIN_PROTECT_PROTO(op, name, E, D) \
1506 EVAL_OP_BIN_PROTECT_PROTO(op, name, E, R) \
1507 EVAL_OP_BIN_PROTECT_PROTO(op, name, E, INVD)
1509 #define EVAL_OP_BIN_PROTECT2(op, name) \
1510 EVAL_OP_BIN_PROTECT_PROTO(op, name, D, E) \
1511 EVAL_OP_BIN_PROTECT_PROTO(op, name, D, D) \
1512 EVAL_OP_BIN_PROTECT_PROTO(op, name, D, R) \
1513 EVAL_OP_BIN_PROTECT_PROTO(op, name, D, INVD)
1515 #define EVAL_OP_BIN_PROTECT3(op, name) \
1516 EVAL_OP_BIN_PROTECT_PROTO(op, name, R, E) \
1517 EVAL_OP_BIN_PROTECT_PROTO(op, name, R, D) \
1518 EVAL_OP_BIN_PROTECT_PROTO(op, name, R, R) \
1519 EVAL_OP_BIN_PROTECT_PROTO(op, name, R, INVD)
1521 #define EVAL_OP_BIN_PROTECT4(op, name) \
1522 EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, E) \
1523 EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, D) \
1524 EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, R) \
1525 EVAL_OP_BIN_PROTECT_PROTO(op, name, INVD, INVD)
1527 expr = ADDR(expr_place);
1529 switch (expr->type) {
1530 case ITM_EXPR_NONE: /* not used */
1531 return (0);
1532 case ITM_EXPR_NOP: /* not used */
1533 return (0);
1534 case ITM_EXPR_NAME: /* not used */
1535 return (0);
1536 case ITM_EXPR_INT: /* integer */
1537 return (expr->data.itm_exnum);
1538 case ITM_EXPR_SEQ: /* byte sequence */
1539 if ((sizeof (itm_place_t)) < expr->data.value.size) {
1540 p = (unsigned char *)ADDR(expr->data.value.place);
1541 } else {
1542 p = (unsigned char *)&(expr->data.value.place);
1544 for (i = 0, num = 0; i < expr->data.value.size; i++, p++) {
1545 num = ((num << 8) | *p);
1547 return (num);
1548 case ITM_EXPR_REG: /* register */
1549 return (REG(expr->data.itm_exnum));
1550 case ITM_EXPR_IN_VECTOR: /* in[expr] */
1551 num = EVAL_EXPR(0);
1552 if ((0 <= num) && (num < inbytesleft)) {
1553 return (*((unsigned char *)(inbuf + num)));
1554 } else if ((-1) == num) {
1555 return (inbytesleft);
1556 } else {
1557 return (0);
1559 case ITM_EXPR_IN_VECTOR_D: /* in[DECIMAL] */
1560 num = expr->data.itm_exnum;
1561 if ((0 <= num) && (num < inbytesleft)) {
1562 return (*((unsigned char *)(inbuf + num)));
1563 } else if ((-1) == num) {
1564 return (inbytesleft);
1565 } else {
1566 return (0);
1568 case ITM_EXPR_OUT: /* out */
1569 return (outbytesleft);
1570 case ITM_EXPR_TRUE: /* true */
1571 return (1);
1572 case ITM_EXPR_FALSE: /* false */
1573 return (0);
1574 case ITM_EXPR_UMINUS: /* unary minus */
1575 return ((-1) * EVAL_EXPR(0));
1576 #define PLUS_FOR_CSTYLE_CLEAN +
1577 #define MINUS_FOR_CSTYLE_CLEAN -
1578 #define MUL_FOR_CSTYLE_CLEAN *
1579 #define DIV_FOR_CSTYLE_CLEAN /
1580 #define MOD_FOR_CSTYLE_CLEAN %
1581 #define SHIFT_L_FOR_CSTYLE_CLEAN <<
1582 #define SHIFT_R_FOR_CSTYLE_CLEAN >>
1583 #define OR_FOR_CSTYLE_CLEAN |
1584 #define XOR_FOR_CSTYLE_CLEAN ^
1585 #define AND_FOR_CSTYLE_CLEAN &
1586 #define EQ_FOR_CSTYLE_CLEAN ==
1587 #define NE_FOR_CSTYLE_CLEAN !=
1588 #define GT_FOR_CSTYLE_CLEAN >
1589 #define GE_FOR_CSTYLE_CLEAN >=
1590 #define LT_FOR_CSTYLE_CLEAN <
1591 #define LE_FOR_CSTYLE_CLEAN <=
1592 EVAL_OP_BIN1(PLUS_FOR_CSTYLE_CLEAN, PLUS) /* A + B */
1593 EVAL_OP_BIN2(PLUS_FOR_CSTYLE_CLEAN, PLUS) /* A + B */
1594 EVAL_OP_BIN3(PLUS_FOR_CSTYLE_CLEAN, PLUS) /* A + B */
1595 EVAL_OP_BIN4(PLUS_FOR_CSTYLE_CLEAN, PLUS) /* A + B */
1597 EVAL_OP_BIN1(MINUS_FOR_CSTYLE_CLEAN, MINUS) /* A - B */
1598 EVAL_OP_BIN2(MINUS_FOR_CSTYLE_CLEAN, MINUS) /* A - B */
1599 EVAL_OP_BIN3(MINUS_FOR_CSTYLE_CLEAN, MINUS) /* A - B */
1600 EVAL_OP_BIN4(MINUS_FOR_CSTYLE_CLEAN, MINUS) /* A - B */
1602 EVAL_OP_BIN1(MUL_FOR_CSTYLE_CLEAN, MUL) /* A * B */
1603 EVAL_OP_BIN2(MUL_FOR_CSTYLE_CLEAN, MUL) /* A * B */
1604 EVAL_OP_BIN3(MUL_FOR_CSTYLE_CLEAN, MUL) /* A * B */
1605 EVAL_OP_BIN4(MUL_FOR_CSTYLE_CLEAN, MUL) /* A * B */
1607 EVAL_OP_BIN_PROTECT1(DIV_FOR_CSTYLE_CLEAN, DIV) /* A / B */
1608 EVAL_OP_BIN_PROTECT2(DIV_FOR_CSTYLE_CLEAN, DIV) /* A / B */
1609 EVAL_OP_BIN_PROTECT3(DIV_FOR_CSTYLE_CLEAN, DIV) /* A / B */
1610 EVAL_OP_BIN_PROTECT4(DIV_FOR_CSTYLE_CLEAN, DIV) /* A / B */
1612 EVAL_OP_BIN_PROTECT1(MOD_FOR_CSTYLE_CLEAN, MOD) /* A % B */
1613 EVAL_OP_BIN_PROTECT2(MOD_FOR_CSTYLE_CLEAN, MOD) /* A % B */
1614 EVAL_OP_BIN_PROTECT3(MOD_FOR_CSTYLE_CLEAN, MOD) /* A % B */
1615 EVAL_OP_BIN_PROTECT4(MOD_FOR_CSTYLE_CLEAN, MOD) /* A % B */
1617 EVAL_OP_BIN1(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L) /* A << B */
1618 EVAL_OP_BIN2(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L) /* A << B */
1619 EVAL_OP_BIN3(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L) /* A << B */
1620 EVAL_OP_BIN4(SHIFT_L_FOR_CSTYLE_CLEAN, SHIFT_L) /* A << B */
1622 EVAL_OP_BIN1(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R) /* A >> B */
1623 EVAL_OP_BIN2(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R) /* A >> B */
1624 EVAL_OP_BIN3(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R) /* A >> B */
1625 EVAL_OP_BIN4(SHIFT_R_FOR_CSTYLE_CLEAN, SHIFT_R) /* A >> B */
1627 EVAL_OP_BIN1(OR_FOR_CSTYLE_CLEAN, OR) /* A | B */
1628 EVAL_OP_BIN2(OR_FOR_CSTYLE_CLEAN, OR) /* A | B */
1629 EVAL_OP_BIN3(OR_FOR_CSTYLE_CLEAN, OR) /* A | B */
1630 EVAL_OP_BIN4(OR_FOR_CSTYLE_CLEAN, OR) /* A | B */
1632 EVAL_OP_BIN1(XOR_FOR_CSTYLE_CLEAN, XOR) /* A ^ B */
1633 EVAL_OP_BIN2(XOR_FOR_CSTYLE_CLEAN, XOR) /* A ^ B */
1634 EVAL_OP_BIN3(XOR_FOR_CSTYLE_CLEAN, XOR) /* A ^ B */
1635 EVAL_OP_BIN4(XOR_FOR_CSTYLE_CLEAN, XOR) /* A ^ B */
1637 EVAL_OP_BIN1(AND_FOR_CSTYLE_CLEAN, AND) /* A & B */
1638 EVAL_OP_BIN2(AND_FOR_CSTYLE_CLEAN, AND) /* A & B */
1639 EVAL_OP_BIN3(AND_FOR_CSTYLE_CLEAN, AND) /* A & B */
1640 EVAL_OP_BIN4(AND_FOR_CSTYLE_CLEAN, AND) /* A & B */
1642 EVAL_OP_BIN1(EQ_FOR_CSTYLE_CLEAN, EQ) /* A == B */
1643 EVAL_OP_BIN2(EQ_FOR_CSTYLE_CLEAN, EQ) /* A == B */
1644 EVAL_OP_BIN3(EQ_FOR_CSTYLE_CLEAN, EQ) /* A == B */
1645 EVAL_OP_BIN4(EQ_FOR_CSTYLE_CLEAN, EQ) /* A == B */
1647 EVAL_OP_BIN1(NE_FOR_CSTYLE_CLEAN, NE) /* A != B */
1648 EVAL_OP_BIN2(NE_FOR_CSTYLE_CLEAN, NE) /* A != B */
1649 EVAL_OP_BIN3(NE_FOR_CSTYLE_CLEAN, NE) /* A != B */
1650 EVAL_OP_BIN4(NE_FOR_CSTYLE_CLEAN, NE) /* A != B */
1652 EVAL_OP_BIN1(GT_FOR_CSTYLE_CLEAN, GT) /* A > B */
1653 EVAL_OP_BIN2(GT_FOR_CSTYLE_CLEAN, GT) /* A > B */
1654 EVAL_OP_BIN3(GT_FOR_CSTYLE_CLEAN, GT) /* A > B */
1655 EVAL_OP_BIN4(GT_FOR_CSTYLE_CLEAN, GT) /* A > B */
1657 EVAL_OP_BIN1(GE_FOR_CSTYLE_CLEAN, GE) /* A >= B */
1658 EVAL_OP_BIN2(GE_FOR_CSTYLE_CLEAN, GE) /* A >= B */
1659 EVAL_OP_BIN3(GE_FOR_CSTYLE_CLEAN, GE) /* A >= B */
1660 EVAL_OP_BIN4(GE_FOR_CSTYLE_CLEAN, GE) /* A >= B */
1662 EVAL_OP_BIN1(LT_FOR_CSTYLE_CLEAN, LT) /* A < B */
1663 EVAL_OP_BIN2(LT_FOR_CSTYLE_CLEAN, LT) /* A < B */
1664 EVAL_OP_BIN3(LT_FOR_CSTYLE_CLEAN, LT) /* A < B */
1665 EVAL_OP_BIN4(LT_FOR_CSTYLE_CLEAN, LT) /* A < B */
1667 EVAL_OP_BIN1(LE_FOR_CSTYLE_CLEAN, LE) /* A <= B */
1668 EVAL_OP_BIN2(LE_FOR_CSTYLE_CLEAN, LE) /* A <= B */
1669 EVAL_OP_BIN3(LE_FOR_CSTYLE_CLEAN, LE) /* A <= B */
1670 EVAL_OP_BIN4(LE_FOR_CSTYLE_CLEAN, LE) /* A <= B */
1672 case ITM_EXPR_NOT: /* !A */
1673 return (!(EVAL_EXPR(0)));
1674 case ITM_EXPR_NEG: /* ~A */
1675 return (~(EVAL_EXPR(0)));
1676 case ITM_EXPR_LOR: /* A || B */
1677 if (0 != (num = EVAL_EXPR(0)))
1678 return (num);
1679 if (0 != (num = EVAL_EXPR(1)))
1680 return (num);
1681 return (0);
1682 case ITM_EXPR_LAND: /* A && B */
1683 if (0 == EVAL_EXPR(0))
1684 return (0);
1685 if (0 == (num = EVAL_EXPR(1)))
1686 return (0);
1687 return (num);
1688 case ITM_EXPR_ASSIGN: /* A = B */
1689 num = EVAL_EXPR(1);
1690 if (expr->data.operand[0].itm_ptr < ist->itm_hdr->reg_num) {
1691 return (*(ist->regs + expr->data.operand[0].itm_ptr)
1692 = num);
1693 } else {
1694 return (0);
1696 case ITM_EXPR_IN_EQ: /* in == A */
1697 expr_op = ADDR(expr->data.operand[0]);
1698 switch (expr_op->type) {
1699 case ITM_EXPR_SEQ:
1700 if (inbytesleft < expr_op->data.value.size) {
1701 return (0);
1703 p = DADDR(&(expr_op->data.value));
1704 for (i = 0; i < expr_op->data.value.size; i++, p++) {
1705 if (*p != *(inbuf + i)) {
1706 return (0);
1709 return (1);
1710 default:
1711 num = EVAL_EXPR(0);
1712 return (num == *((unsigned char *)inbuf));
1714 default:
1715 break;
1718 return (0);
1720 #undef EVAL_EXPR_E
1721 #undef EVAL_EXPR_D
1722 #undef EVAL_EXPR_R
1723 #undef EVAL_EXPR_INVD
1724 #undef EVAL_EXPR
1729 * maintain ITM reference information
1731 static void
1732 itm_ref_free(int fd, void *ptr0, void *ptr1, void *ptr2, size_t len)
1734 int r;
1735 r = errno;
1736 if (0 <= fd) {
1737 (void) close(fd);
1739 free(ptr0);
1740 free(ptr1);
1741 if (0 < len) {
1742 (void) munmap(ptr2, len);
1744 errno = r;
1747 static itm_ref_t *
1748 itm_ref_inc(const char *itm)
1750 itm_ref_t *ref;
1751 itm_hdr_t *hdr;
1752 struct stat st;
1753 int fd;
1755 fd = open(itm, O_RDONLY, 0);
1756 if (fd == -1) {
1757 itm_ref_free(-1, NULL, NULL, NULL, 0);
1758 return (NULL);
1761 if (fstat(fd, &st) == -1) {
1762 itm_ref_free(fd, NULL, NULL, NULL, 0);
1763 return (NULL);
1765 hdr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
1766 if (MAP_FAILED == hdr) {
1767 itm_ref_free(fd, NULL, NULL, NULL, 0);
1768 return (NULL);
1771 (void) close(fd);
1773 ref = malloc(sizeof (itm_ref_t));
1774 if (NULL == ref) {
1775 itm_ref_free(-1, NULL, NULL, hdr, st.st_size);
1776 return (NULL);
1778 ref->name = malloc(strlen(itm) + 1);
1779 if (NULL == ref->name) {
1780 itm_ref_free(-1, ref, NULL, hdr, st.st_size);
1781 return (NULL);
1783 (void) strcpy(ref->name, itm);
1784 ref->hdr = hdr;
1785 ref->len = st.st_size;
1787 if ((hdr->ident[0] != ITM_IDENT_0) ||
1788 (hdr->ident[1] != ITM_IDENT_1) ||
1789 (hdr->ident[2] != ITM_IDENT_2) ||
1790 (hdr->ident[3] != ITM_IDENT_3) ||
1791 (hdr->spec[0] != ITM_SPEC_0) ||
1792 (hdr->spec[1] != ITM_SPEC_1) ||
1793 (hdr->spec[2] != ITM_SPEC_2) ||
1794 #if defined(_LITTLE_ENDIAN)
1795 #if defined(_LP64)
1796 ((hdr->spec[3] != ITM_SPEC_3_32_LITTLE_ENDIAN) &&
1797 (hdr->spec[3] != ITM_SPEC_3_64_LITTLE_ENDIAN)) ||
1798 #else
1799 (hdr->spec[3] != ITM_SPEC_3_32_LITTLE_ENDIAN) ||
1800 #endif
1801 #else
1802 #if defined(_LP64)
1803 ((hdr->spec[3] != ITM_SPEC_3_32_BIG_ENDIAN) &&
1804 (hdr->spec[3] != ITM_SPEC_3_64_BIG_ENDIAN)) ||
1805 #else
1806 (hdr->spec[3] != ITM_SPEC_3_32_BIG_ENDIAN) ||
1807 #endif
1808 #endif
1809 (hdr->version[0] != ITM_VER_0) ||
1810 (hdr->version[1] != ITM_VER_1) ||
1811 (hdr->version[2] != ITM_VER_2) ||
1812 (hdr->version[3] != ITM_VER_3) ||
1813 (((size_t)(hdr->itm_size.itm_ptr)) != st.st_size)) {
1814 itm_ref_free(-1, ref, ref->name, ref->hdr, ref->len);
1815 errno = ELIBBAD;
1816 TRACE_MESSAGE('e', ("itm_ref_inc:error=%d\n", errno));
1817 return (NULL);
1820 return (ref);
1824 static void
1825 itm_ref_dec(itm_ref_t *ref)
1827 (void) munmap((char *)(ref->hdr), ref->len);
1828 free(ref->name);
1829 free(ref);
1833 static void
1834 op_init_default(icv_state_t *ist)
1836 ist->direc = ADDR(ist->itm_hdr->direc_init_tbl);
1837 regs_init(ist);
1841 static void
1842 op_reset_default(icv_state_t *ist)
1844 ist->direc = ADDR(ist->itm_hdr->direc_init_tbl);
1845 regs_init(ist);
1849 static void
1850 regs_init(icv_state_t *ist)
1852 if (0 < ist->itm_hdr->reg_num) {
1853 (void) memset(ist->regs, 0,
1854 (sizeof (itm_num_t)) * ist->itm_hdr->reg_num);
1859 #if defined(DEBUG)
1860 static void
1861 trace_init()
1863 char *env_val;
1864 char *p;
1866 env_val = getenv("ITM_INT_TRACE");
1867 if (NULL == env_val)
1868 return;
1870 for (p = env_val; *p; p++) {
1871 trace_option[(*p) & 0x007f] = 1;
1875 static void
1876 trace_message(char *format, ...)
1878 va_list ap;
1880 va_start(ap, format);
1882 (void) vfprintf(stderr, format, ap);
1884 va_end(ap);
1886 #endif /* DEBUG */