kiconv_emea.c revision 5206:34f0b41fc3c5
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 */
97extern const int8_t u8_number_of_bytes[];
98extern const uint8_t u8_valid_min_2nd_byte[];
99extern 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 */
106static void *
107open_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
118static void *
119open_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
130static void *
131open_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
142static void *
143open_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
154static void *
155open_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
166static void *
167open_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
178static void *
179open_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
190static void *
191open_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
202static void *
203open_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
214static void *
215open_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
226static void *
227open_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
238static void *
239open_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
250static void *
251open_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
262static void *
263open_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
274static void *
275open_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
286static void *
287open_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
298static void *
299open_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
310static void *
311open_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
322static void *
323open_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
334static void *
335open_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
346static void *
347open_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
358static void *
359open_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
370static void *
371open_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
382static void *
383open_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
394static void *
395open_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 */
410static void *
411open_fr_720()
412{
413	return ((void *)KICONV_TBLID_720);
414}
415
416static void *
417open_fr_737()
418{
419	return ((void *)KICONV_TBLID_737);
420}
421
422static void *
423open_fr_852()
424{
425	return ((void *)KICONV_TBLID_852);
426}
427
428static void *
429open_fr_857()
430{
431	return ((void *)KICONV_TBLID_857);
432}
433
434static void *
435open_fr_862()
436{
437	return ((void *)KICONV_TBLID_862);
438}
439
440static void *
441open_fr_866()
442{
443	return ((void *)KICONV_TBLID_866);
444}
445
446static void *
447open_fr_1250()
448{
449	return ((void *)KICONV_TBLID_1250);
450}
451
452static void *
453open_fr_1251()
454{
455	return ((void *)KICONV_TBLID_1251);
456}
457
458static void *
459open_fr_1253()
460{
461	return ((void *)KICONV_TBLID_1253);
462}
463
464static void *
465open_fr_1254()
466{
467	return ((void *)KICONV_TBLID_1254);
468}
469
470static void *
471open_fr_1255()
472{
473	return ((void *)KICONV_TBLID_1255);
474}
475
476static void *
477open_fr_1256()
478{
479	return ((void *)KICONV_TBLID_1256);
480}
481
482static void *
483open_fr_1257()
484{
485	return ((void *)KICONV_TBLID_1257);
486}
487
488static void *
489open_fr_88592()
490{
491	return ((void *)KICONV_TBLID_8859_2);
492}
493
494static void *
495open_fr_88593()
496{
497	return ((void *)KICONV_TBLID_8859_3);
498}
499
500static void *
501open_fr_88594()
502{
503	return ((void *)KICONV_TBLID_8859_4);
504}
505
506static void *
507open_fr_88595()
508{
509	return ((void *)KICONV_TBLID_8859_5);
510}
511
512static void *
513open_fr_88596()
514{
515	return ((void *)KICONV_TBLID_8859_6);
516}
517
518static void *
519open_fr_88597()
520{
521	return ((void *)KICONV_TBLID_8859_7);
522}
523
524static void *
525open_fr_88598()
526{
527	return ((void *)KICONV_TBLID_8859_8);
528}
529
530static void *
531open_fr_88599()
532{
533	return ((void *)KICONV_TBLID_8859_9);
534}
535
536static void *
537open_fr_885910()
538{
539	return ((void *)KICONV_TBLID_8859_10);
540}
541
542static void *
543open_fr_885911()
544{
545	return ((void *)KICONV_TBLID_8859_11);
546}
547
548static void *
549open_fr_885913()
550{
551	return ((void *)KICONV_TBLID_8859_13);
552}
553
554static void *
555open_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 */
564static int
565close_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 */
579static int
580close_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 */
599static size_t
600kiconv_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
779TO_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 */
792static size_t
793kiconv_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 */
892static size_t
893kiconvstr_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 {
1033STR_TO_SB_REPLACE_INVALID:
1034			*ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
1035			ret_val++;
1036		}
1037	}
1038
1039STR_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 */
1050static size_t
1051kiconvstr_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
1058static size_t
1059kiconvstr_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
1066static size_t
1067kiconvstr_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
1074static size_t
1075kiconvstr_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
1082static size_t
1083kiconvstr_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
1090static size_t
1091kiconvstr_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
1098static size_t
1099kiconvstr_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
1106static size_t
1107kiconvstr_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
1114static size_t
1115kiconvstr_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
1122static size_t
1123kiconvstr_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
1130static size_t
1131kiconvstr_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
1138static size_t
1139kiconvstr_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
1146static size_t
1147kiconvstr_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
1154static size_t
1155kiconvstr_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
1162static size_t
1163kiconvstr_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
1170static size_t
1171kiconvstr_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
1178static size_t
1179kiconvstr_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
1186static size_t
1187kiconvstr_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
1194static size_t
1195kiconvstr_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
1202static size_t
1203kiconvstr_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
1210static size_t
1211kiconvstr_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
1218static size_t
1219kiconvstr_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
1226static size_t
1227kiconvstr_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
1234static size_t
1235kiconvstr_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
1242static size_t
1243kiconvstr_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 */
1254static size_t
1255kiconvstr_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 */
1344static size_t
1345kiconvstr_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
1352static size_t
1353kiconvstr_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
1360static size_t
1361kiconvstr_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
1368static size_t
1369kiconvstr_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
1376static size_t
1377kiconvstr_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
1384static size_t
1385kiconvstr_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
1392static size_t
1393kiconvstr_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
1400static size_t
1401kiconvstr_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
1408static size_t
1409kiconvstr_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
1416static size_t
1417kiconvstr_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
1424static size_t
1425kiconvstr_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
1432static size_t
1433kiconvstr_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
1440static size_t
1441kiconvstr_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
1448static size_t
1449kiconvstr_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
1456static size_t
1457kiconvstr_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
1464static size_t
1465kiconvstr_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
1472static size_t
1473kiconvstr_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
1480static size_t
1481kiconvstr_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
1488static size_t
1489kiconvstr_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
1496static size_t
1497kiconvstr_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
1504static size_t
1505kiconvstr_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
1512static size_t
1513kiconvstr_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
1520static size_t
1521kiconvstr_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
1528static size_t
1529kiconvstr_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
1536static size_t
1537kiconvstr_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
1552static 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
1755static 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
1765static struct modlkiconv kiconv_emea = {
1766	&mod_kiconvops,
1767	"kiconv module for EMEA",
1768	&kiconv_emea_modinfo
1769};
1770
1771static struct modlinkage linkage = {
1772	MODREV_1,
1773	(void *)&kiconv_emea,
1774	NULL
1775};
1776
1777int
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
1789int
1790_info(struct modinfo *modinfop)
1791{
1792	return (mod_info(&linkage, modinfop));
1793}
1794
1795int
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