diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | fgetwc_fix.c | 33 | ||||
-rw-r--r-- | fgetwc_fix.h | 5 | ||||
-rw-r--r-- | lolcat.c | 88 |
4 files changed, 111 insertions, 20 deletions
@@ -1,5 +1,6 @@ all: lolcat -lolcat: lolcat.c - gcc -std=c99 -Wall -o lolcat lolcat.c +lolcat: lolcat.c fgetwc_fix.c + gcc -g -std=c99 -Wall -o lolcat lolcat.c fgetwc_fix.c +# gcc -g -std=c99 -Wall -nostdinc -nostdlib -I/usr/x86_64-linux-uclibc/usr/include -I/usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.1/include -I/usr/include -L/usr/x86_64-linux-uclibc/usr/lib /usr/x86_64-linux-uclibc/usr/lib/crt1.o -lc -lrt -o lolcat lolcat.c diff --git a/fgetwc_fix.c b/fgetwc_fix.c new file mode 100644 index 0000000..ed770ce --- /dev/null +++ b/fgetwc_fix.c @@ -0,0 +1,33 @@ + +#include <stdlib.h> +#include <wchar.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "fgetwc_fix.h" + +/* code blatantly ripped from newlib. If you are from newlib: newlib rocks, keep going! */ +wint_t _fgetwc_fixed(FILE *fp) { + wchar_t wc; + size_t res; + size_t nconv = 0; + char buf[MB_CUR_MAX]; + mbstate_t mbstate; + memset(&mbstate, 0, sizeof(mbstate)); + + while((buf[nconv++] = fgetc(fp)) != EOF){ + res = mbrtowc(&wc, buf, nconv, &mbstate); + if (res == (size_t)-1) /* invalid sequence */ + break; + else if (res == (size_t)-2) /* incomplete sequence */ + continue; + else if (res == 0) + return L'\0'; + else + return wc; + } + + errno = EILSEQ; + return WEOF; +} diff --git a/fgetwc_fix.h b/fgetwc_fix.h new file mode 100644 index 0000000..343d9f7 --- /dev/null +++ b/fgetwc_fix.h @@ -0,0 +1,5 @@ + +#include <wchar.h> +#include <stdint.h> + +wint_t _fgetwc_fixed(FILE *fp); @@ -13,6 +13,9 @@ * 0. You just DO WHAT THE FUCK YOU WANT TO. */ +#define _GNU_SOURCE //for fmemopen + +#include <stdint.h> #include <stdio.h> #include <wchar.h> #include <ctype.h> @@ -21,9 +24,35 @@ #include <stdlib.h> #include <string.h> #include <locale.h> +#include <unistd.h> +#include <sys/time.h> + +#include "fgetwc_fix.h" + + +static char helpstr[] = "\n" +"Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n" +"\n" +"Concatenate FILE(s), or standard input, to standard output.\n" +"With no FILE, or when FILE is -, read standard input.\n" +"\n" +" -h <d>: Horizontal rainbow frequency (default: 0.23)\n" +" -v <d>: Vertical rainbow frequency (default: 0.1)\n" +" -f: Force color even when stdout is not a tty\n" +" --version: Print version and exit\n" +" --help: Show this message\n" +"\n" +"Examples:\n" +" lolcat f - g Output f's contents, then stdin, then g's contents.\n" +" lolcat Copy standard input to standard output.\n" +" fortune | lolcat Display a rainbow cookie.\n" +"\n" +"Report lolcat bugs to <http://www.github.org/jaseg/lolcat/issues>\n" +"lolcat home page: <http://www.github.org/jaseg/lolcat/>\n" +"Original idea: <http://www.github.org/busyloop/lolcat/>\n"; #define ARRAY_SIZE(foo) (sizeof(foo)/sizeof(foo[0])) -char codes[] = {39,38,44,43,49,48,84,83,119,118,154,148,184,178,214,208,209,203,204,198,199,163,164,128,129,93,99,63,69,33}; +const char codes[] = {39,38,44,43,49,48,84,83,119,118,154,148,184,178,214,208,209,203,204,198,199,163,164,128,129,93,99,63,69,33}; /* CAUTION! this function uses a function-static variable! */ void find_escape_sequences(int c, int *state){ @@ -43,10 +72,20 @@ void usage(){ exit(1); } +void version(){ + printf("lolcat version 0.1, (c) 2014 jaseg\n"); + exit(0); +} + int main(int argc, char **argv){ int c, cc=-1, i, l=0; + int colors=(isatty(1) == 1); double freq_h = 0.23, freq_v = 0.1; + struct timeval tv; + gettimeofday(&tv, NULL); + double offx = (tv.tv_sec%300)/300.0; + for(i=1;i<argc;i++){ char *endptr; if(!strcmp(argv[i], "-h")){ @@ -65,6 +104,10 @@ int main(int argc, char **argv){ }else{ usage(); } + }else if(!strcmp(argv[i], "-f")){ + colors = 1; + }else if(!strcmp(argv[i], "--version")){ + version(); }else{ if(!strcmp(argv[i], "--")) i++; @@ -87,20 +130,29 @@ int main(int argc, char **argv){ FILE *f = stdin; int escape_state = 0; - if(strcmp(*filename, "-")) + if(!strcmp(*filename, "--help")) + f = fmemopen(helpstr, strlen(helpstr), "r"); + else if(strcmp(*filename, "-")) f = fopen(*filename, "r"); - - while((c = fgetwc(f)) > 0){ - find_escape_sequences(c, &escape_state); - - if(!escape_state){ - if(c == '\n'){ - l++; - i = 0; - }else if(!iscntrl(c)){ - int ncc = (int)((i++)*freq_h + l*freq_v); - if(cc != ncc) - printf("\033[38;5;%hhum", codes[(cc = ncc) % ARRAY_SIZE(codes)]); + + if(!f){ + fprintf(stderr, "Cannot open input file \"%s\": %s\n", *filename, strerror(errno)); + return 2; + } + + while((c = _fgetwc_fixed(f)) > 0){ + if(colors){ + find_escape_sequences(c, &escape_state); + + if(!escape_state){ + if(c == '\n'){ + l++; + i = 0; + }else if(!iscntrl(c)){ + int ncc = offx*ARRAY_SIZE(codes) + (int)((i++)*freq_h + l*freq_v); + if(cc != ncc) + printf("\033[38;5;%hhum", codes[(cc = ncc) % ARRAY_SIZE(codes)]); + } } } @@ -110,11 +162,11 @@ int main(int argc, char **argv){ printf("\033[38;5;%hhum", codes[cc % ARRAY_SIZE(codes)]); } - if(c != WEOF){ - fprintf(stderr, "Error reading input file \"%s\": %s (%d)\n", *filename, strerror(errno), errno); + fclose(f); + + if(c != WEOF && c != 0){ + fprintf(stderr, "Error reading input file \"%s\": %s\n", *filename, strerror(errno)); return 2; } - - fclose(f); } } |