aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2016-12-28 13:08:41 +0100
committerMattias Andrée <maandree@kth.se>2016-12-28 13:08:41 +0100
commit7acda6127bba779f33d04bcbd3f76ca633e012fc (patch)
tree54a09ea5df00d5f4d325f9519b35f5fbc0730fc9
parentAdd LICENSE, arg.h, and xtest.c (diff)
downloadxtest-7acda6127bba779f33d04bcbd3f76ca633e012fc.tar.gz
xtest-7acda6127bba779f33d04bcbd3f76ca633e012fc.tar.bz2
xtest-7acda6127bba779f33d04bcbd3f76ca633e012fc.tar.xz
Add +flags for inverted match
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--arg.h61
-rw-r--r--xtest.c88
2 files changed, 87 insertions, 62 deletions
diff --git a/arg.h b/arg.h
index 0b23c53..b8169f3 100644
--- a/arg.h
+++ b/arg.h
@@ -10,38 +10,51 @@ extern char *argv0;
/* use main(int argc, char *argv[]) */
#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
- argv[0] && argv[0][0] == '-'\
- && argv[0][1];\
+ argv[0] && argv[0][1];\
argc--, argv++) {\
char argc_;\
char **argv_;\
int brk_;\
- 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)\
+ if (argv[0][0] == '-') {\
+ if (argv[0][1] == '-' && argv[0][2] == '\0') {\
+ argv++;\
+ argc--;\
break;\
- argc_ = argv[0][0];\
- switch (argc_)
+ }\
+ 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 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 }\
+#define ARGEND }\
+ } else {\
+ break;\
+ }\
}
#define ARGC() argc_
diff --git a/xtest.c b/xtest.c
index 46baad3..3b4edd5 100644
--- a/xtest.c
+++ b/xtest.c
@@ -13,7 +13,8 @@
char *argv0;
static char delim = '\n';
-static long int tests = 0;
+static long int pos_tests = 0;
+static long int neg_tests = 0;
static int test_b(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISBLK (buf.st_mode); }
static int test_c(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISCHR (buf.st_mode); }
@@ -44,29 +45,37 @@ test_t(char *s)
return isatty((int)fd);
}
+#define LIST_TESTS\
+ X('b', test_b, 0)\
+ X('c', test_c, 1)\
+ X('d', test_d, 2)\
+ X('e', test_e, 3)\
+ X('f', test_f, 4)\
+ X('g', test_g, 5)\
+ X('h', test_h, 6)\
+ X('k', test_k, 7)\
+ X('p', test_p, 8)\
+ X('r', test_r, 9)\
+ X('S', test_S, 10)\
+ X('s', test_s, 11)\
+ X('t', test_t, 12)\
+ X('u', test_u, 13)\
+ X('w', test_w, 14)\
+ X('x', test_x, 15)
+
+#define LIST_SYNONYMS\
+ X('L', test_h, 6)
+
static int (*testmap[])(char *) = {
- test_b,
- test_c,
- test_d,
- test_e,
- test_f,
- test_g,
- test_h,
- test_k,
- test_p,
- test_r,
- test_S,
- test_s,
- test_t,
- test_u,
- test_w,
- test_x
+#define X(FLAG, FUNC, NUM) FUNC,
+ LIST_TESTS
+#undef X
};
static void
usage(void)
{
- fprintf(stderr, "usage: %s [-0bcdefghkLprSstuwx] file ...\n", argv0);
+ fprintf(stderr, "usage: %s [-0bcdefghkLprSstuwx] [+bcdefghkLprSstuwx] file ...\n", argv0);
exit(1);
}
@@ -74,8 +83,15 @@ static void
test(char *s)
{
long int i, j;
- for (i = 0; j = 1L << i, j <= tests; i++) {
- if ((tests & j) && testmap[i](s)) {
+ for (i = 0; j = 1L << i, j <= pos_tests; i++) {
+ if ((pos_tests & j) && testmap[i](s)) {
+ printf("%s%c", s, delim);
+ fflush(stdout);
+ break;
+ }
+ }
+ for (i = 0; j = 1L << i, j <= neg_tests; i++) {
+ if ((neg_tests & j) && !testmap[i](s)) {
printf("%s%c", s, delim);
fflush(stdout);
break;
@@ -94,28 +110,24 @@ main(int argc, char *argv[])
case '0':
delim = '\0';
break;
- case 'b': tests |= 1 << 0; break;
- case 'c': tests |= 1 << 1; break;
- case 'd': tests |= 1 << 2; break;
- case 'e': tests |= 1 << 3; break;
- case 'f': tests |= 1 << 4; break;
- case 'g': tests |= 1 << 5; break;
- case 'h': tests |= 1 << 6; break;
- case 'k': tests |= 1 << 7; break;
- case 'L': tests |= 1 << 6; break;
- case 'p': tests |= 1 << 8; break;
- case 'r': tests |= 1 << 9; break;
- case 'S': tests |= 1 << 10; break;
- case 's': tests |= 1 << 11; break;
- case 't': tests |= 1 << 12; break;
- case 'u': tests |= 1 << 13; break;
- case 'w': tests |= 1 << 14; break;
- case 'x': tests |= 1 << 15; break;
+#define X(FLAG, FUNC, NUM)\
+ case FLAG: pos_tests |= 1 << NUM; break;
+ LIST_TESTS
+ LIST_SYNONYMS
+#undef X
+ default:
+ usage();
+ } ARGALT('+') {
+#define X(FLAG, FUNC, NUM)\
+ case FLAG: neg_tests |= 1 << NUM; break;
+ LIST_TESTS
+ LIST_SYNONYMS
+#undef X
default:
usage();
} ARGEND;
- if (!tests) {
+ if (!pos_tests && !neg_tests) {
fprintf(stderr, "%s: at least one test is required\n", argv0);
return 1;
}