diff --git a/Makefile b/Makefile index 468417a..1cf4f31 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,10 @@ ifeq ($(INSTALL_PREFIX),) INSTALL_PREFIX := /usr/local endif +ifdef DEBUG +CFLAGS += -DDEBUG +endif + include $(BASE)/Makefile.shared include $(BASE)/gen/Makefile.env include $(BASE)/src/Makefile.env diff --git a/Makefile.shared b/Makefile.shared index 9e3d74f..d3a45f3 100644 --- a/Makefile.shared +++ b/Makefile.shared @@ -15,4 +15,8 @@ ifeq ($(PLATFORM), Darwin) CFLAGS += -mmacosx-version-min=10.9 endif +ifdef DEBUG +CFLAGS += -DDEBUG +endif + endif \ No newline at end of file diff --git a/src/AST/Validation/Command.cc b/src/AST/Validation/Command.cc index 54199a0..5d381b0 100644 --- a/src/AST/Validation/Command.cc +++ b/src/AST/Validation/Command.cc @@ -1,7 +1,9 @@ +#include "ASTBlock.hh" #include "ASTNumeric.hh" #include "ASTString.hh" #include "ASTStringList.hh" #include "ASTTag.hh" +#include "checksieve.h" #include "Command.hh" namespace sieve @@ -325,14 +327,57 @@ bool validateSingleArgumentCommand(const ASTNode *node) { return false; } +bool validateBreakCommand(const ASTNode *node) { + const ASTCommand *command = dynamic_cast(node); + size_t size = command->children().size(); + + if (size == 0) + return true; + + if (size != 2) + return false; + + const ASTTag *tagChild = dynamic_cast(command->children()[0]); + const ASTString *stringChild = dynamic_cast(command->children()[1]); + + if (tagChild == NULL || stringChild == NULL) + return false; + + return true; +} + +bool validateForeverypartCommand(const ASTNode *node) { + const ASTCommand *command = dynamic_cast(node); + size_t size = command->children().size(); + + if (size != 1 && size != 3) + return false; + + const ASTBlock *blockChild = dynamic_cast(command->children()[size-1]); + if (blockChild == NULL) + return false; + + if (size == 3) { + const ASTTag *tagChild = dynamic_cast(command->children()[0]); + const ASTString *stringChild = dynamic_cast(command->children()[1]); + + if (tagChild == NULL || stringChild == NULL) + return false; + } + + return true; +} + Command::Command() { _usage_map["addflag"] = "addflag [] "; _usage_map["addheader"] = "addheader [:last] "; + _usage_map["break"] = "break [:name string]"; _usage_map["deleteheader"] = "deleteheader [:index [:last]]\n\t[COMPARATOR] [MATCH-TYPE]\n\t\n\t[]"; _usage_map["discard"] = "discard"; _usage_map["enclose"] = "enclose <:subject string> <:headers string-list> string"; _usage_map["ereject"] = "ereject "; _usage_map["fileinto"] = "fileinto [:flags ][:copy] "; + _usage_map["foreverypart"] = "foreverypart [:name string] block"; _usage_map["global"] = "global "; _usage_map["include"] = "include [:global / :personal] [:once] [:optional] "; _usage_map["keep"] = "keep [:flags ]"; @@ -348,11 +393,13 @@ Command::Command() { _validation_fn_map["addflag"] = &validateIMAP4FlagsAction; _validation_fn_map["addheader"] = &validateAddHeadersCommand; + _validation_fn_map["break"] = &validateBreakCommand; _validation_fn_map["deleteheader"] = &validateDeleteHeadersCommand; _validation_fn_map["discard"] = &validateBareCommand; _validation_fn_map["enclose"] = &validateEncloseCommand; _validation_fn_map["ereject"] = &validateSingleArgumentCommand; _validation_fn_map["fileinto"] = &validateFileintoCommand; + _validation_fn_map["foreverypart"] = &validateForeverypartCommand; _validation_fn_map["global"] = &validateSingleArgumentCommand; _validation_fn_map["include"] = &validateIncludeCommand; _validation_fn_map["keep"] = &validateKeepCommand; @@ -368,8 +415,10 @@ Command::Command() { } bool Command::validate(const ASTCommand *command) { - if (!_validation_fn_map[command->value()]) + if (!_validation_fn_map[command->value()]) { + DEBUGLOG(command->value(), "Command is missing validation.") return true; + } return _validation_fn_map[command->value()](command); } diff --git a/src/AST/Validation/Test.cc b/src/AST/Validation/Test.cc index b73615a..2f50e2d 100644 --- a/src/AST/Validation/Test.cc +++ b/src/AST/Validation/Test.cc @@ -3,6 +3,7 @@ #include "ASTString.hh" #include "ASTStringList.hh" #include "ASTTag.hh" +#include "checksieve.h" #include "Test.hh" namespace sieve { @@ -104,8 +105,10 @@ Test::Test() { } bool Test::validate(const ASTTest *test) { - if (!_validation_fn_map[test->value()]) + if (!_validation_fn_map[test->value()]) { + DEBUGLOG(test->value(), "Test is missing validation.") return true; + } return _validation_fn_map[test->value()](test); } diff --git a/src/checksieve.h b/src/checksieve.h index e3389df..b14ae84 100644 --- a/src/checksieve.h +++ b/src/checksieve.h @@ -7,6 +7,12 @@ #endif #endif +#ifdef DEBUG +#define DEBUGLOG(i, x) std::cout << "DEBUG: " << i << ": "<< x << std::endl; +#else +#define DEBUGLOG(i, x) +#endif + #include #include "location.hh" diff --git a/test/5703/actions_test.py b/test/5703/actions_test.py index 6c9858c..f8a406d 100644 --- a/test/5703/actions_test.py +++ b/test/5703/actions_test.py @@ -7,13 +7,17 @@ def test_foreverypart(self): sieve = ''' require ["foreverypart"]; - foreverypart { } + foreverypart { + discard; + } ''' self.assertFalse(checksieve.parse_string(sieve, False)) def test_foreverypart_no_require(self): sieve = ''' - foreverypart { } + foreverypart { + discard; + } ''' self.assertTrue(checksieve.parse_string(sieve, True)) @@ -22,7 +26,7 @@ def test_foreverypart_with_name(self): require "foreverypart"; foreverypart :name "Cc" { - + discard; } ''' self.assertFalse(checksieve.parse_string(sieve, False))