Index: doc/commands.doc
===================================================================
RCS file: /cygdrive/d/cvs_doxygen/doxygen/doxygen/doc/commands.doc,v
retrieving revision 1.2.8.1
diff -u -r1.2.8.1 commands.doc
--- doc/commands.doc	2 Sep 2012 17:45:54 -0000	1.2.8.1
+++ doc/commands.doc	9 Sep 2012 17:46:52 -0000
@@ -1061,7 +1061,7 @@
   for an example.
 
 <hr>
-\section cmdcond \\cond [<section-label>]
+\section cmdcond \\cond [(section-label)]
 
   \addindex \\cond
   Starts a conditional section that ends with a corresponding
@@ -1073,7 +1073,8 @@
   The section between \\cond and \\endcond commands can be included by
   adding its section label to the \ref cfg_enabled_sections "ENABLED_SECTIONS"
   configuration option. If the section label is omitted, the section will
-  be excluded from processing unconditionally.
+  be excluded from processing unconditionally. The section label can be a logical expression
+  build of section names, round brackets, & (AND), | (OR) and ! (NOT).
 
   For conditional sections within a comment block one should
   use a \ref cmdif "\\if" ... \ref cmdendif "\\endif" block.
@@ -1129,7 +1130,7 @@
   \sa section \ref cmdcondnot "\\condnot" and section \ref cmdendcond "\\endcond".
 
 <hr>
-\section cmdcondnot \\condnot <section-label>
+\section cmdcondnot \\condnot [(section-label)]
 
   \addindex \\condnot
   Starts a conditional section that ends with a corresponding
@@ -1140,7 +1141,8 @@
 
   The section between \\condnot and \\endcond commands can be excluded by
   adding its section label to the \ref cfg_enabled_sections "ENABLED_SECTIONS"
-  configuration option.
+  configuration option. The section label can be a logical expression
+  build of section names, round brackets, & (AND), | (OR) and ! (NOT).
 
   For conditional sections within a comment block one should
   use a \ref cmdif "\\if" ... \ref cmdendif "\\endif" block.
@@ -1202,15 +1204,16 @@
       \ref cmdendif "\\endif."
 
 <hr>
-\section cmdelseif \\elseif <section-label>
+\section cmdelseif \\elseif (section-label)
 
   \addindex \\elseif
   Starts a conditional documentation section if the previous section
   was not enabled. A conditional section is
   disabled by default. To enable it you must put the
   section-label after the \ref cfg_enabled_sections "ENABLED_SECTIONS"
-  tag in the configuration
-  file. Conditional blocks can be nested. A nested section is
+  tag in the configuration file.  The section label can be a logical expression
+  build of section names, round brackets, & (AND), | (OR) and ! (NOT).
+  Conditional blocks can be nested. A nested section is
   only enabled if all enclosing sections are enabled as well.
 
   \sa sections \ref cmdendif "\\endif", \ref cmdifnot "\\ifnot",
@@ -1249,15 +1252,16 @@
   example.
 
 <hr>
-\section cmdif \\if <section-label>
+\section cmdif \\if (section-label)
 
   \addindex \\if
   Starts a conditional documentation section. The section ends
   with a matching \c \\endif command. A conditional section is
   disabled by default. To enable it you must put the
   section-label after the \ref cfg_enabled_sections "ENABLED_SECTIONS"
-  tag in the configuration
-  file. Conditional blocks can be nested. A nested section is
+  tag in the configuration file.  The section label can be a logical expression
+  build of section names, round brackets, & (AND), | (OR) and ! (NOT).
+  Conditional blocks can be nested. A nested section is
   only enabled if all enclosing sections are enabled as well.
 
   \par Example:
@@ -1309,15 +1313,15 @@
               \ref cmdelse "\\else", and \ref cmdelseif "\\elseif".
 
 <hr>
-\section cmdifnot \\ifnot <section-label>
+\section cmdifnot \\ifnot (section-label)
 
   \addindex \\ifnot
   Starts a conditional documentation section. The section ends
   with a matching \c \\endif command. This conditional section is
   enabled by default. To disable it you must put the
   section-label after the \ref cfg_enabled_sections "ENABLED_SECTIONS"
-  tag in the configuration
-  file.
+  tag in the configuration file.  The section label can be a logical expression
+  build of section names, round brackets, & (AND), | (OR) and ! (NOT).
 
   \sa sections \ref cmdendif "\\endif", \ref cmdif "\\if",
               \ref cmdelse "\\else", and \ref cmdelseif "\\elseif".
Index: src/commentcnv.l
===================================================================
RCS file: /cygdrive/d/cvs_doxygen/doxygen/doxygen/src/commentcnv.l,v
retrieving revision 1.5.4.2
diff -u -r1.5.4.2 commentcnv.l
--- src/commentcnv.l	3 Sep 2012 17:17:27 -0000	1.5.4.2
+++ src/commentcnv.l	9 Sep 2012 16:40:39 -0000
@@ -178,30 +178,21 @@
 
 static void startCondSection(const char *sectId)
 {
+  CondParser prs;
   g_condStack.push(new CondCtx(g_lineNr,sectId,g_skip));
   if (guardType == Guard_Cond)
   {
-    if (Config_getList("ENABLED_SECTIONS").find(sectId)!=-1)
+    if (prs.parse(sectId,FALSE) != 1)
     {
-      //printf("*** Section is enabled!\n");
-    }
-    else
-    {
-      //printf("*** Section is disabled!\n");
       g_skip=TRUE;
     }
   }
   else if (guardType == Guard_CondNot)
   {
-    if (Config_getList("ENABLED_SECTIONS").find(sectId)!=-1)
+    if (prs.parse(sectId,TRUE) != 1)
     {
-      //printf("*** Section is disabled!\n");
       g_skip=TRUE;
     }
-    else
-    {
-      //printf("*** Section is enabled!\n");
-    }
   }
 }
 
@@ -709,7 +700,7 @@
 				       }
     				     }
 				    }
