about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--README.md12
-rw-r--r--lr.112
-rw-r--r--lr.c19
3 files changed, 31 insertions, 12 deletions
diff --git a/README.md b/README.md
index b9d3d1a..9fcebb8 100644
--- a/README.md
+++ b/README.md
@@ -175,12 +175,12 @@ Default: `n`.
 	
 	<strprop>  ::= fstype | group | name | path | target | user | xattr
 	
-	<strop>    ::= == | =            -- string equality
-	             | ===               -- case insensitive string equality
-	             | ~~                -- glob (fnmatch)
-	             | ~~~               -- case insensitive glob (fnmatch)
-	             | =~                -- POSIX Extended Regular Expressions
-	             | =~~               -- case insensitive POSIX Extended Regular Expressions
+	<strop>    ::= == | = | !=       -- string (in)equality
+	             | ===    | !===     -- case insensitive string (in)equality
+	             | ~~     | !~~      -- glob (fnmatch)
+	             | ~~~    | !~~~     -- case insensitive glob (fnmatch)
+	             | =~     | !=~ | !~ -- POSIX Extended Regular Expressions
+	             | =~~    | !=~~     -- case insensitive POSIX Extended Regular Expressions
 	
 	<str>      ::= " ([^"] | "")+ "  -- use "" for a single " inside "
 	             | $[A-Za-z0-9_]     -- environment variable
diff --git a/lr.1 b/lr.1
index b175b34..4a45a75 100644
--- a/lr.1
+++ b/lr.1
@@ -310,12 +310,12 @@ tests are given by the following EBNF:
 
 <strprop>  ::= fstype | group | name | path | target | user | xattr
 
-<strop>    ::= == | =            -- string equality
-             | ===               -- case insensitive string equality
-             | ~~                -- glob (fnmatch)
-             | ~~~               -- case insensitive glob (fnmatch)
-             | =~                -- POSIX Extended Regular Expressions
-             | =~~               -- case insensitive POSIX Extended Regular Expressions
+<strop>    ::= == | = | !=       -- string (in)equality
+             | ===    | !===     -- case insensitive string (in)equality
+             | ~~     | !~~      -- glob (fnmatch)
+             | ~~~    | !~~~     -- case insensitive glob (fnmatch)
+             | =~     | !=~ | !~ -- POSIX Extended Regular Expressions
+             | =~~    | !=~~     -- case insensitive POSIX Extended Regular Expressions
 
 <str>      ::= " ([^"] | "")+ "  -- use "" for a single " inside "
              | $[A-Za-z0-9_]+    -- environment variable
diff --git a/lr.c b/lr.c
index a92dcb8..00b6454 100644
--- a/lr.c
+++ b/lr.c
@@ -604,6 +604,7 @@ parse_strcmp()
 {
 	enum prop prop;
 	enum op op;
+	int negate = 0;
 
 	if (token("fstype"))
 		prop = PROP_FSTYPE;
@@ -636,6 +637,18 @@ parse_strcmp()
 		op = EXPR_STREQ;
 	else if (token("="))
 		op = EXPR_STREQ;
+	else if (token("!~~~"))
+		negate = 1, op = EXPR_GLOBI;
+	else if (token("!~~"))
+		negate = 1, op = EXPR_GLOB;
+	else if (token("!=~~"))
+		negate = 1, op = EXPR_REGEXI;
+	else if (token("!=~") || token("!~"))
+		negate = 1, op = EXPR_REGEX;
+	else if (token("!==="))
+		negate = 1, op = EXPR_STREQI;
+	else if (token("!==") || token("!="))
+		negate = 1, op = EXPR_STREQ;
 	else
 		parse_error("invalid string operator at '%.15s'", pos);
 
@@ -661,6 +674,12 @@ parse_strcmp()
 			exit(2);
 		}
 
+		if (negate) {
+			struct expr *not = mkexpr(EXPR_NOT);
+			not->a.expr = e;
+			return not;
+		}
+
 		return e;
 	}