about summary refs log tree commit diff
path: root/lr.c
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2015-10-23 14:23:35 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2015-10-23 14:23:35 +0200
commit16a673847d818d802c7903167b74ccaeaef86f44 (patch)
tree86cc8b1c79c076e09846e0e6e4421844c8ae445b /lr.c
parentc7598e2574388890b08acf0702b4de794f7a7102 (diff)
downloadlr-16a673847d818d802c7903167b74ccaeaef86f44.tar.gz
lr-16a673847d818d802c7903167b74ccaeaef86f44.tar.xz
lr-16a673847d818d802c7903167b74ccaeaef86f44.zip
better mode comparisons
Diffstat (limited to 'lr.c')
-rw-r--r--lr.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/lr.c b/lr.c
index 09c50dd..f31f495 100644
--- a/lr.c
+++ b/lr.c
@@ -101,6 +101,8 @@ enum op {
 	EXPR_REGEXI,
 	EXPR_PRUNE,
 	EXPR_TYPE,
+	EXPR_ALLSET,
+	EXPR_ANYSET
 };
 
 enum prop {
@@ -191,6 +193,24 @@ parse_num(long *r)
 	}
 }
 
+int
+parse_octal(long *r)
+{
+	if (*pos >= '0' && *pos <= '7') {
+		long n = 0;
+		while (*pos >= '0' && *pos <= '7') {
+			n *= 8;
+			n += *pos - '0';
+			pos++;
+		}
+		ws();
+		*r = n;
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
 enum op
 parse_op()
 {
@@ -333,6 +353,34 @@ parse_strcmp()
 }
 
 struct expr *
+parse_mode()
+{
+	struct expr *e = malloc(sizeof (struct expr));
+	long n;
+
+	e->a.prop = PROP_MODE;
+
+	if (token("==")) {
+		e->op = EXPR_EQ;
+	} else if (token("&")) {
+		e->op = EXPR_ALLSET;
+	} else if (token("|")) {
+		e->op = EXPR_ANYSET;
+	} else {
+		parse_error("invalid mode comparison");
+	}
+
+	if (parse_octal(&n)) {
+		e->b.num = n;
+		printf("%d\n", n);
+	} else {
+		parse_error("invalid mode");
+	}
+
+	return e;
+}
+
+struct expr *
 parse_cmp()
 {
 	enum prop prop;
@@ -351,7 +399,7 @@ parse_cmp()
 	else if (token("links"))
 		prop = PROP_LINKS;
 	else if (token("mode"))
-		prop = PROP_MODE;
+		return parse_mode();
 	else if (token("mtime"))
 		prop = PROP_MTIME;
 	else if (token("size"))
@@ -474,6 +522,8 @@ eval(struct expr *e, struct fileinfo *fi)
 	case EXPR_EQ:
 	case EXPR_GE:
 	case EXPR_GT:
+	case EXPR_ALLSET:
+	case EXPR_ANYSET:
 	{
 		long v = 0;
 		switch (e->a.prop) {
@@ -496,6 +546,8 @@ eval(struct expr *e, struct fileinfo *fi)
 		case EXPR_EQ: return v == e->b.num;
 		case EXPR_GE: return v >= e->b.num;
 		case EXPR_GT: return v > e->b.num;
+		case EXPR_ALLSET: return (v & e->b.num) == e->b.num;
+		case EXPR_ANYSET: return (v & e->b.num) > 0;
 		}
 	}
 	case EXPR_TYPE: