utftest.c (2549B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <stdarg.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include "utf.h" 7 8 #define ARGBEGIN \ 9 { \ 10 Rune _argr; \ 11 \ 12 if(!argv0) \ 13 argv0 = argv[0]; \ 14 for(argc--, argv++; *argv && (*argv)[0] == '-' && (*argv)[1] != '\0'; argc--, argv++) { \ 15 if((*argv)[1] == '-' && (*argv)[2] == '\0') { /* -- signifies end of flags */ \ 16 argc--; argv++; \ 17 break; \ 18 } \ 19 (*argv)++; \ 20 while(**argv != '\0' && (*argv += chartorune(&_argr, *argv))) \ 21 switch(_argr) 22 23 #define ARGEND \ 24 } \ 25 } 26 27 #define ARGC() _argr 28 29 static void eprintf(const char *, ...); 30 static void usage(void); 31 32 static const char *argv0; 33 34 int 35 main(int argc, char *argv[]) 36 { 37 int aflag = 0, dflag = 0, lflag = 0, sflag = 0, tflag = 0, uflag = 0, vflag = 0; 38 char buf[BUFSIZ], rbuf[UTFmax]; 39 int len, len2; 40 size_t i, j, n; 41 Rune r; 42 43 ARGBEGIN { 44 case 'a': aflag = 1; break; 45 case 'd': dflag = 1; break; 46 case 'l': lflag = 1; break; 47 case 's': sflag = 1; break; 48 case 't': tflag = 1; break; 49 case 'u': uflag = 1; break; 50 case 'v': vflag = 1; break; 51 default: 52 r = ARGC(); 53 rbuf[runetochar(rbuf, &r)] = '\0'; 54 eprintf("unknown flag -%s\n", rbuf); 55 usage(); 56 } ARGEND; 57 58 if(argc != 0) 59 usage(); 60 61 for(i = 0; (n = fread(&buf[i], 1, sizeof buf - i, stdin)); i = n-i) { 62 for(n += i, i = 0; (len = charntorune(&r, &buf[i], n-i)); i += len) { 63 if(r == Runeerror) { 64 fprintf(stderr, "%s: error converting char to rune:", argv0); 65 for(j = i; j < i+len; j++) 66 fprintf(stderr, " %02X", (unsigned char)buf[j]); 67 fputc('\n', stderr); 68 } 69 if(((aflag && isalpharune(r)) || (dflag && isdigitrune(r)) 70 || (lflag && islowerrune(r)) || (sflag && isspacerune(r)) 71 || (tflag && istitlerune(r)) || (uflag && isupperrune(r)) 72 || (!aflag && !dflag && !lflag && !sflag && !tflag && !uflag)) == vflag) 73 continue; 74 75 if((len2 = runetochar(rbuf, &r))) { 76 if(!fwrite(rbuf, len2, 1, stdout)) 77 eprintf("write error:"); 78 } 79 else 80 fprintf(stderr, "%s: error converting rune to char: U+%02X\n", argv0, r); 81 } 82 if(i < n) 83 memcpy(buf, &buf[i], n-i); 84 } 85 if(ferror(stdin)) 86 eprintf("read error:"); 87 88 return EXIT_SUCCESS; 89 } 90 91 void 92 eprintf(const char *fmt, ...) 93 { 94 va_list ap; 95 96 fprintf(stderr, "%s: ", argv0); 97 98 va_start(ap, fmt); 99 vfprintf(stderr, fmt, ap); 100 va_end(ap); 101 102 if(fmt[0] && fmt[strlen(fmt)-1] == ':') { 103 fputc(' ', stderr); 104 perror(NULL); 105 } 106 exit(EXIT_FAILURE); 107 } 108 109 void 110 usage(void) 111 { 112 fprintf(stderr, "usage: %s [-adlstuv]\n", argv0); 113 exit(EXIT_FAILURE); 114 }