1 /*-------------------------------------------------------------------------
2  *
3  *	  Cyrillic and MULE_INTERNAL
4  *
5  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  * IDENTIFICATION
9  *	  src/backend/utils/mb/conversion_procs/cyrillic_and_mic/cyrillic_and_mic.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #include "postgres.h"
15 #include "fmgr.h"
16 #include "mb/pg_wchar.h"
17 
18 PG_MODULE_MAGIC;
19 
20 PG_FUNCTION_INFO_V1(koi8r_to_mic);
21 PG_FUNCTION_INFO_V1(mic_to_koi8r);
22 PG_FUNCTION_INFO_V1(iso_to_mic);
23 PG_FUNCTION_INFO_V1(mic_to_iso);
24 PG_FUNCTION_INFO_V1(win1251_to_mic);
25 PG_FUNCTION_INFO_V1(mic_to_win1251);
26 PG_FUNCTION_INFO_V1(win866_to_mic);
27 PG_FUNCTION_INFO_V1(mic_to_win866);
28 PG_FUNCTION_INFO_V1(koi8r_to_win1251);
29 PG_FUNCTION_INFO_V1(win1251_to_koi8r);
30 PG_FUNCTION_INFO_V1(koi8r_to_win866);
31 PG_FUNCTION_INFO_V1(win866_to_koi8r);
32 PG_FUNCTION_INFO_V1(win866_to_win1251);
33 PG_FUNCTION_INFO_V1(win1251_to_win866);
34 PG_FUNCTION_INFO_V1(iso_to_koi8r);
35 PG_FUNCTION_INFO_V1(koi8r_to_iso);
36 PG_FUNCTION_INFO_V1(iso_to_win1251);
37 PG_FUNCTION_INFO_V1(win1251_to_iso);
38 PG_FUNCTION_INFO_V1(iso_to_win866);
39 PG_FUNCTION_INFO_V1(win866_to_iso);
40 
41 /* ----------
42  * conv_proc(
43  *		INTEGER,	-- source encoding id
44  *		INTEGER,	-- destination encoding id
45  *		CSTRING,	-- source string (null terminated C string)
46  *		CSTRING,	-- destination string (null terminated C string)
47  *		INTEGER,	-- source string length
48  *		BOOL		-- if true, don't throw an error if conversion fails
49  * ) returns INTEGER;
50  *
51  * Returns the number of bytes successfully converted.
52  * ----------
53  */
54 
55 /*
56  * Cyrillic support
57  * currently supported Cyrillic encodings:
58  *
59  * KOI8-R (this is also the charset for the mule internal code for Cyrillic)
60  * ISO-8859-5
61  * Microsoft's CP1251 (windows-1251)
62  * Alternativny Variant (MS-DOS CP866)
63  */
64 
65 /* ISO-8859-5 to KOI8-R */
66 static const unsigned char iso2koi[] = {
67 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 	0x00, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 	0xE1, 0xE2, 0xF7, 0xE7, 0xE4, 0xE5, 0xF6, 0xFA,
74 	0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
75 	0xF2, 0xF3, 0xF4, 0xF5, 0xE6, 0xE8, 0xE3, 0xFE,
76 	0xFB, 0xFD, 0xFF, 0xF9, 0xF8, 0xFC, 0xE0, 0xF1,
77 	0xC1, 0xC2, 0xD7, 0xC7, 0xC4, 0xC5, 0xD6, 0xDA,
78 	0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
79 	0xD2, 0xD3, 0xD4, 0xD5, 0xC6, 0xC8, 0xC3, 0xDE,
80 	0xDB, 0xDD, 0xDF, 0xD9, 0xD8, 0xDC, 0xC0, 0xD1,
81 	0x00, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
83 };
84 
85 /* KOI8-R to ISO-8859-5 */
86 static const unsigned char koi2iso[] = {
87 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 	0x00, 0x00, 0x00, 0xF1, 0x00, 0x00, 0x00, 0x00,
92 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 	0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00,
94 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 	0xEE, 0xD0, 0xD1, 0xE6, 0xD4, 0xD5, 0xE4, 0xD3,
96 	0xE5, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE,
97 	0xDF, 0xEF, 0xE0, 0xE1, 0xE2, 0xE3, 0xD6, 0xD2,
98 	0xEC, 0xEB, 0xD7, 0xE8, 0xED, 0xE9, 0xE7, 0xEA,
99 	0xCE, 0xB0, 0xB1, 0xC6, 0xB4, 0xB5, 0xC4, 0xB3,
100 	0xC5, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
101 	0xBF, 0xCF, 0xC0, 0xC1, 0xC2, 0xC3, 0xB6, 0xB2,
102 	0xCC, 0xCB, 0xB7, 0xC8, 0xCD, 0xC9, 0xC7, 0xCA
103 };
104 
105 /* WIN1251 to KOI8-R */
106 static const unsigned char win12512koi[] = {
107 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 	0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00,
112 	0xB3, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x00, 0xB7,
113 	0x00, 0x00, 0xB6, 0xA6, 0xAD, 0x00, 0x00, 0x00,
114 	0xA3, 0x00, 0xA4, 0x00, 0x00, 0x00, 0x00, 0xA7,
115 	0xE1, 0xE2, 0xF7, 0xE7, 0xE4, 0xE5, 0xF6, 0xFA,
116 	0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
117 	0xF2, 0xF3, 0xF4, 0xF5, 0xE6, 0xE8, 0xE3, 0xFE,
118 	0xFB, 0xFD, 0xFF, 0xF9, 0xF8, 0xFC, 0xE0, 0xF1,
119 	0xC1, 0xC2, 0xD7, 0xC7, 0xC4, 0xC5, 0xD6, 0xDA,
120 	0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
121 	0xD2, 0xD3, 0xD4, 0xD5, 0xC6, 0xC8, 0xC3, 0xDE,
122 	0xDB, 0xDD, 0xDF, 0xD9, 0xD8, 0xDC, 0xC0, 0xD1
123 };
124 
125 /* KOI8-R to WIN1251 */
126 static const unsigned char koi2win1251[] = {
127 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 	0x00, 0x00, 0x00, 0xB8, 0xBA, 0x00, 0xB3, 0xBF,
132 	0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x00,
133 	0x00, 0x00, 0x00, 0xA8, 0xAA, 0x00, 0xB2, 0xAF,
134 	0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00,
135 	0xFE, 0xE0, 0xE1, 0xF6, 0xE4, 0xE5, 0xF4, 0xE3,
136 	0xF5, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE,
137 	0xEF, 0xFF, 0xF0, 0xF1, 0xF2, 0xF3, 0xE6, 0xE2,
138 	0xFC, 0xFB, 0xE7, 0xF8, 0xFD, 0xF9, 0xF7, 0xFA,
139 	0xDE, 0xC0, 0xC1, 0xD6, 0xC4, 0xC5, 0xD4, 0xC3,
140 	0xD5, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
141 	0xCF, 0xDF, 0xD0, 0xD1, 0xD2, 0xD3, 0xC6, 0xC2,
142 	0xDC, 0xDB, 0xC7, 0xD8, 0xDD, 0xD9, 0xD7, 0xDA
143 };
144 
145 /* WIN866 to KOI8-R */
146 static const unsigned char win8662koi[] = {
147 	0xE1, 0xE2, 0xF7, 0xE7, 0xE4, 0xE5, 0xF6, 0xFA,
148 	0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
149 	0xF2, 0xF3, 0xF4, 0xF5, 0xE6, 0xE8, 0xE3, 0xFE,
150 	0xFB, 0xFD, 0xFF, 0xF9, 0xF8, 0xFC, 0xE0, 0xF1,
151 	0xC1, 0xC2, 0xD7, 0xC7, 0xC4, 0xC5, 0xD6, 0xDA,
152 	0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
153 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 	0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00,
155 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 	0xD2, 0xD3, 0xD4, 0xD5, 0xC6, 0xC8, 0xC3, 0xDE,
160 	0xDB, 0xDD, 0xDF, 0xD9, 0xD8, 0xDC, 0xC0, 0xD1,
161 	0xB3, 0xA3, 0xB4, 0xA4, 0xB7, 0xA7, 0x00, 0x00,
162 	0xB6, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
163 };
164 
165 /* KOI8-R to WIN866 */
166 static const unsigned char koi2win866[] = {
167 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 	0x00, 0x00, 0x00, 0xF1, 0xF3, 0x00, 0xF9, 0xF5,
172 	0x00, 0x00, 0x00, 0x00, 0x00, 0xAD, 0x00, 0x00,
173 	0x00, 0x00, 0x00, 0xF0, 0xF2, 0x00, 0xF8, 0xF4,
174 	0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00,
175 	0xEE, 0xA0, 0xA1, 0xE6, 0xA4, 0xA5, 0xE4, 0xA3,
176 	0xE5, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE,
177 	0xAF, 0xEF, 0xE0, 0xE1, 0xE2, 0xE3, 0xA6, 0xA2,
178 	0xEC, 0xEB, 0xA7, 0xE8, 0xED, 0xE9, 0xE7, 0xEA,
179 	0x9E, 0x80, 0x81, 0x96, 0x84, 0x85, 0x94, 0x83,
180 	0x95, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E,
181 	0x8F, 0x9F, 0x90, 0x91, 0x92, 0x93, 0x86, 0x82,
182 	0x9C, 0x9B, 0x87, 0x98, 0x9D, 0x99, 0x97, 0x9A
183 };
184 
185 /* WIN866 to WIN1251 */
186 static const unsigned char win8662win1251[] = {
187 	0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
188 	0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
189 	0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
190 	0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
191 	0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
192 	0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
193 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 	0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0x00, 0x00,
195 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
200 	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
201 	0xA8, 0xB8, 0xAA, 0xBA, 0xAF, 0xBF, 0x00, 0x00,
202 	0xB2, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
203 };
204 
205 /* WIN1251 to WIN866 */
206 static const unsigned char win12512win866[] = {
207 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 	0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x00, 0x00,
212 	0xF0, 0x00, 0xF2, 0x00, 0x00, 0x00, 0x00, 0xF4,
213 	0x00, 0x00, 0xF8, 0xF9, 0xAD, 0x00, 0x00, 0x00,
214 	0xF1, 0x00, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xF5,
215 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
216 	0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
217 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
218 	0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
219 	0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
220 	0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
221 	0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
222 	0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF
223 };
224 
225 /* ISO-8859-5 to WIN1251 */
226 static const unsigned char iso2win1251[] = {
227 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 	0x00, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 	0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
234 	0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
235 	0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
236 	0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
237 	0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
238 	0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
239 	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
240 	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
241 	0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
243 };
244 
245 /* WIN1251 to ISO-8859-5 */
246 static const unsigned char win12512iso[] = {
247 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252 	0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254 	0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255 	0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
256 	0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
257 	0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
258 	0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
259 	0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
260 	0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
261 	0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
262 	0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF
263 };
264 
265 /* ISO-8859-5 to WIN866 */
266 static const unsigned char iso2win866[] = {
267 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 	0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
274 	0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
275 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
276 	0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
277 	0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
278 	0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
279 	0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
280 	0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
281 	0x00, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
283 };
284 
285 /* WIN866 to ISO-8859-5 */
286 static const unsigned char win8662iso[] = {
287 	0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
288 	0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
289 	0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
290 	0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
291 	0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
292 	0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
293 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 	0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
300 	0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
301 	0xA1, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
303 };
304 
305 
306 Datum
koi8r_to_mic(PG_FUNCTION_ARGS)307 koi8r_to_mic(PG_FUNCTION_ARGS)
308 {
309 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
310 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
311 	int			len = PG_GETARG_INT32(4);
312 	bool		noError = PG_GETARG_BOOL(5);
313 	int			converted;
314 
315 	CHECK_ENCODING_CONVERSION_ARGS(PG_KOI8R, PG_MULE_INTERNAL);
316 
317 	converted = latin2mic(src, dest, len, LC_KOI8_R, PG_KOI8R, noError);
318 
319 	PG_RETURN_INT32(converted);
320 }
321 
322 Datum
mic_to_koi8r(PG_FUNCTION_ARGS)323 mic_to_koi8r(PG_FUNCTION_ARGS)
324 {
325 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
326 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
327 	int			len = PG_GETARG_INT32(4);
328 	bool		noError = PG_GETARG_BOOL(5);
329 	int			converted;
330 
331 	CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_KOI8R);
332 
333 	converted = mic2latin(src, dest, len, LC_KOI8_R, PG_KOI8R, noError);
334 
335 	PG_RETURN_INT32(converted);
336 }
337 
338 Datum
iso_to_mic(PG_FUNCTION_ARGS)339 iso_to_mic(PG_FUNCTION_ARGS)
340 {
341 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
342 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
343 	int			len = PG_GETARG_INT32(4);
344 	bool		noError = PG_GETARG_BOOL(5);
345 	int			converted;
346 
347 	CHECK_ENCODING_CONVERSION_ARGS(PG_ISO_8859_5, PG_MULE_INTERNAL);
348 
349 	converted = latin2mic_with_table(src, dest, len, LC_KOI8_R, PG_ISO_8859_5, iso2koi, noError);
350 
351 	PG_RETURN_INT32(converted);
352 }
353 
354 Datum
mic_to_iso(PG_FUNCTION_ARGS)355 mic_to_iso(PG_FUNCTION_ARGS)
356 {
357 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
358 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
359 	int			len = PG_GETARG_INT32(4);
360 	bool		noError = PG_GETARG_BOOL(5);
361 	int			converted;
362 
363 	CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_ISO_8859_5);
364 
365 	converted = mic2latin_with_table(src, dest, len, LC_KOI8_R, PG_ISO_8859_5, koi2iso, noError);
366 
367 	PG_RETURN_INT32(converted);
368 }
369 
370 Datum
win1251_to_mic(PG_FUNCTION_ARGS)371 win1251_to_mic(PG_FUNCTION_ARGS)
372 {
373 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
374 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
375 	int			len = PG_GETARG_INT32(4);
376 	bool		noError = PG_GETARG_BOOL(5);
377 	int			converted;
378 
379 	CHECK_ENCODING_CONVERSION_ARGS(PG_WIN1251, PG_MULE_INTERNAL);
380 
381 	converted = latin2mic_with_table(src, dest, len, LC_KOI8_R, PG_WIN1251, win12512koi, noError);
382 
383 	PG_RETURN_INT32(converted);
384 }
385 
386 Datum
mic_to_win1251(PG_FUNCTION_ARGS)387 mic_to_win1251(PG_FUNCTION_ARGS)
388 {
389 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
390 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
391 	int			len = PG_GETARG_INT32(4);
392 	bool		noError = PG_GETARG_BOOL(5);
393 	int			converted;
394 
395 	CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_WIN1251);
396 
397 	converted = mic2latin_with_table(src, dest, len, LC_KOI8_R, PG_WIN1251, koi2win1251, noError);
398 
399 	PG_RETURN_INT32(converted);
400 }
401 
402 Datum
win866_to_mic(PG_FUNCTION_ARGS)403 win866_to_mic(PG_FUNCTION_ARGS)
404 {
405 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
406 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
407 	int			len = PG_GETARG_INT32(4);
408 	bool		noError = PG_GETARG_BOOL(5);
409 	int			converted;
410 
411 	CHECK_ENCODING_CONVERSION_ARGS(PG_WIN866, PG_MULE_INTERNAL);
412 
413 	converted = latin2mic_with_table(src, dest, len, LC_KOI8_R, PG_WIN866, win8662koi, noError);
414 
415 	PG_RETURN_INT32(converted);
416 }
417 
418 Datum
mic_to_win866(PG_FUNCTION_ARGS)419 mic_to_win866(PG_FUNCTION_ARGS)
420 {
421 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
422 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
423 	int			len = PG_GETARG_INT32(4);
424 	bool		noError = PG_GETARG_BOOL(5);
425 	int			converted;
426 
427 	CHECK_ENCODING_CONVERSION_ARGS(PG_MULE_INTERNAL, PG_WIN866);
428 
429 	converted = mic2latin_with_table(src, dest, len, LC_KOI8_R, PG_WIN866, koi2win866, noError);
430 
431 	PG_RETURN_INT32(converted);
432 }
433 
434 Datum
koi8r_to_win1251(PG_FUNCTION_ARGS)435 koi8r_to_win1251(PG_FUNCTION_ARGS)
436 {
437 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
438 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
439 	int			len = PG_GETARG_INT32(4);
440 	bool		noError = PG_GETARG_BOOL(5);
441 	int			converted;
442 
443 	CHECK_ENCODING_CONVERSION_ARGS(PG_KOI8R, PG_WIN1251);
444 
445 	converted = local2local(src, dest, len, PG_KOI8R, PG_WIN1251, koi2win1251, noError);
446 
447 	PG_RETURN_INT32(converted);
448 }
449 
450 Datum
win1251_to_koi8r(PG_FUNCTION_ARGS)451 win1251_to_koi8r(PG_FUNCTION_ARGS)
452 {
453 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
454 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
455 	int			len = PG_GETARG_INT32(4);
456 	bool		noError = PG_GETARG_BOOL(5);
457 	int			converted;
458 
459 	CHECK_ENCODING_CONVERSION_ARGS(PG_WIN1251, PG_KOI8R);
460 
461 	converted = local2local(src, dest, len, PG_WIN1251, PG_KOI8R, win12512koi, noError);
462 
463 	PG_RETURN_INT32(converted);
464 }
465 
466 Datum
koi8r_to_win866(PG_FUNCTION_ARGS)467 koi8r_to_win866(PG_FUNCTION_ARGS)
468 {
469 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
470 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
471 	int			len = PG_GETARG_INT32(4);
472 	bool		noError = PG_GETARG_BOOL(5);
473 	int			converted;
474 
475 	CHECK_ENCODING_CONVERSION_ARGS(PG_KOI8R, PG_WIN866);
476 
477 	converted = local2local(src, dest, len, PG_KOI8R, PG_WIN866, koi2win866, noError);
478 
479 	PG_RETURN_INT32(converted);
480 }
481 
482 Datum
win866_to_koi8r(PG_FUNCTION_ARGS)483 win866_to_koi8r(PG_FUNCTION_ARGS)
484 {
485 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
486 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
487 	int			len = PG_GETARG_INT32(4);
488 	bool		noError = PG_GETARG_BOOL(5);
489 	int			converted;
490 
491 	CHECK_ENCODING_CONVERSION_ARGS(PG_WIN866, PG_KOI8R);
492 
493 	converted = local2local(src, dest, len, PG_WIN866, PG_KOI8R, win8662koi, noError);
494 
495 	PG_RETURN_INT32(converted);
496 }
497 
498 Datum
win866_to_win1251(PG_FUNCTION_ARGS)499 win866_to_win1251(PG_FUNCTION_ARGS)
500 {
501 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
502 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
503 	int			len = PG_GETARG_INT32(4);
504 	bool		noError = PG_GETARG_BOOL(5);
505 	int			converted;
506 
507 	CHECK_ENCODING_CONVERSION_ARGS(PG_WIN866, PG_WIN1251);
508 
509 	converted = local2local(src, dest, len, PG_WIN866, PG_WIN1251, win8662win1251, noError);
510 
511 	PG_RETURN_INT32(converted);
512 }
513 
514 Datum
win1251_to_win866(PG_FUNCTION_ARGS)515 win1251_to_win866(PG_FUNCTION_ARGS)
516 {
517 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
518 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
519 	int			len = PG_GETARG_INT32(4);
520 	bool		noError = PG_GETARG_BOOL(5);
521 	int			converted;
522 
523 	CHECK_ENCODING_CONVERSION_ARGS(PG_WIN1251, PG_WIN866);
524 
525 	converted = local2local(src, dest, len, PG_WIN1251, PG_WIN866, win12512win866, noError);
526 
527 	PG_RETURN_INT32(converted);
528 }
529 
530 Datum
iso_to_koi8r(PG_FUNCTION_ARGS)531 iso_to_koi8r(PG_FUNCTION_ARGS)
532 {
533 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
534 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
535 	int			len = PG_GETARG_INT32(4);
536 	bool		noError = PG_GETARG_BOOL(5);
537 	int			converted;
538 
539 	CHECK_ENCODING_CONVERSION_ARGS(PG_ISO_8859_5, PG_KOI8R);
540 
541 	converted = local2local(src, dest, len, PG_ISO_8859_5, PG_KOI8R, iso2koi, noError);
542 
543 	PG_RETURN_INT32(converted);
544 }
545 
546 Datum
koi8r_to_iso(PG_FUNCTION_ARGS)547 koi8r_to_iso(PG_FUNCTION_ARGS)
548 {
549 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
550 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
551 	int			len = PG_GETARG_INT32(4);
552 	bool		noError = PG_GETARG_BOOL(5);
553 	int			converted;
554 
555 	CHECK_ENCODING_CONVERSION_ARGS(PG_KOI8R, PG_ISO_8859_5);
556 
557 	converted = local2local(src, dest, len, PG_KOI8R, PG_ISO_8859_5, koi2iso, noError);
558 
559 	PG_RETURN_INT32(converted);
560 }
561 
562 Datum
iso_to_win1251(PG_FUNCTION_ARGS)563 iso_to_win1251(PG_FUNCTION_ARGS)
564 {
565 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
566 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
567 	int			len = PG_GETARG_INT32(4);
568 	bool		noError = PG_GETARG_BOOL(5);
569 	int			converted;
570 
571 	CHECK_ENCODING_CONVERSION_ARGS(PG_ISO_8859_5, PG_WIN1251);
572 
573 	converted = local2local(src, dest, len, PG_ISO_8859_5, PG_WIN1251, iso2win1251, noError);
574 
575 	PG_RETURN_INT32(converted);
576 }
577 
578 Datum
win1251_to_iso(PG_FUNCTION_ARGS)579 win1251_to_iso(PG_FUNCTION_ARGS)
580 {
581 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
582 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
583 	int			len = PG_GETARG_INT32(4);
584 	bool		noError = PG_GETARG_BOOL(5);
585 	int			converted;
586 
587 	CHECK_ENCODING_CONVERSION_ARGS(PG_WIN1251, PG_ISO_8859_5);
588 
589 	converted = local2local(src, dest, len, PG_WIN1251, PG_ISO_8859_5, win12512iso, noError);
590 
591 	PG_RETURN_INT32(converted);
592 }
593 
594 Datum
iso_to_win866(PG_FUNCTION_ARGS)595 iso_to_win866(PG_FUNCTION_ARGS)
596 {
597 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
598 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
599 	int			len = PG_GETARG_INT32(4);
600 	bool		noError = PG_GETARG_BOOL(5);
601 	int			converted;
602 
603 	CHECK_ENCODING_CONVERSION_ARGS(PG_ISO_8859_5, PG_WIN866);
604 
605 	converted = local2local(src, dest, len, PG_ISO_8859_5, PG_WIN866, iso2win866, noError);
606 
607 	PG_RETURN_INT32(converted);
608 }
609 
610 Datum
win866_to_iso(PG_FUNCTION_ARGS)611 win866_to_iso(PG_FUNCTION_ARGS)
612 {
613 	unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
614 	unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
615 	int			len = PG_GETARG_INT32(4);
616 	bool		noError = PG_GETARG_BOOL(5);
617 	int			converted;
618 
619 	CHECK_ENCODING_CONVERSION_ARGS(PG_WIN866, PG_ISO_8859_5);
620 
621 	converted = local2local(src, dest, len, PG_WIN866, PG_ISO_8859_5, win8662iso, noError);
622 
623 	PG_RETURN_INT32(converted);
624 }
625