xref: /illumos-gate/usr/src/uts/common/kiconv/kiconv_emea/kiconv_emea.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Kernel iconv code conversion module (kiconv_emea) for Europe, Middle East,
30  * and South East Asia (PSARC/2007/173).
31  */
32 
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/sysmacros.h>
36 #include <sys/systm.h>
37 #include <sys/debug.h>
38 #include <sys/kmem.h>
39 #include <sys/cmn_err.h>
40 #include <sys/ddi.h>
41 #include <sys/sunddi.h>
42 #include <sys/ksynch.h>
43 #include <sys/modctl.h>
44 #include <sys/byteorder.h>
45 #include <sys/errno.h>
46 #include <sys/kiconv.h>
47 #include <sys/kiconv_emea1.h>
48 #include <sys/kiconv_emea2.h>
49 
50 
51 /*
52  * The following macros indicate ids to the correct code conversion mapping
53  * data tables to use. The actual tables are coming from <sys/kiconv_emea1.h>
54  * and <sys/kiconv_emea2.h>. If you update the header files, then, you might
55  * also need to update the table ids at below.
56  *
57  * The table for KICONV_TBLID_720 is a special case and should come from
58  * a separate header file than others at <sys/kiconv_emea1.h> hence it has
59  * an id that is rather unusual distinguishing itself from others. (And,
60  * the ids much be of uint8_t.)
61  */
62 #define	KICONV_TBLID_720		(0xFFU)
63 #define	KICONV_TBLID_RANGE1_START	KICONV_TBLID_720
64 #define	KICONV_TBLID_RANGE1_END		KICONV_TBLID_720
65 
66 #define	KICONV_TBLID_737		(0)
67 #define	KICONV_TBLID_852		(1)
68 #define	KICONV_TBLID_857		(2)
69 #define	KICONV_TBLID_862		(3)
70 #define	KICONV_TBLID_866		(4)
71 #define	KICONV_TBLID_1250		(5)
72 #define	KICONV_TBLID_1251		(6)
73 #define	KICONV_TBLID_1253		(7)
74 #define	KICONV_TBLID_1254		(8)
75 #define	KICONV_TBLID_1255		(9)
76 #define	KICONV_TBLID_1256		(10)
77 #define	KICONV_TBLID_1257		(11)
78 #define	KICONV_TBLID_8859_2		(12)
79 #define	KICONV_TBLID_8859_3		(13)
80 #define	KICONV_TBLID_8859_4		(14)
81 #define	KICONV_TBLID_8859_5		(15)
82 #define	KICONV_TBLID_8859_6		(16)
83 #define	KICONV_TBLID_8859_7		(17)
84 #define	KICONV_TBLID_8859_8		(18)
85 #define	KICONV_TBLID_8859_9		(19)
86 #define	KICONV_TBLID_8859_10		(20)
87 #define	KICONV_TBLID_8859_11		(21)
88 #define	KICONV_TBLID_8859_13		(22)
89 #define	KICONV_TBLID_KOI8_R		(23)
90 
91 #define	KICONV_MAX_MAPPING_TBLID	KICONV_TBLID_KOI8_R
92 
93 /*
94  * The following tables are coming from u8_textprep.c. We use them to
95  * check on validity of UTF-8 characters and their bytes.
96  */
97 extern const int8_t u8_number_of_bytes[];
98 extern const uint8_t u8_valid_min_2nd_byte[];
99 extern const uint8_t u8_valid_max_2nd_byte[];
100 
101 
102 /*
103  * The following 25 open_to_xxxx() functions are kiconv_open functions for
104  * the conversions from UTF-8 to xxxx single byte codesets.
105  */
106 static void *
107 open_to_720()
108 {
109 	kiconv_state_t s;
110 
111 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
112 	s->id = KICONV_TBLID_720;
113 	s->bom_processed = 0;
114 
115 	return ((void *)s);
116 }
117 
118 static void *
119 open_to_737()
120 {
121 	kiconv_state_t s;
122 
123 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
124 	s->id = KICONV_TBLID_737;
125 	s->bom_processed = 0;
126 
127 	return ((void *)s);
128 }
129 
130 static void *
131 open_to_852()
132 {
133 	kiconv_state_t s;
134 
135 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
136 	s->id = KICONV_TBLID_852;
137 	s->bom_processed = 0;
138 
139 	return ((void *)s);
140 }
141 
142 static void *
143 open_to_857()
144 {
145 	kiconv_state_t s;
146 
147 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
148 	s->id = KICONV_TBLID_857;
149 	s->bom_processed = 0;
150 
151 	return ((void *)s);
152 }
153 
154 static void *
155 open_to_862()
156 {
157 	kiconv_state_t s;
158 
159 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
160 	s->id = KICONV_TBLID_862;
161 	s->bom_processed = 0;
162 
163 	return ((void *)s);
164 }
165 
166 static void *
167 open_to_866()
168 {
169 	kiconv_state_t s;
170 
171 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
172 	s->id = KICONV_TBLID_866;
173 	s->bom_processed = 0;
174 
175 	return ((void *)s);
176 }
177 
178 static void *
179 open_to_1250()
180 {
181 	kiconv_state_t s;
182 
183 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
184 	s->id = KICONV_TBLID_1250;
185 	s->bom_processed = 0;
186 
187 	return ((void *)s);
188 }
189 
190 static void *
191 open_to_1251()
192 {
193 	kiconv_state_t s;
194 
195 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
196 	s->id = KICONV_TBLID_1251;
197 	s->bom_processed = 0;
198 
199 	return ((void *)s);
200 }
201 
202 static void *
203 open_to_1253()
204 {
205 	kiconv_state_t s;
206 
207 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
208 	s->id = KICONV_TBLID_1253;
209 	s->bom_processed = 0;
210 
211 	return ((void *)s);
212 }
213 
214 static void *
215 open_to_1254()
216 {
217 	kiconv_state_t s;
218 
219 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
220 	s->id = KICONV_TBLID_1254;
221 	s->bom_processed = 0;
222 
223 	return ((void *)s);
224 }
225 
226 static void *
227 open_to_1255()
228 {
229 	kiconv_state_t s;
230 
231 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
232 	s->id = KICONV_TBLID_1255;
233 	s->bom_processed = 0;
234 
235 	return ((void *)s);
236 }
237 
238 static void *
239 open_to_1256()
240 {
241 	kiconv_state_t s;
242 
243 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
244 	s->id = KICONV_TBLID_1256;
245 	s->bom_processed = 0;
246 
247 	return ((void *)s);
248 }
249 
250 static void *
251 open_to_1257()
252 {
253 	kiconv_state_t s;
254 
255 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
256 	s->id = KICONV_TBLID_1257;
257 	s->bom_processed = 0;
258 
259 	return ((void *)s);
260 }
261 
262 static void *
263 open_to_88592()
264 {
265 	kiconv_state_t s;
266 
267 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
268 	s->id = KICONV_TBLID_8859_2;
269 	s->bom_processed = 0;
270 
271 	return ((void *)s);
272 }
273 
274 static void *
275 open_to_88593()
276 {
277 	kiconv_state_t s;
278 
279 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
280 	s->id = KICONV_TBLID_8859_3;
281 	s->bom_processed = 0;
282 
283 	return ((void *)s);
284 }
285 
286 static void *
287 open_to_88594()
288 {
289 	kiconv_state_t s;
290 
291 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
292 	s->id = KICONV_TBLID_8859_4;
293 	s->bom_processed = 0;
294 
295 	return ((void *)s);
296 }
297 
298 static void *
299 open_to_88595()
300 {
301 	kiconv_state_t s;
302 
303 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
304 	s->id = KICONV_TBLID_8859_5;
305 	s->bom_processed = 0;
306 
307 	return ((void *)s);
308 }
309 
310 static void *
311 open_to_88596()
312 {
313 	kiconv_state_t s;
314 
315 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
316 	s->id = KICONV_TBLID_8859_6;
317 	s->bom_processed = 0;
318 
319 	return ((void *)s);
320 }
321 
322 static void *
323 open_to_88597()
324 {
325 	kiconv_state_t s;
326 
327 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
328 	s->id = KICONV_TBLID_8859_7;
329 	s->bom_processed = 0;
330 
331 	return ((void *)s);
332 }
333 
334 static void *
335 open_to_88598()
336 {
337 	kiconv_state_t s;
338 
339 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
340 	s->id = KICONV_TBLID_8859_8;
341 	s->bom_processed = 0;
342 
343 	return ((void *)s);
344 }
345 
346 static void *
347 open_to_88599()
348 {
349 	kiconv_state_t s;
350 
351 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
352 	s->id = KICONV_TBLID_8859_9;
353 	s->bom_processed = 0;
354 
355 	return ((void *)s);
356 }
357 
358 static void *
359 open_to_885910()
360 {
361 	kiconv_state_t s;
362 
363 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
364 	s->id = KICONV_TBLID_8859_10;
365 	s->bom_processed = 0;
366 
367 	return ((void *)s);
368 }
369 
370 static void *
371 open_to_885911()
372 {
373 	kiconv_state_t s;
374 
375 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
376 	s->id = KICONV_TBLID_8859_11;
377 	s->bom_processed = 0;
378 
379 	return ((void *)s);
380 }
381 
382 static void *
383 open_to_885913()
384 {
385 	kiconv_state_t s;
386 
387 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
388 	s->id = KICONV_TBLID_8859_13;
389 	s->bom_processed = 0;
390 
391 	return ((void *)s);
392 }
393 
394 static void *
395 open_to_koi8r()
396 {
397 	kiconv_state_t s;
398 
399 	s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
400 	s->id = KICONV_TBLID_KOI8_R;
401 	s->bom_processed = 0;
402 
403 	return ((void *)s);
404 }
405 
406 /*
407  * The following 25 open_fr_xxxx() functions are kiconv_open functions for
408  * the conversions from xxxx single byte codeset to UTF-8.
409  */
410 static void *
411 open_fr_720()
412 {
413 	return ((void *)KICONV_TBLID_720);
414 }
415 
416 static void *
417 open_fr_737()
418 {
419 	return ((void *)KICONV_TBLID_737);
420 }
421 
422 static void *
423 open_fr_852()
424 {
425 	return ((void *)KICONV_TBLID_852);
426 }
427 
428 static void *
429 open_fr_857()
430 {
431 	return ((void *)KICONV_TBLID_857);
432 }
433 
434 static void *
435 open_fr_862()
436 {
437 	return ((void *)KICONV_TBLID_862);
438 }
439 
440 static void *
441 open_fr_866()
442 {
443 	return ((void *)KICONV_TBLID_866);
444 }
445 
446 static void *
447 open_fr_1250()
448 {
449 	return ((void *)KICONV_TBLID_1250);
450 }
451 
452 static void *
453 open_fr_1251()
454 {
455 	return ((void *)KICONV_TBLID_1251);
456 }
457 
458 static void *
459 open_fr_1253()
460 {
461 	return ((void *)KICONV_TBLID_1253);
462 }
463 
464 static void *
465 open_fr_1254()
466 {
467 	return ((void *)KICONV_TBLID_1254);
468 }
469 
470 static void *
471 open_fr_1255()
472 {
473 	return ((void *)KICONV_TBLID_1255);
474 }
475 
476 static void *
477 open_fr_1256()
478 {
479 	return ((void *)KICONV_TBLID_1256);
480 }
481 
482 static void *
483 open_fr_1257()
484 {
485 	return ((void *)KICONV_TBLID_1257);
486 }
487 
488 static void *
489 open_fr_88592()
490 {
491 	return ((void *)KICONV_TBLID_8859_2);
492 }
493 
494 static void *
495 open_fr_88593()
496 {
497 	return ((void *)KICONV_TBLID_8859_3);
498 }
499 
500 static void *
501 open_fr_88594()
502 {
503 	return ((void *)KICONV_TBLID_8859_4);
504 }
505 
506 static void *
507 open_fr_88595()
508 {
509 	return ((void *)KICONV_TBLID_8859_5);
510 }
511 
512 static void *
513 open_fr_88596()
514 {
515 	return ((void *)KICONV_TBLID_8859_6);
516 }
517 
518 static void *
519 open_fr_88597()
520 {
521 	return ((void *)KICONV_TBLID_8859_7);
522 }
523 
524 static void *
525 open_fr_88598()
526 {
527 	return ((void *)KICONV_TBLID_8859_8);
528 }
529 
530 static void *
531 open_fr_88599()
532 {
533 	return ((void *)KICONV_TBLID_8859_9);
534 }
535 
536 static void *
537 open_fr_885910()
538 {
539 	return ((void *)KICONV_TBLID_8859_10);
540 }
541 
542 static void *
543 open_fr_885911()
544 {
545 	return ((void *)KICONV_TBLID_8859_11);
546 }
547 
548 static void *
549 open_fr_885913()
550 {
551 	return ((void *)KICONV_TBLID_8859_13);
552 }
553 
554 static void *
555 open_fr_koi8r()
556 {
557 	return ((void *)KICONV_TBLID_KOI8_R);
558 }
559 
560 /*
561  * The following is the common kiconv_close function for the conversions from
562  * UTF-8 to single byte codesets.
563  */
564 static int
565 close_to_sb(void *s)
566 {
567 	if (! s || s == (void *)-1)
568 		return (EBADF);
569 
570 	kmem_free(s, sizeof (kiconv_state_data_t));
571 
572 	return (0);
573 }
574 
575 /*
576  * The following is the common kiconv_close function for the conversions from
577  * single byte codesets to UTF-8.
578  */
579 static int
580 close_fr_sb(void *s)
581 {
582 	if ((ulong_t)s > KICONV_MAX_MAPPING_TBLID &&
583 	    ((ulong_t)s < KICONV_TBLID_RANGE1_START ||
584 	    (ulong_t)s > KICONV_TBLID_RANGE1_END))
585 		return (EBADF);
586 
587 	return (0);
588 }
589 
590 /*
591  * The following is the common kiconv function for the conversions from
592  * UTF-8 to single byte codesets. (This may look a lot similar to
593  * kiconvstr_to_sb() but they do have different features to cover and
594  * it's not really worth to try to merge them into a single function since
595  * you'll have to add performance penalty for both per each character
596  * conversion as you will have to figure out if this is kiconv_to_sb() or
597  * kiconvstr_to_sb().)
598  */
599 static size_t
600 kiconv_to_sb(void *kcd, char **inbuf, size_t *inbytesleft, char **outbuf,
601 	size_t *outbytesleft, int *errno)
602 {
603 	kiconv_to_sb_tbl_comp_t *tbl;
604 	size_t id;
605 	size_t ret_val;
606 	uchar_t *ib;
607 	uchar_t *oldib;
608 	uchar_t *ob;
609 	uchar_t *ibtail;
610 	uchar_t *obtail;
611 	uint32_t u8;
612 	size_t i;
613 	size_t l;
614 	size_t h;
615 	size_t init_h;
616 	int8_t sz;
617 	boolean_t second;
618 
619 	/* Check on the kiconv code conversion descriptor. */
620 	if (! kcd || kcd == (void *)-1) {
621 		*errno = EBADF;
622 		return ((size_t)-1);
623 	}
624 
625 	/* Get the table id and check on it. */
626 	id = ((kiconv_state_t)kcd)->id;
627 	if (id > KICONV_MAX_MAPPING_TBLID &&
628 	    (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
629 		*errno = EBADF;
630 		return ((size_t)-1);
631 	}
632 
633 	/* If this is a state reset request, process and return. */
634 	if (! inbuf || ! (*inbuf)) {
635 		((kiconv_state_t)kcd)->bom_processed = 0;
636 		return ((size_t)0);
637 	}
638 
639 	ret_val = 0;
640 	ib = (uchar_t *)*inbuf;
641 	ob = (uchar_t *)*outbuf;
642 	ibtail = ib + *inbytesleft;
643 	obtail = ob + *outbytesleft;
644 
645 	/*
646 	 * Get the table we want to use and also calculate the "init_h"
647 	 * which is the initial high index for the binary search that we will
648 	 * use. While the table sizes are all the same at the moment, to be
649 	 * ready for future cases where tables could be in different sizes,
650 	 * we separately calculate the init_h at here.
651 	 */
652 	if (id == KICONV_TBLID_720) {
653 		tbl = (kiconv_to_sb_tbl_comp_t *)u8_to_cp720_tbl;
654 		init_h = sizeof (u8_to_cp720_tbl);
655 	} else {
656 		tbl = (kiconv_to_sb_tbl_comp_t *)to_sb_tbl[id];
657 		init_h = sizeof (to_sb_tbl[id]);
658 	}
659 	init_h = init_h / sizeof (kiconv_to_sb_tbl_comp_t) - 1;
660 
661 	/*
662 	 * If we haven't checked on the UTF-8 signature BOM character in
663 	 * the beginning of the conversion data stream, we check it and if
664 	 * find one, we skip it since we have no use for it.
665 	 */
666 	if (((kiconv_state_t)kcd)->bom_processed == 0 && (ibtail - ib) >= 3 &&
667 	    *ib == 0xef && *(ib + 1) == 0xbb && *(ib + 2) == 0xbf)
668 			ib += 3;
669 	((kiconv_state_t)kcd)->bom_processed = 1;
670 
671 	while (ib < ibtail) {
672 		sz = u8_number_of_bytes[*ib];
673 		if (sz <= 0) {
674 			*errno = EILSEQ;
675 			ret_val = (size_t)-1;
676 			break;
677 		}
678 
679 		/*
680 		 * If there is no room to write at the output buffer,
681 		 * we issue E2BIG and let the caller knows about it.
682 		 */
683 		if (ob >= obtail) {
684 			*errno = E2BIG;
685 			ret_val = (size_t)-1;
686 			break;
687 		}
688 
689 		/*
690 		 * If it is a 7-bit ASCII character, we don't need to
691 		 * process further and we just copy the character over.
692 		 *
693 		 * If not, we collect the character bytes up to four bytes,
694 		 * validate the bytes, and binary search for the corresponding
695 		 * single byte codeset character byte. If we find it from
696 		 * the mapping table, we put that into the output buffer;
697 		 * otherwise, we put a replacement character instead as
698 		 * a non-identical conversion.
699 		 */
700 		if (sz == 1) {
701 			*ob++ = *ib++;
702 			continue;
703 		}
704 
705 		/*
706 		 * Issue EINVAL if the last character at the input buffer
707 		 * is an incomplete character missing a byte or more.
708 		 */
709 		if ((ibtail - ib) < sz) {
710 			*errno = EINVAL;
711 			ret_val = (size_t)-1;
712 			break;
713 		}
714 
715 		/*
716 		 * We collect UTF-8 character bytes and at the same time,
717 		 * check on if the bytes are valid bytes or not. This follows
718 		 * the latest UTF-8 byte representation.
719 		 */
720 		oldib = ib;
721 		u8 = *ib++;
722 		second = B_TRUE;
723 		for (i = 1; i < sz; i++) {
724 			if (second) {
725 				if (*ib < u8_valid_min_2nd_byte[u8] ||
726 				    *ib > u8_valid_max_2nd_byte[u8]) {
727 					*errno = EILSEQ;
728 					ret_val = (size_t)-1;
729 					ib = oldib;
730 					goto TO_SB_ILLEGAL_CHAR_ERR;
731 				}
732 				second = B_FALSE;
733 			} else if (*ib < 0x80 || *ib > 0xbf) {
734 				*errno = EILSEQ;
735 				ret_val = (size_t)-1;
736 				ib = oldib;
737 				goto TO_SB_ILLEGAL_CHAR_ERR;
738 			}
739 			u8 = (u8 << 8) | ((uint32_t)*ib);
740 			ib++;
741 		}
742 
743 		i = l = 0;
744 		h = init_h;
745 		while (l <= h) {
746 			i = (l + h) / 2;
747 			if (tbl[i].u8 == u8)
748 				break;
749 			else if (tbl[i].u8 < u8)
750 				l = i + 1;
751 			else
752 				h = i - 1;
753 		}
754 
755 		if (tbl[i].u8 == u8) {
756 			*ob++ = tbl[i].sb;
757 		} else {
758 			/*
759 			 * What this means is that we encountered
760 			 * a non-identical conversion. In other words,
761 			 * input buffer contains a valid character in
762 			 * the fromcode but the tocode doesn't have
763 			 * any character that can be mapped to.
764 			 *
765 			 * In this case, we insert an ASCII replacement
766 			 * character instead at the output buffer and
767 			 * count such non-identical conversions by
768 			 * increasing the ret_val.
769 			 *
770 			 * If the return value of the function is bigger
771 			 * than zero, that means we had such non-identical
772 			 * conversion(s).
773 			 */
774 			*ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
775 			ret_val++;
776 		}
777 	}
778 
779 TO_SB_ILLEGAL_CHAR_ERR:
780 	*inbuf = (char *)ib;
781 	*inbytesleft = ibtail - ib;
782 	*outbuf = (char *)ob;
783 	*outbytesleft = obtail - ob;
784 
785 	return (ret_val);
786 }
787 
788 /*
789  * The following is the common kiconv function for the conversions from
790  * single byte codesets to UTf-8.
791  */
792 static size_t
793 kiconv_fr_sb(void *kcd, char **inbuf, size_t *inbytesleft, char **outbuf,
794 	size_t *outbytesleft, int *errno)
795 {
796 	kiconv_to_utf8_tbl_comp_t *tbl;
797 	size_t ret_val;
798 	uchar_t *ib;
799 	uchar_t *ob;
800 	uchar_t *ibtail;
801 	uchar_t *obtail;
802 	size_t i;
803 	size_t k;
804 	int8_t sz;
805 
806 	/* Validate the kiconv code conversion descriptor. */
807 	if ((ulong_t)kcd > KICONV_MAX_MAPPING_TBLID &&
808 	    ((ulong_t)kcd < KICONV_TBLID_RANGE1_START ||
809 	    (ulong_t)kcd > KICONV_TBLID_RANGE1_END)) {
810 		*errno = EBADF;
811 		return ((size_t)-1);
812 	}
813 
814 	/*
815 	 * If this is a state reset request, there is nothing to do and so
816 	 * we just return.
817 	 */
818 	if (! inbuf || ! (*inbuf))
819 		return ((size_t)0);
820 
821 	ret_val = 0;
822 	ib = (uchar_t *)*inbuf;
823 	ob = (uchar_t *)*outbuf;
824 	ibtail = ib + *inbytesleft;
825 	obtail = ob + *outbytesleft;
826 
827 	tbl = ((ulong_t)kcd == KICONV_TBLID_720) ?
828 	    (kiconv_to_utf8_tbl_comp_t *)cp720_to_u8_tbl :
829 	    (kiconv_to_utf8_tbl_comp_t *)to_u8_tbl[(ulong_t)kcd];
830 
831 	while (ib < ibtail) {
832 		/*
833 		 * If this is a 7-bit ASCII character, we just copy over and
834 		 * that's all we need to do for this character.
835 		 */
836 		if (*ib < 0x80) {
837 			if (ob >= obtail) {
838 				*errno = E2BIG;
839 				ret_val = (size_t)-1;
840 				break;
841 			}
842 
843 			*ob++ = *ib++;
844 			continue;
845 		}
846 
847 		/*
848 		 * Otherwise, we get the corresponding UTF-8 character bytes
849 		 * from the mapping table and copy them over.
850 		 *
851 		 * We don't need to worry about if the UTF-8 character bytes
852 		 * at the mapping tables are valid or not since they are good.
853 		 */
854 		k = *ib - 0x80;
855 		sz = u8_number_of_bytes[tbl[k].u8[0]];
856 
857 		/*
858 		 * If (sz <= 0), that means the character in the input buffer
859 		 * is an illegal character possibly unassigned or non-character
860 		 * at the fromcode single byte codeset.
861 		 */
862 		if (sz <= 0) {
863 			*errno = EILSEQ;
864 			ret_val = (size_t)-1;
865 			break;
866 		}
867 
868 		if ((obtail - ob) < sz) {
869 			*errno = E2BIG;
870 			ret_val = (size_t)-1;
871 			break;
872 		}
873 
874 		for (i = 0; i < sz; i++)
875 			*ob++ = tbl[k].u8[i];
876 
877 		ib++;
878 	}
879 
880 	*inbuf = (char *)ib;
881 	*inbytesleft = ibtail - ib;
882 	*outbuf = (char *)ob;
883 	*outbytesleft = obtail - ob;
884 
885 	return (ret_val);
886 }
887 
888 /*
889  * The following is the common kiconvstr function for the conversions from
890  * UTF-8 to single byte codeset.
891  */
892 static size_t
893 kiconvstr_to_sb(size_t id, uchar_t *ib, size_t *inlen, uchar_t *ob,
894 	size_t *outlen, int flag, int *errno)
895 {
896 	kiconv_to_sb_tbl_comp_t *tbl;
897 	size_t ret_val;
898 	uchar_t *oldib;
899 	uchar_t *ibtail;
900 	uchar_t *obtail;
901 	uint32_t u8;
902 	size_t i;
903 	size_t l;
904 	size_t h;
905 	size_t init_h;
906 	int8_t sz;
907 	boolean_t second;
908 	boolean_t do_not_ignore_null;
909 
910 	/* Let's double check on the table id. */
911 	if (id > KICONV_MAX_MAPPING_TBLID &&
912 	    (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
913 		*errno = EBADF;
914 		return ((size_t)-1);
915 	}
916 
917 	ret_val = 0;
918 	ibtail = ib + *inlen;
919 	obtail = ob + *outlen;
920 	do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
921 
922 	if (id == KICONV_TBLID_720) {
923 		tbl = (kiconv_to_sb_tbl_comp_t *)u8_to_cp720_tbl;
924 		init_h = sizeof (u8_to_cp720_tbl);
925 	} else {
926 		tbl = (kiconv_to_sb_tbl_comp_t *)to_sb_tbl[id];
927 		init_h = sizeof (to_sb_tbl[id]);
928 	}
929 	init_h = init_h / sizeof (kiconv_to_sb_tbl_comp_t) - 1;
930 
931 	/* Skip any UTF-8 signature BOM character in the beginning. */
932 	if ((ibtail - ib) >= 3 && *ib == 0xef && *(ib + 1) == 0xbb &&
933 	    *(ib + 2) == 0xbf)
934 			ib += 3;
935 
936 	/*
937 	 * Basically this is pretty much the same as kiconv_to_sb() except
938 	 * that we are now accepting two flag values and doing the processing
939 	 * accordingly.
940 	 */
941 	while (ib < ibtail) {
942 		sz = u8_number_of_bytes[*ib];
943 		if (sz <= 0) {
944 			if (flag & KICONV_REPLACE_INVALID) {
945 				if (ob >= obtail) {
946 					*errno = E2BIG;
947 					ret_val = (size_t)-1;
948 					break;
949 				}
950 
951 				ib++;
952 				goto STR_TO_SB_REPLACE_INVALID;
953 			}
954 
955 			*errno = EILSEQ;
956 			ret_val = (size_t)-1;
957 			break;
958 		}
959 
960 		if (*ib == '\0' && do_not_ignore_null)
961 			break;
962 
963 		if (ob >= obtail) {
964 			*errno = E2BIG;
965 			ret_val = (size_t)-1;
966 			break;
967 		}
968 
969 		if (sz == 1) {
970 			*ob++ = *ib++;
971 			continue;
972 		}
973 
974 		if ((ibtail - ib) < sz) {
975 			if (flag & KICONV_REPLACE_INVALID) {
976 				ib = ibtail;
977 				goto STR_TO_SB_REPLACE_INVALID;
978 			}
979 
980 			*errno = EINVAL;
981 			ret_val = (size_t)-1;
982 			break;
983 		}
984 
985 		oldib = ib;
986 		u8 = *ib++;
987 		second = B_TRUE;
988 		for (i = 1; i < sz; i++) {
989 			if (second) {
990 				if (*ib < u8_valid_min_2nd_byte[u8] ||
991 				    *ib > u8_valid_max_2nd_byte[u8]) {
992 					if (flag & KICONV_REPLACE_INVALID) {
993 						ib = oldib + sz;
994 						goto STR_TO_SB_REPLACE_INVALID;
995 					}
996 
997 					*errno = EILSEQ;
998 					ret_val = (size_t)-1;
999 					ib = oldib;
1000 					goto STR_TO_SB_ILLEGAL_CHAR_ERR;
1001 				}
1002 				second = B_FALSE;
1003 			} else if (*ib < 0x80 || *ib > 0xbf) {
1004 				if (flag & KICONV_REPLACE_INVALID) {
1005 					ib = oldib + sz;
1006 					goto STR_TO_SB_REPLACE_INVALID;
1007 				}
1008 
1009 				*errno = EILSEQ;
1010 				ret_val = (size_t)-1;
1011 				ib = oldib;
1012 				goto STR_TO_SB_ILLEGAL_CHAR_ERR;
1013 			}
1014 			u8 = (u8 << 8) | ((uint32_t)*ib);
1015 			ib++;
1016 		}
1017 
1018 		i = l = 0;
1019 		h = init_h;
1020 		while (l <= h) {
1021 			i = (l + h) / 2;
1022 			if (tbl[i].u8 == u8)
1023 				break;
1024 			else if (tbl[i].u8 < u8)
1025 				l = i + 1;
1026 			else
1027 				h = i - 1;
1028 		}
1029 
1030 		if (tbl[i].u8 == u8) {
1031 			*ob++ = tbl[i].sb;
1032 		} else {
1033 STR_TO_SB_REPLACE_INVALID:
1034 			*ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
1035 			ret_val++;
1036 		}
1037 	}
1038 
1039 STR_TO_SB_ILLEGAL_CHAR_ERR:
1040 	*inlen = ibtail - ib;
1041 	*outlen = obtail - ob;
1042 
1043 	return (ret_val);
1044 }
1045 
1046 /*
1047  * The following 25 functions are the real entry points that will be
1048  * given to the kiconv framework at the genunix.
1049  */
1050 static size_t
1051 kiconvstr_to_720(char *inarray, size_t *inlen, char *outarray,
1052 	size_t *outlen, int flag, int *errno)
1053 {
1054 	return (kiconvstr_to_sb(KICONV_TBLID_720, (uchar_t *)inarray,
1055 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1056 }
1057 
1058 static size_t
1059 kiconvstr_to_737(char *inarray, size_t *inlen, char *outarray,
1060 	size_t *outlen, int flag, int *errno)
1061 {
1062 	return (kiconvstr_to_sb(KICONV_TBLID_737, (uchar_t *)inarray,
1063 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1064 }
1065 
1066 static size_t
1067 kiconvstr_to_852(char *inarray, size_t *inlen, char *outarray,
1068 	size_t *outlen, int flag, int *errno)
1069 {
1070 	return (kiconvstr_to_sb(KICONV_TBLID_852, (uchar_t *)inarray,
1071 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1072 }
1073 
1074 static size_t
1075 kiconvstr_to_857(char *inarray, size_t *inlen, char *outarray,
1076 	size_t *outlen, int flag, int *errno)
1077 {
1078 	return (kiconvstr_to_sb(KICONV_TBLID_857, (uchar_t *)inarray,
1079 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1080 }
1081 
1082 static size_t
1083 kiconvstr_to_862(char *inarray, size_t *inlen, char *outarray,
1084 	size_t *outlen, int flag, int *errno)
1085 {
1086 	return (kiconvstr_to_sb(KICONV_TBLID_862, (uchar_t *)inarray,
1087 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1088 }
1089 
1090 static size_t
1091 kiconvstr_to_866(char *inarray, size_t *inlen, char *outarray,
1092 	size_t *outlen, int flag, int *errno)
1093 {
1094 	return (kiconvstr_to_sb(KICONV_TBLID_866, (uchar_t *)inarray,
1095 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1096 }
1097 
1098 static size_t
1099 kiconvstr_to_1250(char *inarray, size_t *inlen, char *outarray,
1100 	size_t *outlen, int flag, int *errno)
1101 {
1102 	return (kiconvstr_to_sb(KICONV_TBLID_1250, (uchar_t *)inarray,
1103 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1104 }
1105 
1106 static size_t
1107 kiconvstr_to_1251(char *inarray, size_t *inlen, char *outarray,
1108 	size_t *outlen, int flag, int *errno)
1109 {
1110 	return (kiconvstr_to_sb(KICONV_TBLID_1251, (uchar_t *)inarray,
1111 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1112 }
1113 
1114 static size_t
1115 kiconvstr_to_1253(char *inarray, size_t *inlen, char *outarray,
1116 	size_t *outlen, int flag, int *errno)
1117 {
1118 	return (kiconvstr_to_sb(KICONV_TBLID_1253, (uchar_t *)inarray,
1119 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1120 }
1121 
1122 static size_t
1123 kiconvstr_to_1254(char *inarray, size_t *inlen, char *outarray,
1124 	size_t *outlen, int flag, int *errno)
1125 {
1126 	return (kiconvstr_to_sb(KICONV_TBLID_1254, (uchar_t *)inarray,
1127 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1128 }
1129 
1130 static size_t
1131 kiconvstr_to_1255(char *inarray, size_t *inlen, char *outarray,
1132 	size_t *outlen, int flag, int *errno)
1133 {
1134 	return (kiconvstr_to_sb(KICONV_TBLID_1255, (uchar_t *)inarray,
1135 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1136 }
1137 
1138 static size_t
1139 kiconvstr_to_1256(char *inarray, size_t *inlen, char *outarray,
1140 	size_t *outlen, int flag, int *errno)
1141 {
1142 	return (kiconvstr_to_sb(KICONV_TBLID_1256, (uchar_t *)inarray,
1143 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1144 }
1145 
1146 static size_t
1147 kiconvstr_to_1257(char *inarray, size_t *inlen, char *outarray,
1148 	size_t *outlen, int flag, int *errno)
1149 {
1150 	return (kiconvstr_to_sb(KICONV_TBLID_1257, (uchar_t *)inarray,
1151 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1152 }
1153 
1154 static size_t
1155 kiconvstr_to_88592(char *inarray, size_t *inlen, char *outarray,
1156 	size_t *outlen, int flag, int *errno)
1157 {
1158 	return (kiconvstr_to_sb(KICONV_TBLID_8859_2, (uchar_t *)inarray,
1159 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1160 }
1161 
1162 static size_t
1163 kiconvstr_to_88593(char *inarray, size_t *inlen, char *outarray,
1164 	size_t *outlen, int flag, int *errno)
1165 {
1166 	return (kiconvstr_to_sb(KICONV_TBLID_8859_3, (uchar_t *)inarray,
1167 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1168 }
1169 
1170 static size_t
1171 kiconvstr_to_88594(char *inarray, size_t *inlen, char *outarray,
1172 	size_t *outlen, int flag, int *errno)
1173 {
1174 	return (kiconvstr_to_sb(KICONV_TBLID_8859_4, (uchar_t *)inarray,
1175 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1176 }
1177 
1178 static size_t
1179 kiconvstr_to_88595(char *inarray, size_t *inlen, char *outarray,
1180 	size_t *outlen, int flag, int *errno)
1181 {
1182 	return (kiconvstr_to_sb(KICONV_TBLID_8859_5, (uchar_t *)inarray,
1183 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1184 }
1185 
1186 static size_t
1187 kiconvstr_to_88596(char *inarray, size_t *inlen, char *outarray,
1188 	size_t *outlen, int flag, int *errno)
1189 {
1190 	return (kiconvstr_to_sb(KICONV_TBLID_8859_6, (uchar_t *)inarray,
1191 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1192 }
1193 
1194 static size_t
1195 kiconvstr_to_88597(char *inarray, size_t *inlen, char *outarray,
1196 	size_t *outlen, int flag, int *errno)
1197 {
1198 	return (kiconvstr_to_sb(KICONV_TBLID_8859_7, (uchar_t *)inarray,
1199 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1200 }
1201 
1202 static size_t
1203 kiconvstr_to_88598(char *inarray, size_t *inlen, char *outarray,
1204 	size_t *outlen, int flag, int *errno)
1205 {
1206 	return (kiconvstr_to_sb(KICONV_TBLID_8859_8, (uchar_t *)inarray,
1207 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1208 }
1209 
1210 static size_t
1211 kiconvstr_to_88599(char *inarray, size_t *inlen, char *outarray,
1212 	size_t *outlen, int flag, int *errno)
1213 {
1214 	return (kiconvstr_to_sb(KICONV_TBLID_8859_9, (uchar_t *)inarray,
1215 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1216 }
1217 
1218 static size_t
1219 kiconvstr_to_885910(char *inarray, size_t *inlen, char *outarray,
1220 	size_t *outlen, int flag, int *errno)
1221 {
1222 	return (kiconvstr_to_sb(KICONV_TBLID_8859_10, (uchar_t *)inarray,
1223 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1224 }
1225 
1226 static size_t
1227 kiconvstr_to_885911(char *inarray, size_t *inlen, char *outarray,
1228 	size_t *outlen, int flag, int *errno)
1229 {
1230 	return (kiconvstr_to_sb(KICONV_TBLID_8859_11, (uchar_t *)inarray,
1231 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1232 }
1233 
1234 static size_t
1235 kiconvstr_to_885913(char *inarray, size_t *inlen, char *outarray,
1236 	size_t *outlen, int flag, int *errno)
1237 {
1238 	return (kiconvstr_to_sb(KICONV_TBLID_8859_13, (uchar_t *)inarray,
1239 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1240 }
1241 
1242 static size_t
1243 kiconvstr_to_koi8r(char *inarray, size_t *inlen, char *outarray,
1244 	size_t *outlen, int flag, int *errno)
1245 {
1246 	return (kiconvstr_to_sb(KICONV_TBLID_KOI8_R, (uchar_t *)inarray,
1247 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1248 }
1249 
1250 /*
1251  * The following is the common kiconvstr function for the conversions from
1252  * single byte codeset to UTF-8.
1253  */
1254 static size_t
1255 kiconvstr_fr_sb(size_t id, uchar_t *ib, size_t *inlen, uchar_t *ob,
1256 	size_t *outlen, int flag, int *errno)
1257 {
1258 	kiconv_to_utf8_tbl_comp_t *tbl;
1259 	size_t ret_val;
1260 	uchar_t *ibtail;
1261 	uchar_t *obtail;
1262 	size_t i;
1263 	size_t k;
1264 	int8_t sz;
1265 	boolean_t do_not_ignore_null;
1266 
1267 	if (id > KICONV_MAX_MAPPING_TBLID &&
1268 	    (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
1269 		*errno = EBADF;
1270 		return ((size_t)-1);
1271 	}
1272 
1273 	ret_val = 0;
1274 	ibtail = ib + *inlen;
1275 	obtail = ob + *outlen;
1276 	do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
1277 
1278 	tbl = (id == KICONV_TBLID_720) ?
1279 	    (kiconv_to_utf8_tbl_comp_t *)cp720_to_u8_tbl :
1280 	    (kiconv_to_utf8_tbl_comp_t *)to_u8_tbl[id];
1281 
1282 	while (ib < ibtail) {
1283 		if (*ib == '\0' && do_not_ignore_null)
1284 			break;
1285 
1286 		if (*ib < 0x80) {
1287 			if (ob >= obtail) {
1288 				*errno = E2BIG;
1289 				ret_val = (size_t)-1;
1290 				break;
1291 			}
1292 			*ob++ = *ib++;
1293 			continue;
1294 		}
1295 
1296 		k = *ib - 0x80;
1297 		sz = u8_number_of_bytes[tbl[k].u8[0]];
1298 
1299 		if (sz <= 0) {
1300 			if (flag & KICONV_REPLACE_INVALID) {
1301 				if ((obtail - ob) < 3) {
1302 					*errno = E2BIG;
1303 					ret_val = (size_t)-1;
1304 					break;
1305 				}
1306 
1307 				/* Save KICONV_UTF8_REPLACEMENT_CHAR. */
1308 				*ob++ = 0xef;
1309 				*ob++ = 0xbf;
1310 				*ob++ = 0xbd;
1311 				ret_val++;
1312 				ib++;
1313 
1314 				continue;
1315 			}
1316 
1317 			*errno = EILSEQ;
1318 			ret_val = (size_t)-1;
1319 			break;
1320 		}
1321 
1322 		if ((obtail - ob) < sz) {
1323 			*errno = E2BIG;
1324 			ret_val = (size_t)-1;
1325 			break;
1326 		}
1327 
1328 		for (i = 0; i < sz; i++)
1329 			*ob++ = tbl[k].u8[i];
1330 
1331 		ib++;
1332 	}
1333 
1334 	*inlen = ibtail - ib;
1335 	*outlen = obtail - ob;
1336 
1337 	return (ret_val);
1338 }
1339 
1340 /*
1341  * The following 25 functions are the real entry points that will be
1342  * given to kiconv framework at the genunix.
1343  */
1344 static size_t
1345 kiconvstr_fr_720(char *inarray, size_t *inlen, char *outarray,
1346 	size_t *outlen, int flag, int *errno)
1347 {
1348 	return (kiconvstr_fr_sb(KICONV_TBLID_720, (uchar_t *)inarray,
1349 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1350 }
1351 
1352 static size_t
1353 kiconvstr_fr_737(char *inarray, size_t *inlen, char *outarray,
1354 	size_t *outlen, int flag, int *errno)
1355 {
1356 	return (kiconvstr_fr_sb(KICONV_TBLID_737, (uchar_t *)inarray,
1357 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1358 }
1359 
1360 static size_t
1361 kiconvstr_fr_852(char *inarray, size_t *inlen, char *outarray,
1362 	size_t *outlen, int flag, int *errno)
1363 {
1364 	return (kiconvstr_fr_sb(KICONV_TBLID_852, (uchar_t *)inarray,
1365 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1366 }
1367 
1368 static size_t
1369 kiconvstr_fr_857(char *inarray, size_t *inlen, char *outarray,
1370 	size_t *outlen, int flag, int *errno)
1371 {
1372 	return (kiconvstr_fr_sb(KICONV_TBLID_857, (uchar_t *)inarray,
1373 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1374 }
1375 
1376 static size_t
1377 kiconvstr_fr_862(char *inarray, size_t *inlen, char *outarray,
1378 	size_t *outlen, int flag, int *errno)
1379 {
1380 	return (kiconvstr_fr_sb(KICONV_TBLID_862, (uchar_t *)inarray,
1381 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1382 }
1383 
1384 static size_t
1385 kiconvstr_fr_866(char *inarray, size_t *inlen, char *outarray,
1386 	size_t *outlen, int flag, int *errno)
1387 {
1388 	return (kiconvstr_fr_sb(KICONV_TBLID_866, (uchar_t *)inarray,
1389 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1390 }
1391 
1392 static size_t
1393 kiconvstr_fr_1250(char *inarray, size_t *inlen, char *outarray,
1394 	size_t *outlen, int flag, int *errno)
1395 {
1396 	return (kiconvstr_fr_sb(KICONV_TBLID_1250, (uchar_t *)inarray,
1397 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1398 }
1399 
1400 static size_t
1401 kiconvstr_fr_1251(char *inarray, size_t *inlen, char *outarray,
1402 	size_t *outlen, int flag, int *errno)
1403 {
1404 	return (kiconvstr_fr_sb(KICONV_TBLID_1251, (uchar_t *)inarray,
1405 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1406 }
1407 
1408 static size_t
1409 kiconvstr_fr_1253(char *inarray, size_t *inlen, char *outarray,
1410 	size_t *outlen, int flag, int *errno)
1411 {
1412 	return (kiconvstr_fr_sb(KICONV_TBLID_1253, (uchar_t *)inarray,
1413 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1414 }
1415 
1416 static size_t
1417 kiconvstr_fr_1254(char *inarray, size_t *inlen, char *outarray,
1418 	size_t *outlen, int flag, int *errno)
1419 {
1420 	return (kiconvstr_fr_sb(KICONV_TBLID_1254, (uchar_t *)inarray,
1421 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1422 }
1423 
1424 static size_t
1425 kiconvstr_fr_1255(char *inarray, size_t *inlen, char *outarray,
1426 	size_t *outlen, int flag, int *errno)
1427 {
1428 	return (kiconvstr_fr_sb(KICONV_TBLID_1255, (uchar_t *)inarray,
1429 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1430 }
1431 
1432 static size_t
1433 kiconvstr_fr_1256(char *inarray, size_t *inlen, char *outarray,
1434 	size_t *outlen, int flag, int *errno)
1435 {
1436 	return (kiconvstr_fr_sb(KICONV_TBLID_1256, (uchar_t *)inarray,
1437 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1438 }
1439 
1440 static size_t
1441 kiconvstr_fr_1257(char *inarray, size_t *inlen, char *outarray,
1442 	size_t *outlen, int flag, int *errno)
1443 {
1444 	return (kiconvstr_fr_sb(KICONV_TBLID_1257, (uchar_t *)inarray,
1445 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1446 }
1447 
1448 static size_t
1449 kiconvstr_fr_88592(char *inarray, size_t *inlen, char *outarray,
1450 	size_t *outlen, int flag, int *errno)
1451 {
1452 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_2, (uchar_t *)inarray,
1453 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1454 }
1455 
1456 static size_t
1457 kiconvstr_fr_88593(char *inarray, size_t *inlen, char *outarray,
1458 	size_t *outlen, int flag, int *errno)
1459 {
1460 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_3, (uchar_t *)inarray,
1461 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1462 }
1463 
1464 static size_t
1465 kiconvstr_fr_88594(char *inarray, size_t *inlen, char *outarray,
1466 	size_t *outlen, int flag, int *errno)
1467 {
1468 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_4, (uchar_t *)inarray,
1469 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1470 }
1471 
1472 static size_t
1473 kiconvstr_fr_88595(char *inarray, size_t *inlen, char *outarray,
1474 	size_t *outlen, int flag, int *errno)
1475 {
1476 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_5, (uchar_t *)inarray,
1477 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1478 }
1479 
1480 static size_t
1481 kiconvstr_fr_88596(char *inarray, size_t *inlen, char *outarray,
1482 	size_t *outlen, int flag, int *errno)
1483 {
1484 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_6, (uchar_t *)inarray,
1485 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1486 }
1487 
1488 static size_t
1489 kiconvstr_fr_88597(char *inarray, size_t *inlen, char *outarray,
1490 	size_t *outlen, int flag, int *errno)
1491 {
1492 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_7, (uchar_t *)inarray,
1493 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1494 }
1495 
1496 static size_t
1497 kiconvstr_fr_88598(char *inarray, size_t *inlen, char *outarray,
1498 	size_t *outlen, int flag, int *errno)
1499 {
1500 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_8, (uchar_t *)inarray,
1501 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1502 }
1503 
1504 static size_t
1505 kiconvstr_fr_88599(char *inarray, size_t *inlen, char *outarray,
1506 	size_t *outlen, int flag, int *errno)
1507 {
1508 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_9, (uchar_t *)inarray,
1509 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1510 }
1511 
1512 static size_t
1513 kiconvstr_fr_885910(char *inarray, size_t *inlen, char *outarray,
1514 	size_t *outlen, int flag, int *errno)
1515 {
1516 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_10, (uchar_t *)inarray,
1517 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1518 }
1519 
1520 static size_t
1521 kiconvstr_fr_885911(char *inarray, size_t *inlen, char *outarray,
1522 	size_t *outlen, int flag, int *errno)
1523 {
1524 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_11, (uchar_t *)inarray,
1525 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1526 }
1527 
1528 static size_t
1529 kiconvstr_fr_885913(char *inarray, size_t *inlen, char *outarray,
1530 	size_t *outlen, int flag, int *errno)
1531 {
1532 	return (kiconvstr_fr_sb(KICONV_TBLID_8859_13, (uchar_t *)inarray,
1533 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1534 }
1535 
1536 static size_t
1537 kiconvstr_fr_koi8r(char *inarray, size_t *inlen, char *outarray,
1538 	size_t *outlen, int flag, int *errno)
1539 {
1540 	return (kiconvstr_fr_sb(KICONV_TBLID_KOI8_R, (uchar_t *)inarray,
1541 	    inlen, (uchar_t *)outarray, outlen, flag, errno));
1542 }
1543 
1544 
1545 /*
1546  * The following are the supported code conversions that will be passed to
1547  * and registered from this module. The tocode and fromcode names are
1548  * normalized.
1549  */
1550 #define	KICONV_MAX_EMEA_OPS		50
1551 
1552 static kiconv_ops_t kiconv_emea_ops[KICONV_MAX_EMEA_OPS] = {
1553 	{
1554 		"utf8", "cp1250",
1555 		open_fr_1250, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1250
1556 	},
1557 	{
1558 		"cp1250", "utf8",
1559 		open_to_1250, kiconv_to_sb, close_to_sb, kiconvstr_to_1250
1560 	},
1561 	{
1562 		"utf8", "iso88592",
1563 		open_fr_88592, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88592
1564 	},
1565 	{
1566 		"iso88592", "utf8",
1567 		open_to_88592, kiconv_to_sb, close_to_sb, kiconvstr_to_88592
1568 	},
1569 	{
1570 		"utf8", "cp852",
1571 		open_fr_852, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_852
1572 	},
1573 	{
1574 		"cp852", "utf8",
1575 		open_to_852, kiconv_to_sb, close_to_sb, kiconvstr_to_852
1576 	},
1577 	{
1578 		"utf8", "cp1251",
1579 		open_fr_1251, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1251
1580 	},
1581 	{
1582 		"cp1251", "utf8",
1583 		open_to_1251, kiconv_to_sb, close_to_sb, kiconvstr_to_1251
1584 	},
1585 	{
1586 		"utf8", "iso88595",
1587 		open_fr_88595, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88595
1588 	},
1589 	{
1590 		"iso88595", "utf8",
1591 		open_to_88595, kiconv_to_sb, close_to_sb, kiconvstr_to_88595
1592 	},
1593 	{
1594 		"utf8", "koi8r",
1595 		open_fr_koi8r, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_koi8r
1596 	},
1597 	{
1598 		"koi8r", "utf8",
1599 		open_to_koi8r, kiconv_to_sb, close_to_sb, kiconvstr_to_koi8r
1600 	},
1601 	{
1602 		"utf8", "cp866",
1603 		open_fr_866, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_866
1604 	},
1605 	{
1606 		"cp866", "utf8",
1607 		open_to_866, kiconv_to_sb, close_to_sb, kiconvstr_to_866
1608 	},
1609 	{
1610 		"utf8", "cp1253",
1611 		open_fr_1253, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1253
1612 	},
1613 	{
1614 		"cp1253", "utf8",
1615 		open_to_1253, kiconv_to_sb, close_to_sb, kiconvstr_to_1253
1616 	},
1617 	{
1618 		"utf8", "iso88597",
1619 		open_fr_88597, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88597
1620 	},
1621 	{
1622 		"iso88597", "utf8",
1623 		open_to_88597, kiconv_to_sb, close_to_sb, kiconvstr_to_88597
1624 	},
1625 	{
1626 		"utf8", "cp737",
1627 		open_fr_737, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_737
1628 	},
1629 	{
1630 		"cp737", "utf8",
1631 		open_to_737, kiconv_to_sb, close_to_sb, kiconvstr_to_737
1632 	},
1633 	{
1634 		"utf8", "cp1254",
1635 		open_fr_1254, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1254
1636 	},
1637 	{
1638 		"cp1254", "utf8",
1639 		open_to_1254, kiconv_to_sb, close_to_sb, kiconvstr_to_1254
1640 	},
1641 	{
1642 		"utf8", "iso88599",
1643 		open_fr_88599, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88599
1644 	},
1645 	{
1646 		"iso88599", "utf8",
1647 		open_to_88599, kiconv_to_sb, close_to_sb, kiconvstr_to_88599
1648 	},
1649 	{
1650 		"utf8", "cp857",
1651 		open_fr_857, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_857
1652 	},
1653 	{
1654 		"cp857", "utf8",
1655 		open_to_857, kiconv_to_sb, close_to_sb, kiconvstr_to_857
1656 	},
1657 	{
1658 		"utf8", "cp1256",
1659 		open_fr_1256, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1256
1660 	},
1661 	{
1662 		"cp1256", "utf8",
1663 		open_to_1256, kiconv_to_sb, close_to_sb, kiconvstr_to_1256
1664 	},
1665 	{
1666 		"utf8", "iso88596",
1667 		open_fr_88596, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88596
1668 	},
1669 	{
1670 		"iso88596", "utf8",
1671 		open_to_88596, kiconv_to_sb, close_to_sb, kiconvstr_to_88596
1672 	},
1673 	{
1674 		"utf8", "cp720",
1675 		open_fr_720, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_720
1676 	},
1677 	{
1678 		"cp720", "utf8",
1679 		open_to_720, kiconv_to_sb, close_to_sb, kiconvstr_to_720
1680 	},
1681 	{
1682 		"utf8", "cp1255",
1683 		open_fr_1255, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1255
1684 	},
1685 	{
1686 		"cp1255", "utf8",
1687 		open_to_1255, kiconv_to_sb, close_to_sb, kiconvstr_to_1255
1688 	},
1689 	{
1690 		"utf8", "iso88598",
1691 		open_fr_88598, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88598
1692 	},
1693 	{
1694 		"iso88598", "utf8",
1695 		open_to_88598, kiconv_to_sb, close_to_sb, kiconvstr_to_88598
1696 	},
1697 	{
1698 		"utf8", "cp862",
1699 		open_fr_862, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_862
1700 	},
1701 	{
1702 		"cp862", "utf8",
1703 		open_to_862, kiconv_to_sb, close_to_sb, kiconvstr_to_862
1704 	},
1705 	{
1706 		"utf8", "cp1257",
1707 		open_fr_1257, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1257
1708 	},
1709 	{
1710 		"cp1257", "utf8",
1711 		open_to_1257, kiconv_to_sb, close_to_sb, kiconvstr_to_1257
1712 	},
1713 	{
1714 		"utf8", "iso885913",
1715 		open_fr_885913, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885913
1716 	},
1717 	{
1718 		"iso885913", "utf8",
1719 		open_to_885913, kiconv_to_sb, close_to_sb, kiconvstr_to_885913
1720 	},
1721 	{
1722 		"utf8", "iso885910",
1723 		open_fr_885910, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885910
1724 	},
1725 	{
1726 		"iso885910", "utf8",
1727 		open_to_885910, kiconv_to_sb, close_to_sb, kiconvstr_to_885910
1728 	},
1729 	{
1730 		"utf8", "iso885911",
1731 		open_fr_885911, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885911
1732 	},
1733 	{
1734 		"iso885911", "utf8",
1735 		open_to_885911, kiconv_to_sb, close_to_sb, kiconvstr_to_885911
1736 	},
1737 	{
1738 		"utf8", "iso88593",
1739 		open_fr_88593, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88593
1740 	},
1741 	{
1742 		"iso88593", "utf8",
1743 		open_to_88593, kiconv_to_sb, close_to_sb, kiconvstr_to_88593
1744 	},
1745 	{
1746 		"utf8", "iso88594",
1747 		open_fr_88594, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88594
1748 	},
1749 	{
1750 		"iso88594", "utf8",
1751 		open_to_88594, kiconv_to_sb, close_to_sb, kiconvstr_to_88594
1752 	},
1753 };
1754 
1755 static kiconv_module_info_t kiconv_emea_modinfo = {
1756 	"kiconv_emea",		/* Must be the same as in kiconv framework. */
1757 	KICONV_MAX_EMEA_OPS,	/* size_t kiconv_num_convs */
1758 	kiconv_emea_ops,	/* kiconv_ops_t *kiconv_ops_tbl */
1759 	0,			/* size_t kiconv_num_aliases */
1760 	NULL,			/* char **aliases */
1761 	NULL,			/* char **canonicals */
1762 	0			/* int nowait */
1763 };
1764 
1765 static struct modlkiconv kiconv_emea = {
1766 	&mod_kiconvops,
1767 	"kiconv module for EMEA",
1768 	&kiconv_emea_modinfo
1769 };
1770 
1771 static struct modlinkage linkage = {
1772 	MODREV_1,
1773 	(void *)&kiconv_emea,
1774 	NULL
1775 };
1776 
1777 int
1778 _init()
1779 {
1780 	int err;
1781 
1782 	err = mod_install(&linkage);
1783 	if (err)
1784 		cmn_err(CE_WARN, "kiconv_emea: failed to load kernel module");
1785 
1786 	return (err);
1787 }
1788 
1789 int
1790 _info(struct modinfo *modinfop)
1791 {
1792 	return (mod_info(&linkage, modinfop));
1793 }
1794 
1795 int
1796 _fini()
1797 {
1798 	int err;
1799 
1800 	/*
1801 	 * If this module is being used, then, we cannot remove the module.
1802 	 * The following checking will catch pretty much all usual cases.
1803 	 *
1804 	 * Any remaining will be catached by the kiconv_unregister_module()
1805 	 * during mod_remove() at below.
1806 	 */
1807 	if (kiconv_module_ref_count(KICONV_MODULE_ID_EMEA))
1808 		return (EBUSY);
1809 
1810 	err = mod_remove(&linkage);
1811 	if (err)
1812 		cmn_err(CE_WARN, "kiconv_emea: failed to remove kernel module");
1813 
1814 	return (err);
1815 }
1816