-<CondLine>[a-z_A-Z][a-z_A-Z0-9.\-]* {
+<CondLine>[!()&| \ta-z_A-Z0-9.\-]+ {
   				     bool oldSkip=g_skip;
                                      startCondSection(yytext);
 				     if (g_condCtx==CComment && !oldSkip && g_skip) 
Index: src/commentscan.l
===================================================================
RCS file: /cygdrive/d/cvs_doxygen/doxygen/doxygen/src/commentscan.l,v
retrieving revision 1.4
diff -u -r1.4 commentscan.l
--- src/commentscan.l	29 Jul 2012 11:30:15 -0000	1.4
+++ src/commentscan.l	9 Sep 2012 16:41:50 -0000
@@ -1724,8 +1724,9 @@
 
   /* ----- handle arguments of if/ifnot commands ------- */
 
-<GuardParam>{LABELID}			{ // parameter of if/ifnot guard
-                                          bool sectionEnabled = Config_getList("ENABLED_SECTIONS").find(yytext)!=-1;
+<GuardParam>[!()&| \ta-z_A-Z0-9.\-]+ {// parameter of if/ifnot guard
+                                          CondParser prs;
+                                          bool sectionEnabled = prs.parse(yytext,FALSE) != 1;
 					  bool parentEnabled = TRUE;
 					  if (!guards.isEmpty()) parentEnabled = guards.top()->isEnabled();
 					  if (parentEnabled)
Index: src/config.xml
===================================================================
RCS file: /cygdrive/d/cvs_doxygen/doxygen/doxygen/src/config.xml,v
retrieving revision 1.4
diff -u -r1.4 config.xml
--- src/config.xml	12 Aug 2012 12:06:56 -0000	1.4
+++ src/config.xml	9 Sep 2012 16:54:39 -0000
@@ -510,7 +510,8 @@
 ' defval='1'/>
     <option type='list' id='ENABLED_SECTIONS' format='string' docs='
 The ENABLED_SECTIONS tag can be used to enable conditional 
-documentation sections, marked by \if sectionname ... \endif. 
+documentation sections, marked by \if section-label ... \endif 
+and \cond section-label ... \endcond blocks. 
 '>
     </option>
     <option type='int' id='MAX_INITIALIZER_LINES' docs='
Index: src/configoptions.cpp
===================================================================
RCS file: /cygdrive/d/cvs_doxygen/doxygen/doxygen/src/configoptions.cpp,v
retrieving revision 1.4
diff -u -r1.4 configoptions.cpp
--- src/configoptions.cpp	12 Aug 2012 19:38:06 -0000	1.4
+++ src/configoptions.cpp	9 Sep 2012 17:03:54 -0000
@@ -730,7 +730,8 @@
   cl = cfg->addList(
                  "ENABLED_SECTIONS",
                  "The ENABLED_SECTIONS tag can be used to enable conditional\n"
-                 "documentation sections, marked by \\if sectionname ... \\endif."
+                 "documentation sections, marked by \\if section-label ... \\endif\n"
+                 "and \\cond section-label ... \\endcond blocks."
                 );
   //----
   ci = cfg->addInt(
Index: src/doxygen.cpp
===================================================================
RCS file: /cygdrive/d/cvs_doxygen/doxygen/doxygen/src/doxygen.cpp,v
retrieving revision 1.5
diff -u -r1.5 doxygen.cpp
--- src/doxygen.cpp	12 Aug 2012 12:06:56 -0000	1.5
+++ src/doxygen.cpp	9 Sep 2012 17:40:42 -0000
@@ -10841,3 +10841,358 @@
   g_successfulRun=TRUE;
 }
 
+/**
+ * C++ Expression parser for EXTABLED_SETIONS in Doxygen
+ *  this parser is based on the parsers as written by Jos de Jong.
+ *
+ * Inforamtion from the original source code:
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * Copyright (C) 2007-2011 Jos de Jong, http://www.speqmath.com
+ *
+ * The parser is based on the example "A mini C++ Interpreter" from the
+ * book "The art of C++" by Herbert Schildt.
+ *
+ * author       Jos de Jong, <wjosdejong@gmail.com>
+ * date         2007-12-22, updated 2012-02-06
+ *
+ */
+
+// declarations
+
+using namespace std;
+
+/**
+ * parses and evaluates the given expression
+ * On error, the variable parse_err is set
+ */
+int CondParser::parse(const char new_expr[], bool negate)
+{
+    expr = new char[strlen(new_expr)+1];
+    token = new char[strlen(new_expr)+1];
+    expr[0] = '\0';
+    token[0] = '\0';
+    token_type = NOTHING;
+    parse_err = 0;
+
+    // initialize all variables
+    strcpy(expr, new_expr);  // copy the given expression to expr
+    e = expr;                                  // let e point to the start of the expression
+    ans = 0;
+
+    getToken();
+    if (token_type == DELIMETER && *token == '\0')
+    {
+        err("Empty expression\n");
+        return 0;
+    }
+
+    ans = parse_level1();
+
+    // check for garbage at the end of the expression
+    // an expression ends with a character '\0' and token_type = delimeter
+    if (token_type != DELIMETER || *token != '\0')
+    {
+        if (token_type == DELIMETER)
+        {
+            // user entered a not existing operator like "//"
+            err("Unknown operator \"%s\"\n", token);
+            return 1;
+        }
+        else
+        {
+            err("Unexpected part \"%s\"\n", token);
+            parse_err = 1;
+            return 1;
+        }
+    }
+
+    delete token;
+    delete expr;
+    if (parse_err != 0) return 1;
+    if (negate) return 1 - ans;
+    return ans;
+}
+
+
+/**
+ * checks if the given char c is a delimeter
+ * minus is checked apart, can be unary minus
+ */
+bool isDelimeter(const char c)
+{
+    if (c == 0) return 0;
+    return strchr("&|^!", c) != 0;
+}
+
+/**
+ * checks if the given char c is a letter or underscore
+ */
+bool isAlpha(const char c)
+{
+    if (c == 0) return 0;
+    return strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ_", toupper(c)) != 0;
+}
+
+/**
+ * Get next token in the current string expr.
+ * Uses the Parser data expr, e, token, t, token_type and parse_err
+ */
+void CondParser::getToken()
+{
+    token_type = NOTHING;
+    char* t;           // points to a character in token
+    t = token;         // let t point to the first character in token
+    *t = '\0';         // set token empty
+
+    //printf("\tgetToken e:{%c}, ascii=%i, col=%i\n", *e, *e, e-expr);
+
+    // skip over whitespaces
+    while (*e == ' ' || *e == '\t')     // space or tab
+    {
+        e++;
+    }
+
+    // check for end of expression
+    if (*e == '\0')
+    {
+        // token is still empty
+        token_type = DELIMETER;
+        return;
+    }
+
+    // check for minus
+    if (*e == '-')
+    {
+        token_type = DELIMETER;
+        *t = *e;
+        e++;
+        t++;
+        *t = '\0';  // add a null character at the end of token
+        return;
+    }
+
+    // check for parentheses
+    if (*e == '(' || *e == ')')
+    {
+        token_type = DELIMETER;
+        *t = *e;
+        e++;
+        t++;
+        *t = '\0';
+        return;
+    }
+
+    // check for operators (delimeters)
+    if (isDelimeter(*e))
+    {
+        token_type = DELIMETER;
+        while (isDelimeter(*e))
+        {
+            *t = *e;
+            e++;
+            t++;
+        }
+        *t = '\0';  // add a null character at the end of token
+        return;
+    }
+
+    // check for variables
+    if (isAlpha(*e))
+    {
+        while (isAlpha(*e))
+        {
+            *t = *e;
+            e++;
+            t++;
+        }
+        *t = '\0';  // add a null character at the end of token
+
+        // check if this is a variable or a function.
+        // a function has a parentesis '(' open after the name
+        char* e2 = NULL;
+        e2 = e;
+
+        // skip whitespaces
+        while (*e2 == ' ' || *e2 == '\t')     // space or tab
+        {
+            e2++;
+        }
+
+        token_type = VARIABLE;
+        return;
+    }
+
+    // something unknown is found, wrong characters -> a syntax error
+    token_type = UNKNOWN;
+    while (*e != '\0')
+    {
+        *t = *e;
+        e++;
+        t++;
+    }
+    *t = '\0';
+    parse_err = 1;
+    err("Syntax error in part \"%s\"\n", token);
+
+    return;
+}
+
+
+/**
+ * conditional operators AND and OR
+ */
+int CondParser::parse_level1()
+{
+    int op_id;
+    int ans;
+    ans = parse_level2();
+
+    op_id = get_operator_id(token);
+    while (op_id == AND || op_id == OR)
+    {
+        getToken();
+        ans = eval_operator(op_id, ans, parse_level2());
+        op_id = get_operator_id(token);
+    }
+
+    return ans;
+}
+
+/**
+ * NOT
+ */
+int CondParser::parse_level2()
+{
+    int ans;
+
+    int op_id = get_operator_id(token);
+    if (op_id == NOT)
+    {
+        getToken();
+        ans = 1 - parse_level3();
+    }
+    else
+    {
+        ans = parse_level3();
+    }
+
+    return ans;
+}
+
+
+/**
+ * parenthesized expression or variable
+ */
+int CondParser::parse_level3()
+{
+    // check if it is a parenthesized expression
+    if (token_type == DELIMETER)
+    {
+        if (token[0] == '(' && token[1] == '\0')
+        {
+            getToken();
+            int ans = parse_level1();
+            if (token_type != DELIMETER || token[0] != ')' || token[1] || '\0')
+            {
+                err("Parentesis ) missing\n");
+                parse_err = 1;
+                return 1;
+            }
+            getToken();
+            return ans;
+        }
+    }
+
+    // if not parenthesized then the expression is a variable
+    return parse_var();
+}
+
+
+int CondParser::parse_var()
+{
+    int ans = 0;
+
+    switch (token_type)
+    {
+        case VARIABLE:
+            // this is a variable
+            ans = eval_variable(token);
+            getToken();
+            break;
+
+        default:
+            // syntax error or unexpected end of expression
+            if (token[0] == '\0')
+            {
+                err("Unexpected end of expression\n");
+                parse_err = 1;
+                return 1;
+            }
+            else
+            {
+                err("Value expected\n");
+                parse_err = 1;
+                return 1;
+            }
+            break;
+    }
+
+    return ans;
+}
+
+
+/**
+ * returns the id of the given operator
+ * returns -1 if the operator is not recognized
+ */
+int CondParser::get_operator_id(const char op_name[])
+{
+    // level 2
+    if (!strcmp(op_name, "&")) {return AND;}
+    if (!strcmp(op_name, "|")) {return OR;}
+
+    // not operator
+    if (!strcmp(op_name, "!")) {return NOT;}
+
+    return UNKNOWN_OP;
+}
+
+
+/**
+ * evaluate an operator for given valuess
+ */
+int CondParser::eval_operator(const int op_id, const int &lhs, const int &rhs)
+{
+    switch (op_id)
+    {
+        // level 2
+        case AND:           return lhs & rhs;
+        case OR:            return lhs | rhs;
+    }
+
+    err("Internal error unknown operator %d\n", op_id);
+    parse_err = 1;
+    return 1;
+}
+
+
+/**
+ * evaluate a variable
+ */
+int CondParser::eval_variable(const char var_name[])
+{
+    if (Config_getList("ENABLED_SECTIONS").find(var_name)==-1) return 0;
+    return 1;
+}
Index: src/doxygen.h
===================================================================
RCS file: /cygdrive/d/cvs_doxygen/doxygen/doxygen/src/doxygen.h,v
retrieving revision 1.2
diff -u -r1.2 doxygen.h
--- src/doxygen.h	12 Aug 2012 12:06:56 -0000	1.2
+++ src/doxygen.h	9 Sep 2012 16:11:29 -0000
@@ -174,5 +174,93 @@
 void copyAndFilterFile(const char *fileName,BufStr &dest);
 
 #define NEWMATCH
+/**
+ *
+ * C++ Expression parser for EXTABLED_SETIONS in Doxygen
+ *  this parser is based on the parsers as written by Jos de Jong.
+ *
+ * Inforamtion from the original source code:
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ * Copyright (C) 2007-2011 Jos de Jong, http://www.speqmath.com
+ *
+ * The parser is based on the example "A mini C++ Interpreter" from the
+ * book "The art of C++" by Herbert Schildt.
+ *
+ * author       Jos de Jong, <wjosdejong@gmail.com>
+ * date         2007-12-22, updated 2012-02-06
+ *
+ *
+ *
+ * Features used:
+ *     Operators:
+ *         &     AND operator
+ *         |     OR  operator
+ *         !     NOT operator
+ */
+
+#ifndef PARSER_H
+#define PARSER_H
+
+// declarations
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+
+using namespace std;
+
+class CondParser
+{
+    // public functions
+    public:
+        int parse(const char expr[], bool negate);
+
+    // enumerations
+    private:
+
+        enum TOKENTYPE {NOTHING = -1, DELIMETER, VARIABLE, UNKNOWN};
+
+        enum OPERATOR_ID {UNKNOWN_OP = -1, AND = 1, OR, NOT}; 
+
+    // data
+    private:
+        int parse_err;                // error state
+        char* expr;                   // holds the expression
+        char* e;                      // points to a character in expr
+
+        char* token;                  // holds the token
+        TOKENTYPE token_type;         // type of the token
+
+        int ans;                      // holds the result of the expression
+        char ans_str[255];            // holds a string containing the result
+                                      // of the expression
+
+    // private functions
+    private:
+        void getToken();
+
+        int parse_level1();
+        int parse_level2();
+        int parse_level3();
+        int parse_var();
+
+        int get_operator_id(const char op_name[]);
+        int eval_operator(const int op_id, const int &lhs, const int &rhs);
+        int eval_variable(const char var_name[]);
+};
+
+#endif
 
 #endif
Index: src/pre.l
===================================================================
RCS file: /cygdrive/d/cvs_doxygen/doxygen/doxygen/src/pre.l,v
retrieving revision 1.1.14.1
diff -u -r1.1.14.1 pre.l
--- src/pre.l	2 Sep 2012 17:46:28 -0000	1.1.14.1
+++ src/pre.l	9 Sep 2012 16:40:29 -0000
@@ -1655,17 +1655,18 @@
 
 static void startCondSection(const char *sectId)
 {
+  CondParser prs;
   g_condStack.push(new bool(g_skip));
   if (guardType == Guard_Cond)
   {
-    if (Config_getList("ENABLED_SECTIONS").find(sectId)==-1)
+    if (prs.parse(sectId,FALSE) != 1)
     {
       g_skip=TRUE;
     }
   }
   else if (guardType == Guard_CondNot)
   {
-    if (Config_getList("ENABLED_SECTIONS").find(sectId)!=-1)
+    if (prs.parse(sectId,TRUE) != 1)
     {
       g_skip=TRUE;
     }
@@ -2477,7 +2478,7 @@
   					  outputArray(yytext,yyleng);
   					  BEGIN(CondLine);
   					}
-<CondLine>[a-z_A-Z][a-z_A-Z0-9.\-]*	{
+<CondLine>[!()&| \ta-z_A-Z0-9.\-]+      {
   				          startCondSection(yytext);
   					  outputArray(yytext,yyleng);
   					  BEGIN(g_condCtx);
