commit ed2cf4c1d66bcdfbf44c34eb94dd94a0535a9334
parent 2bedb844c0b48f7af4e41f2c7d338e2defcf5859
Author: Mattias Andrée <maandree@kth.se>
Date: Sun, 8 Jan 2017 03:49:20 +0100
Add vu-single-colour
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat:
| A | src/arg.h | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/util.c | | | 171 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/util.h | | | 35 | +++++++++++++++++++++++++++++++++++ |
| A | src/vu-single-colour.c | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 365 insertions(+), 0 deletions(-)
diff --git a/src/arg.h b/src/arg.h
@@ -0,0 +1,78 @@
+/*
+ * Copy me if you can.
+ * by 20h
+ */
+
+#ifndef ARG_H__
+#define ARG_H__
+
+extern char *argv0;
+
+/* use main(int argc, char *argv[]) */
+#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
+ argv[0] && argv[0][1];\
+ argc--, argv++) {\
+ char argc_;\
+ char **argv_;\
+ int brk_;\
+ if (argv[0][0] == '-') {\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
+ break;\
+ }\
+ for (brk_ = 0, argv[0]++, argv_ = argv;\
+ argv[0][0] && !brk_;\
+ argv[0]++) {\
+ if (argv_ != argv)\
+ break;\
+ argc_ = argv[0][0];\
+ switch (argc_)
+
+/* Handles obsolete -NUM syntax */
+#define ARGNUM case '0':\
+ case '1':\
+ case '2':\
+ case '3':\
+ case '4':\
+ case '5':\
+ case '6':\
+ case '7':\
+ case '8':\
+ case '9'
+
+#define ARGALT(SYMBOL) }\
+ } else if (argv[0][0] == SYMBOL) {\
+ for (brk_ = 0, argv[0]++, argv_ = argv;\
+ argv[0][0] && !brk_;\
+ argv[0]++) {\
+ if (argv_ != argv)\
+ break;\
+ argc_ = argv[0][0];\
+ switch (argc_)
+
+#define ARGEND }\
+ } else {\
+ break;\
+ }\
+ }
+
+#define ARGC() argc_
+
+#define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX))
+
+#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ ((x), abort(), (char *)0) :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
+ (char *)0 :\
+ (brk_ = 1, (argv[0][1] != '\0')?\
+ (&argv[0][1]) :\
+ (argc--, argv++, argv[0])))
+
+#define LNGARG() &argv[0][0]
+
+#endif
diff --git a/src/util.c b/src/util.c
@@ -0,0 +1,171 @@
+/* See LICENSE file for copyright and license details. */
+#include "util.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+char *argv0;
+
+static void
+xvprintf(const char *fmt, va_list ap)
+{
+ if (argv0 && strncmp(fmt, "usage", strlen("usage")))
+ fprintf(stderr, "%s: ", argv0);
+
+ vfprintf(stderr, fmt, ap);
+
+ if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
+ fputc(' ', stderr);
+ perror(NULL);
+ }
+}
+
+void
+eprintf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ xvprintf(fmt, ap);
+ va_end(ap);
+
+ exit(1);
+}
+
+void
+enprintf(int status, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ xvprintf(fmt, ap);
+ va_end(ap);
+
+ exit(status);
+}
+
+void
+weprintf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ xvprintf(fmt, ap);
+ va_end(ap);
+}
+
+
+int
+tollu(const char *s, unsigned long long int min, unsigned long long int max, unsigned long long int *out)
+{
+ char *end;
+ errno = 0;
+ if (*s == '-') {
+ errno = ERANGE;
+ return -1;
+ }
+ if (tolower(*s) == 'x' || *s == '#')
+ *out = strtoull(s + 1, &end, 16);
+ else if (*s == '0' && tolower(s[1]) == 'x')
+ *out = strtoull(s + 2, &end, 16);
+ else if (*s == '0' && tolower(s[1]) == 'o')
+ *out = strtoull(s + 2, &end, 8);
+ else if (*s == '0' && tolower(s[1]) == 'b')
+ *out = strtoull(s + 2, &end, 2);
+ else
+ *out = strtoull(s, &end, 10);
+ if (errno)
+ return -1;
+ if (*end) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (*out < min || *out > max) {
+ errno = ERANGE;
+ return -1;
+ }
+ return 0;
+}
+
+int
+tolli(const char *s, long long int min, long long int max, long long int *out)
+{
+ char *end;
+ int sign = 1;
+ unsigned long long int inter;
+ errno = 0;
+ if (*s == '-') {
+ s++;
+ sign = -1;
+ }
+ if (tollu(s, 0, ULLONG_MAX, &inter))
+ return -1;
+ if (sign > 0) {
+ if (max < 0 || inter > (unsigned long long int)max)
+ goto erange;
+ *out = (long long int)inter;
+ if (*out < min)
+ goto erange;
+ } else {
+#if LLONG_MIN == -LLONG_MAX
+ if (inter > -LLONG_MIN)
+ goto erange;
+#else
+ if (inter > (unsigned long long int)LLONG_MAX + 1ULL)
+ goto erange;
+#endif
+ *out = -(long long int)inter;
+ if (*out < min || *out > max)
+ goto erange;
+ }
+ return 0;
+
+erange:
+ errno = ERANGE;
+ return -1;
+}
+
+
+int
+fshut(FILE *fp, const char *fname)
+{
+ int ret = 0;
+
+ /* fflush() is undefined for input streams by ISO C,
+ * but not POSIX 2008 if you ignore ISO C overrides.
+ * Leave it unchecked and rely on the following
+ * functions to detect errors.
+ */
+ fflush(fp);
+
+ if (ferror(fp) && !ret) {
+ weprintf("ferror %s:", fname);
+ ret = 1;
+ }
+
+ if (fclose(fp) && !ret) {
+ weprintf("fclose %s:", fname);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+void
+enfshut(int status, FILE *fp, const char *fname)
+{
+ if (fshut(fp, fname))
+ exit(status);
+}
+
+void
+efshut(FILE *fp, const char *fname)
+{
+ enfshut(1, fp, fname);
+}
diff --git a/src/util.h b/src/util.h
@@ -0,0 +1,35 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdio.h>
+
+#define ELEMENTSOF(ARRAY) (sizeof(ARRAY) / sizeof(*(ARRAY)))
+
+void eprintf(const char *fmt, ...);
+void enprintf(int status, const char *fmt, ...);
+void weprintf(const char *fmt, ...);
+
+int tollu(const char *s, unsigned long long int min, unsigned long long int max, unsigned long long int *out);
+int tolli(const char *s, long long int min, long long int max, long long int *out);
+#define DEF_STR_TO_INT(FNAME, INTTYPE, INTER_FNAME, INTER_INTTYPE)\
+ static inline int\
+ FNAME(const char *s, INTTYPE min, INTTYPE max, INTTYPE *out)\
+ {\
+ INTER_INTTYPE inter;\
+ if (INTER_FNAME(s, (INTER_INTTYPE)min, (INTER_INTTYPE)max, &inter))\
+ return -1;\
+ *out = (INTTYPE)inter;\
+ return 0;\
+ }
+DEF_STR_TO_INT(tolu, unsigned long int, tollu, unsigned long long int)
+DEF_STR_TO_INT(tou, unsigned int, tollu, unsigned long long int)
+DEF_STR_TO_INT(toli, long int, tolli, long long int)
+DEF_STR_TO_INT(toi, int, tolli, long long int)
+#undef DEF_STR_TO_INT
+#define tozu tolu
+#define tozi toli
+#define toju tollu
+#define toji tolli
+
+int fshut(FILE *fp, const char *fname);
+void enfshut(int status, FILE *fp, const char *fname);
+void efshut(FILE *fp, const char *fname);
diff --git a/src/vu-single-colour.c b/src/vu-single-colour.c
@@ -0,0 +1,81 @@
+/* See LICENSE file for copyright and license details. */
+#include "arg.h"
+#include "util.h"
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+ eprintf("usage: %s [-f frames] -w width -h height red green blue [alpha]\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int red, green, blue, alpha = 255;
+ size_t width = 0, height = 0, frames = 1;
+ unsigned char pixel[4];
+ size_t x, y, n;
+ int32_t buf[1024];
+ ssize_t r;
+
+ ARGBEGIN {
+ case 'f':
+ if (tozu(EARGF(usage()), 1, SIZE_MAX, &frames))
+ eprintf("argument of -f must be an integer in [1, %zu]\n", SIZE_MAX);
+ break;
+ case 'w':
+ if (tozu(EARGF(usage()), 1, SIZE_MAX, &width))
+ eprintf("argument of -w must be an integer in [1, %zu]\n", SIZE_MAX);
+ break;
+ case 'h':
+ if (tozu(EARGF(usage()), 1, SIZE_MAX, &height))
+ eprintf("argument of -h must be an integer in [1, %zu]\n", SIZE_MAX);
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!width || !height || argc < 3 || argc > 4)
+ usage();
+
+ if (toi(argv[0], 0, 255, &red))
+ eprintf("the red value must be an integer in [0, 255]\n");
+ if (toi(argv[1], 0, 255, &green))
+ eprintf("the green value must be an integer in [0, 255]\n");
+ if (toi(argv[2], 0, 255, &blue))
+ eprintf("the blue value must be an integer in [0, 255]\n");
+ if (argc > 3 && toi(argv[3], 0, 255, &alpha))
+ eprintf("the alpha value must be an integer in [0, 255]\n");
+
+ pixel[0] = (unsigned char)red;
+ pixel[1] = (unsigned char)green;
+ pixel[2] = (unsigned char)blue;
+ pixel[3] = (unsigned char)alpha;
+
+ for (x = 0; x < ELEMENTSOF(buf); x++)
+ buf[x] = *(int32_t *)(void *)pixel;
+ while (frames--) {
+ for (y = height; y--;) {
+ for (x = width; x;) {
+ n = ELEMENTSOF(buf) < x ? ELEMENTSOF(buf) : x;
+ x -= n;
+ n *= sizeof(*buf);
+ while (n) {
+ r = write(STDOUT_FILENO, buf, n);
+ if (r < 0)
+ eprintf("write <stdout>:");
+ n -= (size_t)r;
+ }
+ }
+ }
+ }
+
+ efshut(stdout, "<stdout>");
+ return 0;
+}