Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/std/iconv.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*/
25
26
static const char usage[] =
27
"[-?\n@(#)$Id: iconv (AT&T Research) 2011-01-11 $\n]"
28
USAGE_LICENSE
29
"[+NAME?iconv - codeset conversion]"
30
"[+DESCRIPTION?\biconv\b converts the encoding of characters in the \afile\a"
31
" operands from one codeset to another and writes the results to"
32
" the standard output. If \afile\a is \b-\b or omitted then the"
33
" standard input is read.]"
34
"[+?Character encodings in either codeset may include single-byte values"
35
" (for example, for the ISO 8859-1:1987 standard characters) or"
36
" multi-byte values (for example, for certain characters in the"
37
" ISO 6937:1983 standard). Invalid characters in the input stream"
38
" (either those that are not valid members of the input codeset or"
39
" those that have no corresponding value in the output codeset) are"
40
" output as the underscore character (\b_\b) in the output codeset.]"
41
"[+?The \bnative\b codeset is determined by the \bLANG\b, \bLC_ALL\b and"
42
" \bLC_CTYPE\b environment variables. The supported codesets"
43
" are matched by these left-anchored case-insensitive \bksh\b(1)"
44
" patterns:]{\fcodesets\f}"
45
"[+?Conversion between certain codesets may not be supported. Also, since the"
46
" standard(s) provide no support for listing the known codesets, the"
47
" above list may be incomplete.]"
48
49
"[a:all?List all conversion errors. By default (and \b--omit\b is not "
50
"specified) \biconv\b stops after the first error.]"
51
"[c:omit?Omit invalid input characters from the output. Invalid input "
52
"characters still affect the exit status.]"
53
"[e:errors?Do not ignore conversion errors.]"
54
"[f:from?The input codeset is set to \acodeset\a.]:[codeset:=native]"
55
"[i:ignore?Ignore conversion errors.]"
56
"[l:list?List all known codesets on the standard output.]"
57
"[s:silent?Suppress invalid character diagnostics. Invalid input "
58
"characters still affect the exit status. If \b--all\b is also specified "
59
"then non-zero invalid character counts are listed.]"
60
"[t:to?The output codeset is set to \acodeset\a.]:[codeset:=native]"
61
62
"\n"
63
"\n[ pid ... ]\n"
64
"\n"
65
66
"[+SEE ALSO?\bdd\b(1), \biconv\b(3), \bsetlocale\b(3)]"
67
;
68
69
#include <ast.h>
70
#include <error.h>
71
#include <iconv.h>
72
73
/*
74
* optget() info discipline function
75
*/
76
77
static int
78
optinfo(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
79
{
80
register iconv_list_t* ic;
81
register const char* p;
82
register int c;
83
84
if (streq(s, "codesets"))
85
for (ic = iconv_list(NiL); ic; ic = iconv_list(ic))
86
{
87
sfputc(sp, '[');
88
sfputc(sp, '+');
89
sfputc(sp, '\b');
90
p = ic->match;
91
if (*p == '(')
92
p++;
93
while (c = *p++)
94
{
95
if (c == ')' && !*p)
96
break;
97
if (c == '?' || c == ']')
98
sfputc(sp, c);
99
sfputc(sp, c);
100
}
101
sfputc(sp, '?');
102
p = ic->desc;
103
while (c = *p++)
104
{
105
if (c == ']')
106
sfputc(sp, c);
107
sfputc(sp, c);
108
}
109
sfputc(sp, ']');
110
}
111
return 0;
112
}
113
114
static int
115
listall(void)
116
{
117
118
register iconv_list_t* ic;
119
register const char* p;
120
121
sfprintf(sfstdout, "Patterns:\n\n");
122
for (ic = iconv_list(NiL); ic; ic = iconv_list(ic))
123
sfprintf(sfstdout, " %s -- %s\n", ic->match, ic->desc);
124
p = "/usr/bin/iconv";
125
if (!access(p, X_OK) || !access(p += 4, X_OK))
126
{
127
sfprintf(sfstdout, "\n");
128
execl(p, "iconv", "-l", 0);
129
}
130
return 0;
131
}
132
133
int
134
main(int argc, register char** argv)
135
{
136
char* file;
137
char* from;
138
char* to;
139
iconv_t cvt;
140
int all;
141
int fail;
142
int ignore;
143
int list;
144
Sfio_t* ip;
145
Optdisc_t od;
146
Iconv_disc_t id;
147
148
NoP(argc);
149
error_info.id = "iconv";
150
from = to = "native";
151
all = ignore = list = 0;
152
setlocale(LC_ALL, "");
153
154
/*
155
* set up the disciplines
156
*/
157
158
optinit(&od, optinfo);
159
iconv_init(&id, errorf);
160
id.flags |= ICONV_FATAL;
161
162
/*
163
* grab the options
164
*/
165
166
for (;;)
167
{
168
switch (optget(argv, usage))
169
{
170
case 'a':
171
all = 1;
172
id.flags &= ~ICONV_FATAL;
173
continue;
174
case 'c':
175
id.flags |= ICONV_OMIT;
176
id.flags &= ~ICONV_FATAL;
177
continue;
178
case 'e':
179
ignore = 0;
180
continue;
181
case 'f':
182
from = opt_info.arg;
183
continue;
184
case 'i':
185
ignore = 1;
186
continue;
187
case 'l':
188
list = 1;
189
continue;
190
case 's':
191
id.errorf = 0;
192
continue;
193
case 't':
194
to = opt_info.arg;
195
continue;
196
case '?':
197
error(ERROR_USAGE|4, "%s", opt_info.arg);
198
break;
199
case ':':
200
error(2, "%s", opt_info.arg);
201
break;
202
}
203
break;
204
}
205
argv += opt_info.index;
206
if (error_info.errors)
207
error(ERROR_USAGE|4, "%s", optusage(NiL));
208
if (list)
209
return listall();
210
if ((cvt = iconv_open(to, from)) == (iconv_t)(-1))
211
{
212
if ((cvt = iconv_open(to, "utf-8")) == (iconv_t)(-1))
213
error(3, "%s: unknown destination codeset", to);
214
iconv_close(cvt);
215
if ((cvt = iconv_open("utf-8", from)) == (iconv_t)(-1))
216
error(3, "%s: unknown source codeset", from);
217
iconv_close(cvt);
218
error(3, "cannot convert from %s to %s", from, to);
219
}
220
fail = 0;
221
if (file = *argv)
222
argv++;
223
do
224
{
225
if (!file || streq(file, "-"))
226
{
227
file = "/dev/stdin";
228
ip = sfstdin;
229
}
230
else if (!(ip = sfopen(NiL, file, "r")))
231
{
232
error(ERROR_SYSTEM|2, "%s: cannot open", file);
233
continue;
234
}
235
id.errors = 0;
236
iconv_move(cvt, ip, sfstdout, SF_UNBOUND, &id);
237
if (!id.errors && (!sfeof(ip) || sferror(ip)))
238
error(ERROR_SYSTEM|2, "%s: conversion read error", file);
239
if (id.errors)
240
{
241
if (ignore || !id.errors)
242
fail = 1;
243
else if (!id.errorf && all)
244
{
245
if (id.errors == 1)
246
error(2, "%s: %d character conversion error", file, id.errors);
247
else if (id.errors)
248
error(2, "%s: %d character conversion errors", file, id.errors);
249
}
250
}
251
if (ip != sfstdin)
252
sfclose(ip);
253
} while (file = *argv++);
254
if (sfsync(sfstdout))
255
error(ERROR_SYSTEM|3, "conversion write error");
256
return error_info.errors != 0 || fail;
257
}
258
259