/* See LICENSE file for copyright and license details. */ #include "common.h" char *argv0; int main(int argc, char *argv[]) { if (!argc) { fprintf(stderr, "numtext: no command lines arguments specified, don't know what to execute\n"); return 1; } argv0 = strrchr(argv[0], '/'); argv0 = argv0 ? &argv0[1] : argv[0]; if (!strcmp(argv0, "numtext-strip")) return numtext_strip_main(argc, argv); else if (!strcmp(argv0, "card2ord")) return card2ord_main(argc, argv); fprintf(stderr, "%s: not a recognised command for numtext multicall binary\n", argv[0]); return 1; } int run(int argc, char *argv[], ssize_t (*callback)(char *outbuf, size_t outbuf_size, const char *num, size_t num_len)) { char *line = NULL; size_t size = 0; ssize_t len; int ret = 0; char *outbuf = NULL; size_t outbuf_size = 0; size_t num_len; if (argc) { for (; *argv; argv++) { num_len = strlen(*argv); len = callback(outbuf, outbuf_size, *argv, num_len); if (len < 0) { ret = 1; continue; } if ((size_t)len > outbuf_size) { outbuf_size = (size_t)len; outbuf = realloc(outbuf, outbuf_size); if (!outbuf) { fprintf(stderr, "%s: realloc %zu: %s\n", argv0, outbuf_size, strerror(errno)); exit(1); } } len = callback(outbuf, outbuf_size, *argv, num_len); if (len < 0) { ret = 1; continue; } printf("%s\n", outbuf); } } else { for (;;) { len = getline(&line, &size, stdin); if (len == -1) break; if (len && line[len - 1] == '\n') line[--len] = '\0'; if (!len) continue; num_len = (size_t)len; len = callback(outbuf, outbuf_size, line, num_len); if (len < 0) { ret = 1; continue; } if ((size_t)len > outbuf_size) { outbuf_size = (size_t)len; outbuf = realloc(outbuf, outbuf_size); if (!outbuf) { fprintf(stderr, "%s: realloc %zu: %s\n", argv0, outbuf_size, strerror(errno)); exit(1); } } len = callback(outbuf, outbuf_size, line, num_len); if (len < 0) { ret = 1; continue; } printf("%s\n", outbuf); } if (ferror(stdin)) { fprintf(stderr, "%s: getline : %s\n", argv0, strerror(errno)); ret = 1; } free(line); } if (fflush(stdout) || fclose(stdout)) { fprintf(stderr, "%s: printf: %s\n", argv0, strerror(errno)); ret = 1; } free(outbuf); return ret; } int get_language(const char *arg, enum libnumtext_language *langp, int *have_langp) { static const struct language { enum libnumtext_language value; const char *code; const char *name; } languages[] = { {LIBNUMTEXT_SWEDISH, "sv", "swedish"} }; size_t i; if (*have_langp) return 0; *have_langp = 1; if (!strcmp(arg, "?")) { printf("Languages:\n"); for (i = 0; i < sizeof(languages) / sizeof(*languages); i++) printf("\t%s %s\n", languages[i].code, languages[i].name); exit(0); } else { for (i = 0; i < sizeof(languages) / sizeof(*languages); i++) { if (!strcasecmp(arg, languages[i].code) || !strcasecmp(arg, languages[i].name)) { *langp = languages[i].value; return 1; } } fprintf(stderr, "%s: unrecognised language, use ? to list available languages: %s\n", argv0, arg); exit(1); } } static char * process_option(char *opt, struct option *options, uint32_t *flagsp, uint32_t *maskedp) { size_t len; if (opt[0] == '?' && (!opt[1] || opt[1] == ',')) { printf("Options:\n"); for (; options->option; options++) if (options->option_pattern) printf("\t%s\n", options->option_pattern); exit(0); } for (; options->option; options++) { len = strlen(options->option); if (!strncmp(opt, options->option, len) && (!opt[len] || opt[len] == ',')) { if (options->mask & *maskedp) { fprintf(stderr, "%s: option conflicts with previously specified option: %.*s\n", argv0, (int)len, opt); exit(1); } *flagsp |= options->flag; *maskedp |= options->mask; return &opt[len]; } } fprintf(stderr, "%s: unrecognised option for selected language, use ? to list available options: %s\n", argv0, opt); exit(1); } void process_options(char **optss, size_t n_optss, struct option *options, uint32_t *flagsp, uint32_t *maskedp) { uint32_t _masked; char *opts; size_t i; if (!maskedp) maskedp = &_masked; *flagsp = 0; *maskedp = 0; for (i = 0; i < n_optss; i++) { opts = optss[i]; for (;;) { while (*opts == ',') opts = &opts[1]; if (!*opts) break; else opts = process_option(opts, options, flagsp, maskedp); } } }