From 02d288d89683e99fd18fe9f54d4e731a6c474a4f Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 12 Apr 2012 01:38:35 -0400 Subject: initial check-in --- src/strings.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/strings.c (limited to 'src/strings.c') diff --git a/src/strings.c b/src/strings.c new file mode 100644 index 0000000..5a1781b --- /dev/null +++ b/src/strings.c @@ -0,0 +1,132 @@ +/* + * strings.c + * Implementation of SUSv3 XCU strings utility + * Copyright © 2007 Rich Felker + * Licensed under the terms of the GNU General Public License, v2 or later + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int my_mbrtowc(wchar_t *wc, int b, mbstate_t *st) +{ + char c = b; + int retry = 1; +retry: + switch ((int)mbrtowc(wc, &c, 1, st)) { + case -2: + return -2; + case -1: + memset(st, 0, sizeof(mbstate_t)); + if (retry--) goto retry; + return retry; /* yes this is lame */ + } + return 1; +} + +int main(int argc, char *argv[]) +{ + mbstate_t st; + wchar_t *buf; + size_t i, min = 4; + int b; + off_t start, ofs; + int l; + char fmtbuf[] = "%ll? ", *fmt=fmtbuf+5; + int ret = 0; + int in_str; + FILE *f = stdin; + char *name = "(stdin)"; + + if (!setlocale(LC_CTYPE, "")) { + fprintf(stderr, "%s: warning: cannot set LC_CTYPE", argv[0]); + perror(""); + } + + while ((b = getopt(argc, argv, "an:t:")) != EOF) switch(b) { + case 'a': + /* no-op: we always search entire file */ + break; + case 'n': + min = strtoul(optarg, NULL, 10); + if (min < 1 || min >= SIZE_MAX) { + fprintf(stderr, "%s: invalid argument to -%c: %s\n", + argv[0], b, optarg); + exit(1); + } + break; + case 't': + if (!strchr("dox", optarg[0]) || optarg[1]) { + fprintf(stderr, "%s: invalid argument to -%c: %s\n", + argv[0], b, optarg); + exit(1); + } + fmt = fmtbuf; + fmt[3] = optarg[0]; + break; + default: + exit(1); + } + + /* min+1 does not overflow because of above check */ + if (!(buf = calloc(sizeof(wchar_t), min+1))) { + fprintf(stderr, "%s: ", argv[0]); + perror("calloc failed"); + exit(1); + } + + if (optind < argc) goto nextfile; +begin: + memset(&st, 0, sizeof(mbstate_t)); + start = ofs = i = in_str = 0; + while ((b=getc(f)) >= 0) { + ofs++; + l = my_mbrtowc(buf+i, b, &st); + if (l == -2) continue; + if (l == -1 || !iswprint(buf[i])) { + if (in_str) putchar('\n'); + in_str = 0; + i = 0; + start = ofs; + continue; + } + if (i