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