1 /* This file is part of GNU Dico
2 Copyright (C) 2012-2020 Sergey Poznyakoff
3
4 GNU Dico is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Dico is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Dico. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <dico.h>
22
23 typedef int (*opfn) (int argc, char **argv);
24
25 struct optab {
26 char *name;
27 opfn fun;
28 };
29
30 static unsigned *
strtowc(const char * str)31 strtowc(const char *str)
32 {
33 unsigned *buf;
34 if (utf8_mbstr_to_wc(str, &buf, NULL)) {
35 dico_log(L_ERR, errno, "cannot convert \"%s\"", str);
36 abort();
37 }
38 return buf;
39 }
40
41
42 static int
help(int argc,char ** argv)43 help(int argc, char **argv)
44 {
45 printf("No more help, sorry");
46 return 0;
47 }
48
49 static int
op_strlen(int argc,char ** argv)50 op_strlen(int argc, char **argv)
51 {
52 char *opname = *argv++;
53 argc--;
54 if (argc != 1) {
55 dico_log(L_ERR, 0, "%s requires one argument", opname);
56 return 1;
57 }
58 printf("%lu\n", (unsigned long) utf8_strlen(argv[0]));
59 return 0;
60 }
61
62 static int
op_strcasecmp(int argc,char ** argv)63 op_strcasecmp(int argc, char **argv)
64 {
65 char *opname = *argv++;
66 argc--;
67 if (argc != 2) {
68 dico_log(L_ERR, 0, "%s requires two arguments", opname);
69 return 1;
70 }
71 printf("%d\n", utf8_strcasecmp(argv[0], argv[1]));
72 return 0;
73 }
74
75 static int
op_strncasecmp(int argc,char ** argv)76 op_strncasecmp(int argc, char **argv)
77 {
78 char *opname = *argv++;
79 argc--;
80 if (argc != 3) {
81 dico_log(L_ERR, 0, "%s requires three arguments", opname);
82 return 1;
83 }
84 printf("%d\n", utf8_strncasecmp(argv[0], argv[1], atoi(argv[2])));
85 return 0;
86 }
87
88 static int
op_wc_strcmp(int argc,char ** argv)89 op_wc_strcmp(int argc, char **argv)
90 {
91 unsigned *wa, *wb;
92 char *opname = *argv++;
93 argc--;
94 if (argc != 2) {
95 dico_log(L_ERR, 0, "%s requires two arguments", opname);
96 return 1;
97 }
98
99 wa = strtowc(argv[0]);
100 wb = strtowc(argv[1]);
101
102 printf("%d\n", utf8_wc_strcmp(wa, wb));
103 return 0;
104 }
105
106 static int
op_wc_strncmp(int argc,char ** argv)107 op_wc_strncmp(int argc, char **argv)
108 {
109 unsigned *wa, *wb;
110 char *opname = *argv++;
111 argc--;
112 if (argc != 3) {
113 dico_log(L_ERR, 0, "%s requires three arguments", opname);
114 return 1;
115 }
116
117 wa = strtowc(argv[0]);
118 wb = strtowc(argv[1]);
119
120 printf("%d\n", utf8_wc_strncmp(wa, wb, atoi(argv[2])));
121 return 0;
122 }
123
124 static int
op_wc_strcasecmp(int argc,char ** argv)125 op_wc_strcasecmp(int argc, char **argv)
126 {
127 unsigned *wa, *wb;
128 char *opname = *argv++;
129 argc--;
130 if (argc != 2) {
131 dico_log(L_ERR, 0, "%s requires two arguments", opname);
132 return 1;
133 }
134
135 wa = strtowc(argv[0]);
136 wb = strtowc(argv[1]);
137
138 printf("%d\n", utf8_wc_strcasecmp(wa, wb));
139 return 0;
140 }
141
142 static int
op_wc_strncasecmp(int argc,char ** argv)143 op_wc_strncasecmp(int argc, char **argv)
144 {
145 unsigned *wa, *wb;
146 char *opname = *argv++;
147 argc--;
148 if (argc != 3) {
149 dico_log(L_ERR, 0, "%s requires three arguments", opname);
150 return 1;
151 }
152
153 wa = strtowc(argv[0]);
154 wb = strtowc(argv[1]);
155
156 printf("%d\n", utf8_wc_strncasecmp(wa, wb, atoi(argv[2])));
157 return 0;
158 }
159
160 static int
op_toupper(int argc,char ** argv)161 op_toupper(int argc, char **argv)
162 {
163 char *opname = *argv++;
164 argc--;
165 if (argc != 1) {
166 dico_log(L_ERR, 0, "%s requires one arguments", opname);
167 return 1;
168 }
169 if (utf8_toupper(argv[0]))
170 abort();
171 printf("%s\n", argv[0]);
172 return 0;
173 }
174
175 static int
op_tolower(int argc,char ** argv)176 op_tolower(int argc, char **argv)
177 {
178 char *opname = *argv++;
179 argc--;
180 if (argc != 1) {
181 dico_log(L_ERR, 0, "%s requires one argument", opname);
182 return 1;
183 }
184 if (utf8_tolower(argv[0]))
185 abort();
186 printf("%s\n", argv[0]);
187 return 0;
188 }
189
190 static int
op_wc_strchr(int argc,char ** argv)191 op_wc_strchr(int argc, char **argv)
192 {
193 unsigned *wa, *wb;
194 const unsigned *p;
195 char *opname = *argv++;
196 argc--;
197 if (argc != 2) {
198 dico_log(L_ERR, 0, "%s requires two arguments", opname);
199 return 1;
200 }
201
202 wa = strtowc(argv[0]);
203 wb = strtowc(argv[1]);
204 p = utf8_wc_strchr(wa, wb[0]);
205 if (!p)
206 return 2;
207 printf("%td\n", p - wa);
208 return 0;
209 }
210
211 static int
op_wc_strchr_ci(int argc,char ** argv)212 op_wc_strchr_ci(int argc, char **argv)
213 {
214 unsigned *wa, *wb;
215 const unsigned *p;
216 char *opname = *argv++;
217 argc--;
218 if (argc != 2) {
219 dico_log(L_ERR, 0, "%s requires two arguments", opname);
220 return 1;
221 }
222
223 wa = strtowc(argv[0]);
224 wb = strtowc(argv[1]);
225 p = utf8_wc_strchr_ci(wa, wb[0]);
226 if (!p)
227 return 2;
228 printf("%td\n", p - wa);
229 return 0;
230 }
231
232 static int
op_wc_strstr(int argc,char ** argv)233 op_wc_strstr(int argc, char **argv)
234 {
235 unsigned *wa, *wb;
236 const unsigned *p;
237 char *opname = *argv++;
238 argc--;
239 if (argc != 2) {
240 dico_log(L_ERR, 0, "%s requires two arguments", opname);
241 return 1;
242 }
243
244 wa = strtowc(argv[0]);
245 wb = strtowc(argv[1]);
246 p = utf8_wc_strstr(wa, wb);
247 if (!p) {
248 if (errno) {
249 dico_log(L_ERR, errno, "can't match");
250 return 3;
251 }
252 return 2;
253 }
254 printf("%td\n", p - wa);
255 return 0;
256 }
257
258 struct optab optab[] = {
259 { "help", help },
260 { "strlen", op_strlen },
261 { "strcasecmp", op_strcasecmp },
262 { "strncasecmp", op_strncasecmp },
263 { "wc_strcmp", op_wc_strcmp },
264 { "wc_strncmp", op_wc_strncmp },
265 { "wc_strcasecmp", op_wc_strcasecmp },
266 { "wc_strncasecmp", op_wc_strncasecmp },
267 { "toupper", op_toupper },
268 { "tolower", op_tolower },
269 { "wc_strchr", op_wc_strchr },
270 { "wc_strchr_ci", op_wc_strchr_ci },
271 { "wc_strstr", op_wc_strstr },
272 { NULL }
273 };
274
275 void
usage(FILE * fp)276 usage(FILE *fp)
277 {
278 fprintf(fp, "usage: %s [op] [args]\n", dico_program_name);
279 }
280
281 int
main(int argc,char ** argv)282 main(int argc, char **argv)
283 {
284 struct optab *op;
285
286 dico_set_program_name(argv[0]);
287 argc--;
288 argv++;
289 if (!argc) {
290 usage(stderr);
291 return 1;
292 }
293 for (op = optab; op->name; op++)
294 if (strcmp(*argv, op->name) == 0)
295 return op->fun(argc, argv);
296 dico_log(L_ERR, 0, "unknown operation");
297 return 1;
298 }
299