/* This file is part of GNU Dico Copyright (C) 2012-2020 Sergey Poznyakoff GNU Dico is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Dico is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Dico. If not, see . */ #include #include #include #include #include typedef int (*opfn) (int argc, char **argv); struct optab { char *name; opfn fun; }; static unsigned * strtowc(const char *str) { unsigned *buf; if (utf8_mbstr_to_wc(str, &buf, NULL)) { dico_log(L_ERR, errno, "cannot convert \"%s\"", str); abort(); } return buf; } static int help(int argc, char **argv) { printf("No more help, sorry"); return 0; } static int op_strlen(int argc, char **argv) { char *opname = *argv++; argc--; if (argc != 1) { dico_log(L_ERR, 0, "%s requires one argument", opname); return 1; } printf("%lu\n", (unsigned long) utf8_strlen(argv[0])); return 0; } static int op_strcasecmp(int argc, char **argv) { char *opname = *argv++; argc--; if (argc != 2) { dico_log(L_ERR, 0, "%s requires two arguments", opname); return 1; } printf("%d\n", utf8_strcasecmp(argv[0], argv[1])); return 0; } static int op_strncasecmp(int argc, char **argv) { char *opname = *argv++; argc--; if (argc != 3) { dico_log(L_ERR, 0, "%s requires three arguments", opname); return 1; } printf("%d\n", utf8_strncasecmp(argv[0], argv[1], atoi(argv[2]))); return 0; } static int op_wc_strcmp(int argc, char **argv) { unsigned *wa, *wb; char *opname = *argv++; argc--; if (argc != 2) { dico_log(L_ERR, 0, "%s requires two arguments", opname); return 1; } wa = strtowc(argv[0]); wb = strtowc(argv[1]); printf("%d\n", utf8_wc_strcmp(wa, wb)); return 0; } static int op_wc_strncmp(int argc, char **argv) { unsigned *wa, *wb; char *opname = *argv++; argc--; if (argc != 3) { dico_log(L_ERR, 0, "%s requires three arguments", opname); return 1; } wa = strtowc(argv[0]); wb = strtowc(argv[1]); printf("%d\n", utf8_wc_strncmp(wa, wb, atoi(argv[2]))); return 0; } static int op_wc_strcasecmp(int argc, char **argv) { unsigned *wa, *wb; char *opname = *argv++; argc--; if (argc != 2) { dico_log(L_ERR, 0, "%s requires two arguments", opname); return 1; } wa = strtowc(argv[0]); wb = strtowc(argv[1]); printf("%d\n", utf8_wc_strcasecmp(wa, wb)); return 0; } static int op_wc_strncasecmp(int argc, char **argv) { unsigned *wa, *wb; char *opname = *argv++; argc--; if (argc != 3) { dico_log(L_ERR, 0, "%s requires three arguments", opname); return 1; } wa = strtowc(argv[0]); wb = strtowc(argv[1]); printf("%d\n", utf8_wc_strncasecmp(wa, wb, atoi(argv[2]))); return 0; } static int op_toupper(int argc, char **argv) { char *opname = *argv++; argc--; if (argc != 1) { dico_log(L_ERR, 0, "%s requires one arguments", opname); return 1; } if (utf8_toupper(argv[0])) abort(); printf("%s\n", argv[0]); return 0; } static int op_tolower(int argc, char **argv) { char *opname = *argv++; argc--; if (argc != 1) { dico_log(L_ERR, 0, "%s requires one argument", opname); return 1; } if (utf8_tolower(argv[0])) abort(); printf("%s\n", argv[0]); return 0; } static int op_wc_strchr(int argc, char **argv) { unsigned *wa, *wb; const unsigned *p; char *opname = *argv++; argc--; if (argc != 2) { dico_log(L_ERR, 0, "%s requires two arguments", opname); return 1; } wa = strtowc(argv[0]); wb = strtowc(argv[1]); p = utf8_wc_strchr(wa, wb[0]); if (!p) return 2; printf("%td\n", p - wa); return 0; } static int op_wc_strchr_ci(int argc, char **argv) { unsigned *wa, *wb; const unsigned *p; char *opname = *argv++; argc--; if (argc != 2) { dico_log(L_ERR, 0, "%s requires two arguments", opname); return 1; } wa = strtowc(argv[0]); wb = strtowc(argv[1]); p = utf8_wc_strchr_ci(wa, wb[0]); if (!p) return 2; printf("%td\n", p - wa); return 0; } static int op_wc_strstr(int argc, char **argv) { unsigned *wa, *wb; const unsigned *p; char *opname = *argv++; argc--; if (argc != 2) { dico_log(L_ERR, 0, "%s requires two arguments", opname); return 1; } wa = strtowc(argv[0]); wb = strtowc(argv[1]); p = utf8_wc_strstr(wa, wb); if (!p) { if (errno) { dico_log(L_ERR, errno, "can't match"); return 3; } return 2; } printf("%td\n", p - wa); return 0; } struct optab optab[] = { { "help", help }, { "strlen", op_strlen }, { "strcasecmp", op_strcasecmp }, { "strncasecmp", op_strncasecmp }, { "wc_strcmp", op_wc_strcmp }, { "wc_strncmp", op_wc_strncmp }, { "wc_strcasecmp", op_wc_strcasecmp }, { "wc_strncasecmp", op_wc_strncasecmp }, { "toupper", op_toupper }, { "tolower", op_tolower }, { "wc_strchr", op_wc_strchr }, { "wc_strchr_ci", op_wc_strchr_ci }, { "wc_strstr", op_wc_strstr }, { NULL } }; void usage(FILE *fp) { fprintf(fp, "usage: %s [op] [args]\n", dico_program_name); } int main(int argc, char **argv) { struct optab *op; dico_set_program_name(argv[0]); argc--; argv++; if (!argc) { usage(stderr); return 1; } for (op = optab; op->name; op++) if (strcmp(*argv, op->name) == 0) return op->fun(argc, argv); dico_log(L_ERR, 0, "unknown operation"); return 1; }