1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
29 * minimally provides { utf*<=>bin ascii<=>ebcdic* }
36 #define _ICONV_LIST_PRIVATE_
46 #define _ast_iconv_t iconv_t
47 #define _ast_iconv_f iconv_f
48 #define _ast_iconv_list_t iconv_list_t
49 #define _ast_iconv_open iconv_open
50 #define _ast_iconv iconv
51 #define _ast_iconv_close iconv_close
52 #define _ast_iconv_list iconv_list
53 #define _ast_iconv_move iconv_move
54 #define _ast_iconv_name iconv_name
55 #define _ast_iconv_write iconv_write
66 #define RETURN(e,n,fn) \
67 if (*fn && !e) e = E2BIG; \
68 if (e) { errno = e; return (size_t)(-1); } \
74 const unsigned char* map
;
88 static Conv_t
* freelist
[4];
91 static const char name_local
[] = "local";
92 static const char name_native
[] = "native";
94 static const _ast_iconv_list_t codes
[] =
99 "multibyte 8-bit unicode",
108 "multibyte 7-bit unicode",
134 "ucs?(-)?(2)?(be)|utf-16?(be)",
143 "ucs?(-)?(2)le|utf-16le",
144 "little endian unicode runes",
155 #include <ast_windows.h>
158 #define CP_UCS2 0x0000
161 static char _win_maps
[] = "/reg/local_machine/SOFTWARE/Classes/MIME/Database/Charset";
164 * return the codeset index given its name or alias
165 * the map is in the what? oh, the registry
169 _win_codeset(const char* name
)
179 error(DEBUG_TRACE
, "AHA#%d _win_codeset name=%s", __LINE__
, name
);
181 if (name
== name_native
)
183 if (!strcasecmp(name
, "utf") || !strcasecmp(name
, "utf8") || !strcasecmp(name
, "utf-8"))
185 if (!strcasecmp(name
, "ucs") || !strcasecmp(name
, "ucs2") || !strcasecmp(name
, "ucs-2"))
187 if (name
[0] == '0' && name
[1] == 'x' && (n
= strtol(name
, &e
, 0)) > 0 && !*e
)
191 sfsprintf(tmp
, sizeof(tmp
), "%s/%s", _win_maps
, name
);
192 if (!(sp
= sfopen(0, tmp
, "r")))
195 if ((s
[0] == 'c' || s
[0] == 'C') && (s
[1] == 'p' || s
[1] == 'P'))
199 sfsprintf(tmp
, sizeof(tmp
), "%s/windows-%s", _win_maps
, s
);
200 if (!(sp
= sfopen(0, tmp
, "r")))
205 if (!(s
= sfgetr(sp
, '\n', 0)))
210 if (!strncasecmp(s
, "AliasForCharSet=", 16))
212 n
= sfvalue(sp
) - 17;
214 if (n
>= sizeof(aka
))
219 name
= (const char*)aka
;
222 if (!strncasecmp(s
, "CodePage=", 9))
235 * get and check the codeset indices
239 _win_iconv_open(register Conv_t
* cc
, const char* t
, const char* f
)
242 error(DEBUG_TRACE
, "AHA#%d _win_iconv_open f=%s t=%s\n", __LINE__
, f
, t
);
244 if ((cc
->from
.index
= _win_codeset(f
)) < 0)
245 return (_ast_iconv_t
)(-1);
246 if ((cc
->to
.index
= _win_codeset(t
)) < 0)
247 return (_ast_iconv_t
)(-1);
249 error(DEBUG_TRACE
, "AHA#%d _win_iconv_open f=0x%04x t=0x%04x\n", __LINE__
, cc
->from
.index
, cc
->to
.index
);
251 return (_ast_iconv_t
)cc
;
255 * even though the indices already check out
256 * they could still be rejected
260 _win_iconv(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
262 Conv_t
* cc
= (Conv_t
*)cd
;
272 error(DEBUG_TRACE
, "AHA#%d _win_iconv from=0x%04x to=0x%04x\n", __LINE__
, cc
->from
.index
, cc
->to
.index
);
274 if (cc
->from
.index
== cc
->to
.index
)
280 fz
= tz
= (*fn
< *tn
) ? *fn
: *tn
;
281 memcpy(*tb
, *fb
, fz
);
292 if (cc
->to
.index
== CP_UCS2
)
294 if ((tz
= MultiByteToWideChar(cc
->from
.index
, 0, (LPCSTR
)*fb
, (int)*fn
, (LPWSTR
)*tb
, *tn
)) && tz
<= *tn
)
303 * binary search on input size to make it fit
311 while (!(tz
= MultiByteToWideChar(cc
->from
.index
, 0, (LPCSTR
)*fb
, (int)fz
, (LPWSTR
)*tb
, 0)))
335 if (cc
->from
.index
== CP_UCS2
)
337 un
= *fn
/ sizeof(WCHAR
);
340 else if (!(un
= MultiByteToWideChar(cc
->from
.index
, 0, (LPCSTR
)*fb
, (int)*fn
, (LPWSTR
)*tb
, 0)))
342 else if (!(ub
= (LPWSTR
)malloc(un
* sizeof(WCHAR
))))
344 else if (!(un
= MultiByteToWideChar(cc
->from
.index
, 0, (LPCSTR
)*fb
, (int)*fn
, (LPWSTR
)ub
, un
)))
351 if (tz
= WideCharToMultiByte(cc
->to
.index
, 0, (LPCWSTR
)ub
, un
, *tb
, *tn
, 0, 0))
357 * binary search on input size to make it fit
365 while (!(fz
= MultiByteToWideChar(cc
->from
.index
, 0, (LPCSTR
)*fb
, (int)bz
, (LPWSTR
)ub
, un
)))
368 if (!(tz
= WideCharToMultiByte(cc
->to
.index
, 0, (LPCWSTR
)ub
, fz
, *tb
, 0, 0, 0)))
386 if (!(tz
= WideCharToMultiByte(cc
->to
.index
, 0, (LPCWSTR
)ub
, fz
, *tb
, tz
, 0, 0)))
389 error(DEBUG_TRACE
, "AHA#%d _win_iconv *fn=%u fz=%u[%u] *tn=%u tz=%u\n", __LINE__
, *fn
, fz
, fz
* sizeof(WCHAR
), *tn
, tz
);
395 if (ub
!= (LPWSTR
)*fb
)
405 if (ub
&& ub
!= (LPWSTR
)*fb
)
414 * return canonical character code set name for m
415 * if b!=0 then canonical name placed in b of size n
416 * <ccode.h> index returned
420 _ast_iconv_name(register const char* m
, register char* b
, size_t n
)
422 register const _ast_iconv_list_t
* cp
;
423 const _ast_iconv_list_t
* bp
;
445 if (error_info
.trace
< DEBUG_TRACE
) sfprintf(sfstderr
, "%s: debug-%d: AHA%d _ast_iconv_name m=\"%s\"\n", error_info
.id
, error_info
.trace
, __LINE__
, m
);
450 if (error_info
.trace
< DEBUG_TRACE
) sfprintf(sfstderr
, "%s: debug-%d: AHA%d _ast_iconv_name n=%d bp=%p cp=%p ccode=%d name=\"%s\"\n", error_info
.id
, error_info
.trace
, __LINE__
, n
, bp
, cp
, cp
->ccode
, cp
->name
);
452 if (strgrpmatch(m
, cp
->match
, sub
, elementsof(sub
) / 2, STR_MAXIMAL
|STR_LEFT
|STR_ICASE
))
454 if (!(c
= m
[sub
[1]]))
459 if (sub
[1] > n
&& !isalpha(c
))
470 else if (!(cp
= (const _ast_iconv_list_t
*)ccmaplist((_ast_iconv_list_t
*)cp
)))
479 for (m
+= sub
[1]; *m
&& !isalnum(*m
); m
++);
485 b
+= sfsprintf(b
, e
- b
, cp
->canon
, m
);
487 else if (cp
->ccode
== CC_NATIVE
)
489 if ((locales
[AST_LC_CTYPE
]->flags
& LC_default
) || !locales
[AST_LC_CTYPE
]->charset
|| !(m
= locales
[AST_LC_CTYPE
]->charset
->code
) || streq(m
, "iso8859-1"))
493 m
= (const char*)"EBCDIC";
496 m
= (const char*)"EBCDIC-I";
499 m
= (const char*)"EBCDIC-O";
502 m
= (const char*)"ISO-8859-1";
505 b
+= sfsprintf(b
, e
- b
, "%s", m
);
509 if (error_info
.trace
< DEBUG_TRACE
) sfprintf(sfstderr
, "%s: debug-%d: AHA%d _ast_iconv_name ccode=%d canon=\"%s\"\n", error_info
.id
, error_info
.trace
, __LINE__
, cp
->ccode
, o
);
513 while (b
< e
&& (c
= *m
++))
521 if (error_info
.trace
< DEBUG_TRACE
) sfprintf(sfstderr
, "%s: debug-%d: AHA%d _ast_iconv_name ccode=%d canon=\"%s\"\n", error_info
.id
, error_info
.trace
, __LINE__
, CC_ICONV
, o
);
527 * convert utf-8 to bin
531 utf2bin(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
533 register unsigned char* f
;
534 register unsigned char* fe
;
535 register unsigned char* t
;
536 register unsigned char* te
;
537 register unsigned char* p
;
544 f
= (unsigned char*)(*fb
);
546 t
= (unsigned char*)(*tb
);
548 while (t
< te
&& f
< fe
)
562 w
= (c
& 0x0F) << 12;
576 w
|= (c
& 0x3F) << 6;
593 *fn
-= (char*)f
- (*fb
);
595 *tn
-= (n
= (char*)t
- (*tb
));
601 * convert bin to utf-8
605 bin2utf(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
607 register unsigned char* f
;
608 register unsigned char* fe
;
609 register unsigned char* t
;
610 register unsigned char* te
;
617 f
= (unsigned char*)(*fb
);
619 t
= (unsigned char*)(*tb
);
621 while (f
< fe
&& t
< te
)
628 else if ((c
= (*_ast_info
.mb_towc
)(&w
, (char*)f
, fe
- f
)) < 0)
646 *t
++ = 0xC0 + (w
>> 6);
648 else if (!(w
& ~0xffff))
655 *t
++ = 0xE0 + (w
>> 12);
656 *t
++ = 0x80 + ((w
>> 6 ) & 0x3F);
663 *t
++ = 0x80 + (w
& 0x3F);
667 *fn
-= (n
= (char*)f
- (*fb
));
669 *tn
-= (char*)t
- (*tb
);
674 static const unsigned char ume_D
[] =
675 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?!\"#$%&*;<=>@[]^_`{|} \t\n";
677 static const unsigned char ume_M
[] =
678 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
680 static unsigned char ume_d
[UCHAR_MAX
+1];
682 static unsigned char ume_m
[UCHAR_MAX
+1];
685 #define UMEINIT() (ume_d[ume_D[0]]?0:umeinit())
688 * initialize the ume tables
694 register const unsigned char* s
;
698 if (!ume_d
[ume_D
[0]])
703 memset(ume_m
, NOE
, sizeof(ume_m
));
704 for (i
= 0; c
= ume_M
[i
]; i
++)
711 * convert utf-7 to bin
715 ume2bin(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
717 register unsigned char* f
;
718 register unsigned char* fe
;
719 register unsigned char* t
;
720 register unsigned char* te
;
721 register unsigned char* p
;
730 f
= (unsigned char*)(*fb
);
732 t
= (unsigned char*)(*tb
);
735 while (f
< fe
&& t
< te
)
741 if (c
== '-' && s
> 1)
743 else if ((w
= ume_m
[c
]) == NOE
)
748 else if (f
>= (fe
- 2))
757 w
= (w
<< 6) | ume_m
[*f
++];
758 w
= (w
<< 6) | ume_m
[*f
++];
761 else if (t
>= (te
- 1))
769 *t
++ = (w
>> 8) & 0xFF;
779 *fn
-= (char*)f
- (*fb
);
781 *tn
-= (n
= (char*)t
- (*tb
));
787 * convert bin to utf-7
791 bin2ume(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
793 register unsigned char* f
;
794 register unsigned char* fe
;
795 register unsigned char* t
;
796 register unsigned char* te
;
805 f
= (unsigned char*)(*fb
);
807 t
= (unsigned char*)(*tb
);
810 while (f
< fe
&& t
< (te
- s
))
817 else if ((c
= (*_ast_info
.mb_towc
)(&w
, (char*)f
, fe
- f
)) < 0)
824 if (!(w
& ~0x7F) && ume_d
[w
])
833 else if (t
>= (te
- (4 + s
)))
845 *t
++ = ume_M
[(w
>> 12) & 0x3F];
846 *t
++ = ume_M
[(w
>> 6) & 0x3F];
847 *t
++ = ume_M
[w
& 0x3F];
853 *fn
-= (n
= (char*)f
- (*fb
));
855 *tn
-= (char*)t
- (*tb
);
861 * convert ucs-2 to bin with no byte swap
865 ucs2bin(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
867 register unsigned char* f
;
868 register unsigned char* fe
;
869 register unsigned char* t
;
870 register unsigned char* te
;
876 f
= (unsigned char*)(*fb
);
878 t
= (unsigned char*)(*tb
);
880 while (f
< (fe
- 1) && t
< te
)
886 else if (t
>= (te
- 1))
894 *t
++ = (w
>> 8) & 0xFF;
898 *fn
-= (char*)f
- (*fb
);
900 *tn
-= (n
= (char*)t
- (*tb
));
906 * convert bin to ucs-2 with no byte swap
910 bin2ucs(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
912 register unsigned char* f
;
913 register unsigned char* fe
;
914 register unsigned char* t
;
915 register unsigned char* te
;
922 f
= (unsigned char*)(*fb
);
924 t
= (unsigned char*)(*tb
);
926 while (f
< fe
&& t
< (te
- 1))
933 if ((c
= (*_ast_info
.mb_towc
)(&w
, (char*)f
, fe
- f
)) < 0)
940 *t
++ = (w
>> 8) & 0xFF;
944 *fn
-= (n
= (char*)f
- (*fb
));
946 *tn
-= (char*)t
- (*tb
);
952 * convert ucs-2 to bin with byte swap
956 scu2bin(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
958 register unsigned char* f
;
959 register unsigned char* fe
;
960 register unsigned char* t
;
961 register unsigned char* te
;
967 f
= (unsigned char*)(*fb
);
969 t
= (unsigned char*)(*tb
);
971 while (f
< (fe
- 1) && t
< te
)
977 else if (t
>= (te
- 1))
985 *t
++ = (w
>> 8) & 0xFF;
989 *fn
-= (char*)f
- (*fb
);
991 *tn
-= (n
= (char*)t
- (*tb
));
997 * convert bin to ucs-2 with byte swap
1001 bin2scu(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
1003 register unsigned char* f
;
1004 register unsigned char* fe
;
1005 register unsigned char* t
;
1006 register unsigned char* te
;
1013 f
= (unsigned char*)(*fb
);
1015 t
= (unsigned char*)(*tb
);
1017 while (f
< fe
&& t
< (te
- 1))
1024 else if ((c
= (*_ast_info
.mb_towc
)(&w
, (char*)f
, fe
- f
)) < 0)
1032 *t
++ = (w
>> 8) & 0xFF;
1035 *fn
-= (n
= (char*)f
- (*fb
));
1037 *tn
-= (char*)t
- (*tb
);
1043 * open a character code conversion map from f to t
1047 _ast_iconv_open(const char* t
, const char* f
)
1049 register Conv_t
* cc
;
1058 error(DEBUG_TRACE
, "AHA#%d _ast_iconv_open f=%s t=%s\n", __LINE__
, f
, t
);
1060 if (!t
|| !*t
|| *t
== '-' && !*(t
+ 1) || !strcasecmp(t
, name_local
) || !strcasecmp(t
, name_native
))
1062 if (!f
|| !*f
|| *f
== '-' && !*(f
+ 1) || !strcasecmp(t
, name_local
) || !strcasecmp(f
, name_native
))
1066 * the ast identify is always (iconv_t)(0)
1070 return (iconv_t
)(0);
1071 fc
= _ast_iconv_name(f
, fr
, sizeof(fr
));
1072 tc
= _ast_iconv_name(t
, to
, sizeof(to
));
1074 error(DEBUG_TRACE
, "AHA#%d _ast_iconv_open f=%s:%s:%d t=%s:%s:%d\n", __LINE__
, f
, fr
, fc
, t
, to
, tc
);
1076 if (fc
!= CC_ICONV
&& fc
== tc
|| streq(fr
, to
))
1077 return (iconv_t
)(0);
1080 * first check the free list
1083 for (i
= 0; i
< elementsof(freelist
); i
++)
1084 if ((cc
= freelist
[i
]) && streq(to
, cc
->to
.name
) && streq(fr
, cc
->from
.name
))
1089 * reset the shift state if any
1092 if (cc
->cvt
!= (iconv_t
)(-1))
1093 iconv(cc
->cvt
, NiL
, NiL
, NiL
, NiL
);
1099 * allocate a new one
1102 if (!(cc
= newof(0, Conv_t
, 1, strlen(to
) + strlen(fr
) + 2)))
1103 return (iconv_t
)(-1);
1104 cc
->to
.name
= (char*)(cc
+ 1);
1105 cc
->from
.name
= strcopy(cc
->to
.name
, to
) + 1;
1106 strcpy(cc
->from
.name
, fr
);
1107 cc
->cvt
= (iconv_t
)(-1);
1110 * 8 bit maps are the easiest
1113 if (fc
>= 0 && tc
>= 0)
1114 cc
->from
.map
= ccmap(fc
, tc
);
1116 else if ((cc
->cvt
= iconv_open(to
, fr
)) != (iconv_t
)(-1))
1117 cc
->from
.fun
= (_ast_iconv_f
)iconv
;
1120 else if ((cc
->cvt
= _win_iconv_open(cc
, to
, fr
)) != (_ast_iconv_t
)(-1))
1121 cc
->from
.fun
= (_ast_iconv_f
)_win_iconv
;
1128 cc
->from
.fun
= utf2bin
;
1131 cc
->from
.fun
= ume2bin
;
1134 cc
->from
.fun
= ucs2bin
;
1137 cc
->from
.fun
= scu2bin
;
1144 cc
->from
.map
= ccmap(fc
, CC_ASCII
);
1150 cc
->to
.fun
= bin2utf
;
1153 cc
->to
.fun
= bin2ume
;
1156 cc
->to
.fun
= bin2ucs
;
1159 cc
->to
.fun
= bin2scu
;
1166 cc
->to
.map
= ccmap(CC_ASCII
, tc
);
1172 return (iconv_t
)(-1);
1176 * close a character code conversion map
1180 _ast_iconv_close(_ast_iconv_t cd
)
1187 if (cd
== (_ast_iconv_t
)(-1))
1189 if (!(cc
= (Conv_t
*)cd
))
1193 * add to the free list
1199 if (++ i
>= elementsof(freelist
))
1205 if (++ i
>= elementsof(freelist
))
1212 if (oc
= freelist
[i
])
1215 if (oc
->cvt
!= (iconv_t
)(-1))
1216 r
= iconv_close(oc
->cvt
);
1224 freelist
[freeindex
= i
] = cc
;
1229 * copy *fb size *fn to *tb size *tn
1230 * fb,fn tb,tn updated on return
1234 _ast_iconv(_ast_iconv_t cd
, char** fb
, size_t* fn
, char** tb
, size_t* tn
)
1236 Conv_t
* cc
= (Conv_t
*)cd
;
1237 register unsigned char* f
;
1238 register unsigned char* t
;
1239 register unsigned char* e
;
1240 register const unsigned char* m
;
1249 /* TODO: reset to the initial state */
1252 /* TODO: write the initial state shift sequence */
1262 if (!cc
->buf
&& !(cc
->buf
= oldof(0, char, cc
->size
= SF_BUFSIZE
, 0)))
1271 if ((*cc
->from
.fun
)(cc
->cvt
, &tfb
, &tfn
, &b
, &i
) == (size_t)(-1))
1275 n
= (*cc
->to
.fun
)(cc
->cvt
, &tfb
, &tfn
, tb
, tn
);
1281 if ((*cc
->from
.fun
)(cc
->cvt
, fb
, fn
, tb
, tn
) == (size_t)(-1))
1286 e
= (unsigned char*)(*tb
);
1287 for (t
= e
- n
; t
< e
; t
++)
1292 else if (cc
->to
.fun
)
1294 if (!(m
= cc
->from
.map
))
1295 return (*cc
->to
.fun
)(cc
->cvt
, fb
, fn
, tb
, tn
);
1296 if (!cc
->buf
&& !(cc
->buf
= oldof(0, char, cc
->size
= SF_BUFSIZE
, 0)))
1301 if ((n
= *fn
) > cc
->size
)
1303 f
= (unsigned char*)(*fb
);
1305 t
= (unsigned char*)(b
= cc
->buf
);
1308 n
= (*cc
->to
.fun
)(cc
->cvt
, &b
, fn
, tb
, tn
);
1315 if (cc
&& (m
= cc
->from
.map
))
1317 f
= (unsigned char*)(*fb
);
1319 t
= (unsigned char*)(*tb
);
1324 memcpy(*tb
, *fb
, n
);
1333 * write *fb size *fn to op
1334 * fb,fn updated on return
1335 * total bytes written to op returned
1339 _ast_iconv_write(_ast_iconv_t cd
, Sfio_t
* op
, char** fb
, size_t* fn
, size_t* e
)
1350 if (!(tb
= (char*)sfreserve(op
, -(tn
+ 1), SF_WRITE
|SF_LOCKR
)))
1355 error(DEBUG_TRACE
, "AHA#%d iconv_write ts=%p tn=%d", __LINE__
, ts
, tn
);
1358 while (_ast_iconv(cd
, fb
, fn
, &ts
, &tn
) == (size_t)(-1))
1363 error(DEBUG_TRACE
, "AHA#%d iconv_write %d => %d `%-.*s'", __LINE__
, *fn
, tn
, *fn
, *fb
);
1364 _r
= _ast_iconv(cd
, fb
, fn
, &ts
, &tn
);
1365 error(DEBUG_TRACE
, "AHA#%d iconv_write %d => %d [%d]", __LINE__
, *fn
, tn
, _r
);
1366 if (_r
!= (size_t)(-1))
1380 error(DEBUG_TRACE
, "AHA#%d iconv_write %d", __LINE__
, ts
- tb
);
1383 sfwrite(op
, tb
, ts
- tb
);
1390 * move n bytes from ip to op
1394 _ast_iconv_move(_ast_iconv_t cd
, Sfio_t
* ip
, Sfio_t
* op
, size_t n
, size_t* e
)
1410 if (fn
!= SF_UNBOUND
)
1411 fn
= -((ssize_t
)(fn
& (((size_t)(~0))>>1)));
1412 if (!(fb
= (char*)sfreserve(ip
, fn
, locked
= SF_LOCKR
)) &&
1413 !(fb
= (char*)sfreserve(ip
, fn
, locked
= 0)))
1416 fn
= fo
= sfvalue(ip
);
1417 if (!(tb
= (char*)sfreserve(op
, SF_UNBOUND
, SF_WRITE
|SF_LOCKR
)))
1424 while (_ast_iconv(cd
, &fs
, &fn
, &ts
, &tn
) != (size_t)(-1) && fn
> 0)
1436 sfwrite(op
, tb
, ts
- tb
);
1439 sfread(ip
, fb
, fs
- fb
);
1441 for (i
= fn
; --i
>= (fs
- fb
);)
1442 sfungetc(ip
, fb
[i
]);
1443 if (n
!= SF_UNBOUND
)
1456 * iconv_list_t iterator
1457 * call with arg 0 to start
1458 * prev return value is current arg
1462 _ast_iconv_list(_ast_iconv_list_t
* cp
)
1469 if (!(cp
= newof(0, _ast_iconv_list_t
, 1, 0)))
1470 return ccmaplist(NiL
);
1471 if (!(cp
->data
= opendir(_win_maps
)))
1474 return ccmaplist(NiL
);
1479 if (ent
= readdir((DIR*)cp
->data
))
1481 cp
->name
= cp
->match
= cp
->desc
= (const char*)ent
->d_name
;
1484 closedir((DIR*)cp
->data
);
1486 return ccmaplist(NiL
);
1490 return ccmaplist(NiL
);
1493 return (cp
= ccmaplist(cp
)) ? cp
: (_ast_iconv_list_t
*)codes
;
1494 return (++cp
)->name
? cp
: (_ast_iconv_list_t
*)0;