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