diff --git a/Makefile b/Makefile index 653fe72..359c2e6 100644 --- a/Makefile +++ b/Makefile @@ -102,10 +102,10 @@ streq: libio streq.o $(CC) $(CFLAGS) -o bin/streq build/libio.o build/streq.o str.o: src/str.c - $(CC) $(CFLAGS) -o build/str.o src/str.c + $(CC) $(CFLAGS) -c -o build/str.o src/str.c str: libio str.o - $(CC) $(CFLAGS) -o bin/str lib/libio.o src/str.o + $(CC) $(CFLAGS) -o bin/str build/libio.o build/str.o sleep.o: libio sysexits src/sleep.c usefulmacros $(CC) $(CFLAGS) -c -o build/sleep.o src/sleep.c diff --git a/src/str.c b/src/str.c index 9a26b39..e93c4d5 100644 --- a/src/str.c +++ b/src/str.c @@ -1,50 +1,60 @@ +#include #include +#include /* strcmp(3) */ #include -#include -#include "libstrnum.h" +#include /* write(2) */ +#include "libio.h" /* fdputs(3) */ +#include "usefulmacros.h" -int *typenames[] = { - (int []){ 'f','l','o','a','t', ASCII_US, STRIS_TYPE_FLOAT, '\0' }, - (int []){ 'i','n','t', ASCII_US, STRIS_TYPE_INT, '\0' }, - (int []){ 'u','i','n','t', ASCII_US, STRIS_TYPE_UINT, '\0' } +static char *program_name = "str"; + +static struct { + char *name; + int (*f)(int); +}ctypes[] = { + { "isalnum", isalnum }, + { "isalpha", isalpha }, + { "isblank", isblank }, + { "iscntrl", iscntrl }, + { "isdigit", isdigit }, + { "isxdigit", isxdigit }, + { "isgraph", isgraph }, + { "islower", islower }, + { "isprint", isprint }, + { "ispunct", ispunct }, + { "isspace", isspace }, + { "isupper", isupper } }; -size_t typenames_s = 3; - int main(int argc, char *argv[]){ int i; int j; - int k; - enum Strtype t; - for(k = 0; argv[0][k] != '\0'; ++k); if(argc < 3){ - write(2, "Usage: ", 7); - write(2, argv[0], k); +error: write(2, "Usage: ", 7); + fdputs(2, argv[0] == NULL ? program_name : argv[0]); write(2, " [type] [string...]\n", 20); return EX_USAGE; } - j = 0; - t = 0; - for(i = 0; argv[1][i] != '\0'; ++i) - if(typenames[j][i] != argv[1][i]) - if(++j >= typenames_s){ - write(2, argv[0], k); - write(2, ": ", 2); - for(k = 0; argv[1][k] != '\0'; ++k); - write(2, argv[1], k); - write(2, ": No such type\n", 15); - return EX_DATAERR; - } + /* We could skip checking the first two characters and replace it with + * a single if(argv[1][0] == 'i' && argv[1][1] == 's') or something + * but it's simpler to just waste the cycles. */ + /* slow but for our purposes this is fine */ + for(i = 0; i < ARRAYLEN(ctypes); ++i) + if(strcmp(argv[1], ctypes[i].name) == 0){ + i *= -1; + break; + } + if(i > 0) + goto error; + i *= -1; - if(argv[1][i] == '\0' && typenames[j][i] == ASCII_US) - t = typenames[j][i+1]; - - for(i = 2; i < argc; ++i) - if(!stris(t, argv[i])) - return 1; + for(argv += 2; *argv != NULL; ++argv) + for(j = 0; argv[0][j] != '\0'; ++j) + if(!ctypes[i].f(argv[0][j])) + return 1; return 0; }