Quash various warnings from higher levels of compiler warnings.
[ircu2.10.12-pk.git] / ircd / crule.c
index 5fd660dba3d7b95bd2fadf636e6b57ff977abcc7..a91aecb41b76021a64c7b5be61e1d4859b05a899 100644 (file)
@@ -1,9 +1,11 @@
-/*
- * SmartRoute phase 1
- * connection rule patch
+/**
+ * @file
+ * @brief Connection rule parser and checker
+ * @version $Id$
+ *
  * by Tony Vencill (Tonto on IRC) <vencill@bga.com>
  *
- * The majority of this file is a recusive descent parser used to convert
+ * The majority of this file is a recursive descent parser used to convert
  * connection rules into expression trees when the conf file is read.
  * All parsing structures and types are hidden in the interest of good
  * programming style and to make possible future data structure changes
  * the rule functions are made empty functions as in the stand-alone
  * test parser.
  *
- * $Id$
+ * The production rules for the grammar are as follows ("rule" is the
+ * starting production):
+ *
+ *   rule:
+ *     orexpr END          END is end of input or :
+ *   orexpr:
+ *     andexpr
+ *     andexpr || orexpr
+ *   andexpr:
+ *     primary
+ *     primary && andexpr
+ *  primary:
+ *    function
+ *    ! primary
+ *    ( orexpr )
+ *  function:
+ *    word ( )             word is alphanumeric string, first character
+ *    word ( arglist )       must be a letter
+ *  arglist:
+ *    word
+ *    word , arglist
  */
 #include "config.h"
 
@@ -63,7 +85,7 @@
         strcpy(x,y); \
         } while(0)
 
-/* We don't care about collation discrepacies here, it seems.... */
+/* We don't care about collation discrepancies here, it seems.... */
 #define ircd_strcmp strcasecmp
 
 #endif
 #endif
 
 /* some constants and shared data types */
-#define CR_MAXARGLEN 80         /* why 80? why not? it's > hostname lengths */
-#define CR_MAXARGS 3            /* There's a better way to do this,
-                                   but not now. */
+#define CR_MAXARGLEN 80         /**< Maximum arg length (must be > HOSTLEN) */
+#define CR_MAXARGS 3            /**< Maximum number of args for a rule */
 
 /*
  * Some symbols for easy reading
  */
 
+/** Input scanner tokens. */
 enum crule_token {
-  CR_UNKNOWN, CR_END, CR_AND, CR_OR, CR_NOT, CR_OPENPAREN, CR_CLOSEPAREN,
-  CR_COMMA, CR_WORD
+  CR_UNKNOWN,    /**< Unknown token type. */
+  CR_END,        /**< End of input ('\\0' or ':'). */
+  CR_AND,        /**< Logical and operator (&&). */
+  CR_OR,         /**< Logical or operator (||). */
+  CR_NOT,        /**< Logical not operator (!). */
+  CR_OPENPAREN,  /**< Open parenthesis. */
+  CR_CLOSEPAREN, /**< Close parenthesis. */
+  CR_COMMA,      /**< Comma. */
+  CR_WORD        /**< Something that looks like a hostmask (alphanumerics, "*?.-"). */
 };
 
+/** Parser error codes. */
 enum crule_errcode {
-  CR_NOERR, CR_UNEXPCTTOK, CR_UNKNWTOK, CR_EXPCTAND, CR_EXPCTOR,
-  CR_EXPCTPRIM, CR_EXPCTOPEN, CR_EXPCTCLOSE, CR_UNKNWFUNC, CR_ARGMISMAT
+  CR_NOERR,      /**< No error. */
+  CR_UNEXPCTTOK, /**< Invalid token given context. */
+  CR_UNKNWTOK,   /**< Input did not form a valid token. */
+  CR_EXPCTAND,   /**< Did not see expected && operator. */
+  CR_EXPCTOR,    /**< Did not see expected || operator. */
+  CR_EXPCTPRIM,  /**< Expected a primitive (parentheses, ! or word). */
+  CR_EXPCTOPEN,  /**< Expected an open parenthesis after function name. */
+  CR_EXPCTCLOSE, /**< Expected a close parenthesis to match open parenthesis. */
+  CR_UNKNWFUNC,  /**< Attempt to use an unknown function. */
+  CR_ARGMISMAT   /**< Wrong number of arguments to function. */
 };
 
 /*
  * Expression tree structure, function pointer, and tree pointer local!
  */
+/** Evaluation function for a connection rule. */
 typedef int (*crule_funcptr) (int, void **);
 
+/** Node in a connection rule tree. */
 struct CRuleNode {
-  crule_funcptr funcptr;
-  int numargs;
-  void *arg[CR_MAXARGS];        /* For operators arg points to a tree element;
-                                   for functions arg points to a char string. */
+  crule_funcptr funcptr; /**< Evaluation function for this node. */
+  int numargs;           /**< Number of arguments. */
+  void *arg[CR_MAXARGS]; /**< Array of arguments.  For operators, each arg
+                            is a tree element; for functions, each arg is
+                            a string. */
 };
 
+/** Typedef to save typing effort. */
 typedef struct CRuleNode* CRuleNodePtr;
 
 /* local rule function prototypes */
-static int crule_connected(int, void **);
-static int crule_directcon(int, void **);
-static int crule_via(int, void **);
-static int crule_directop(int, void **);
-static int crule__andor(int, void **);
-static int crule__not(int, void **);
+static int crule_connected(int, void *[]);
+static int crule_directcon(int, void *[]);
+static int crule_via(int, void *[]);
+static int crule_directop(int, void *[]);
+static int crule__andor(int, void *[]);
+static int crule__not(int, void *[]);
 
 /* local parsing function prototypes */
 static int crule_gettoken(int* token, const char** str);
@@ -142,7 +184,7 @@ void print_tree(CRuleNodePtr);
 #endif
 #endif
 
-/* error messages */
+/** Error messages, indexed by the corresponding crule_errcode. */
 char *crule_errstr[] = {
   "Unknown error",              /* NOERR? - for completeness */
   "Unexpected token",           /* UNEXPCTTOK */
@@ -156,13 +198,14 @@ char *crule_errstr[] = {
   "Argument mismatch"           /* ARGMISMAT */
 };
 
-/* function table - null terminated */
+/** Connection rule function table entry. */
 struct crule_funclistent {
-  char name[15];                /* MAXIMUM FUNCTION NAME LENGTH IS 14 CHARS!! */
-  int reqnumargs;
-  crule_funcptr funcptr;
+  char name[15];         /**< Function name. */
+  int reqnumargs;        /**< Required number of arguments. */
+  crule_funcptr funcptr; /**< Handler function. */
 };
 
+/** Defined connection rules. */
 struct crule_funclistent crule_funclist[] = {
   /* maximum function name length is 14 chars */
   {"connected", 1, crule_connected},
@@ -172,32 +215,37 @@ struct crule_funclistent crule_funclist[] = {
   {"", 0, NULL}                 /* this must be here to mark end of list */
 };
 
-#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+/** Check whether any connected server matches crulearg[0].
+ * @param[in] numargs Number of valid args in \a crulearg.
+ * @param[in] crulearg Argument array.
+ * @return Non-zero if the condition is true, zero if not.
+ */
 static int crule_connected(int numargs, void *crulearg[])
 {
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
   struct Client *acptr;
 
   /* taken from m_links */
   for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
   {
-    if (!IsServer(acptr) && !IsMe(acptr))
+    if (!IsServer(acptr) || IsMe(acptr))
       continue;
     if (match((char *)crulearg[0], cli_name(acptr)))
       continue;
     return (1);
   }
+#endif
   return (0);
 }
-#else
-static int crule_connected(int numargs, void **crulearg)
-{
-  return (0);
-}
-#endif
 
-#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+/** Check whether any directly connected server matches crulearg[0].
+ * @param[in] numargs Number of valid args in \a crulearg.
+ * @param[in] crulearg Argument array.
+ * @return Non-zero if the condition is true, zero if not.
+ */
 static int crule_directcon(int numargs, void *crulearg[])
 {
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
   int i;
   struct Client *acptr;
 
@@ -210,42 +258,42 @@ static int crule_directcon(int numargs, void *crulearg[])
       continue;
     return (1);
   }
+#endif
   return (0);
 }
-#else
-static int crule_directcon(int numargs, void **crulearg)
-{
-  return (0);
-}
-#endif
 
-#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
+/** Check whether a connected server matching crulearg[1] is
+ * connnected to me behind one matching crulearg[0].
+ * @param[in] numargs Number of valid args in \a crulearg.
+ * @param[in] crulearg Argument array.
+ * @return Non-zero if the condition is true, zero if not.
+ */
 static int crule_via(int numargs, void *crulearg[])
 {
+#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
   struct Client *acptr;
 
   /* adapted from m_links */
   for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
   {
-    if (!IsServer(acptr) && !IsMe(acptr))
+    if (!IsServer(acptr) || IsMe(acptr))
       continue;
     if (match((char *)crulearg[1], cli_name(acptr)))
       continue;
-    if (match((char *)crulearg[0],
-             cli_name(LocalClientArray[cli_fd(cli_from(acptr))])))
+    if (match((char *)crulearg[0], cli_name(cli_from(acptr))))
       continue;
     return (1);
   }
+#endif
   return (0);
 }
-#else
-static int crule_via(int numargs, void **crulearg)
-{
-  return (0);
-}
-#endif
 
-static int crule_directop(int numargs, void **crulearg)
+/** Check whether we have a local IRC operator.
+ * @param[in] numargs Number of valid args in \a crulearg.
+ * @param[in] crulearg Argument array.
+ * @return Non-zero if the condition is true, zero if not.
+ */
+static int crule_directop(int numargs, void *crulearg[])
 {
 #if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
   int i;
@@ -262,39 +310,47 @@ static int crule_directop(int numargs, void **crulearg)
   return (0);
 }
 
+/** Evaluate a connection rule.
+ * @param[in] rule Rule to evalute.
+ * @return Non-zero if the rule allows the connection, zero otherwise.
+ */
+int crule_eval(struct CRuleNode* rule)
+{
+  return (rule->funcptr(rule->numargs, rule->arg));
+}
+
+/** Perform an and-or-or test on crulearg[0] and crulearg[1].
+ * If crulearg[2] is non-NULL, it means do OR; if it is NULL, do AND.
+ * @param[in] numargs Number of valid args in \a crulearg.
+ * @param[in] crulearg Argument array.
+ * @return Non-zero if the condition is true, zero if not.
+ */
 static int crule__andor(int numargs, void *crulearg[])
 {
   int result1;
 
-  result1 = ((CRuleNodePtr) crulearg[0])->funcptr
-      (((CRuleNodePtr) crulearg[0])->numargs,
-      ((CRuleNodePtr) crulearg[0])->arg);
+  result1 = crule_eval(crulearg[0]);
   if (crulearg[2])              /* or */
-    return (result1 ||
-        ((CRuleNodePtr) crulearg[1])->funcptr
-        (((CRuleNodePtr) crulearg[1])->numargs,
-        ((CRuleNodePtr) crulearg[1])->arg));
+    return (result1 || crule_eval(crulearg[1]));
   else
-    return (result1 &&
-        ((CRuleNodePtr) crulearg[1])->funcptr
-        (((CRuleNodePtr) crulearg[1])->numargs,
-        ((CRuleNodePtr) crulearg[1])->arg));
+    return (result1 && crule_eval(crulearg[1]));
 }
 
+/** Logically invert the result of crulearg[0].
+ * @param[in] numargs Number of valid args in \a crulearg.
+ * @param[in] crulearg Argument array.
+ * @return Non-zero if the condition is true, zero if not.
+ */
 static int crule__not(int numargs, void *crulearg[])
 {
-  return (!((CRuleNodePtr) crulearg[0])->funcptr
-      (((CRuleNodePtr) crulearg[0])->numargs,
-      ((CRuleNodePtr) crulearg[0])->arg));
-}
-
-#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
-int crule_eval(struct CRuleNode* rule)
-{
-  return (rule->funcptr(rule->numargs, rule->arg));
+  return (!crule_eval(crulearg[0]));
 }
-#endif
 
+/** Scan an input token from \a ruleptr.
+ * @param[out] next_tokp Receives type of next token.
+ * @param[in,out] ruleptr Next readable character from input.
+ * @return Either CR_UNKNWTOK if the input was unrecognizable, else CR_NOERR.
+ */
 static int crule_gettoken(int* next_tokp, const char** ruleptr)
 {
   char pending = '\0';
@@ -352,6 +408,12 @@ static int crule_gettoken(int* next_tokp, const char** ruleptr)
   return CR_NOERR;
 }
 
+/** Scan a word from \a ruleptr.
+ * @param[out] word Output buffer.
+ * @param[out] wordlenp Length of word written to \a word (not including terminating NUL).
+ * @param[in] maxlen Maximum number of bytes writable to \a word.
+ * @param[in,out] ruleptr Next readable character from input.
+ */
 static void crule_getword(char* word, int* wordlenp, size_t maxlen, const char** ruleptr)
 {
   char *word_ptr;
@@ -366,26 +428,9 @@ static void crule_getword(char* word, int* wordlenp, size_t maxlen, const char**
   *wordlenp = word_ptr - word;
 }
 
-/*
- * Grammar
- *   rule:
- *     orexpr END          END is end of input or :
- *   orexpr:
- *     andexpr
- *     andexpr || orexpr
- *   andexpr:
- *     primary
- *     primary && andexpr
- *  primary:
- *    function
- *    ! primary
- *    ( orexpr )
- *  function:
- *    word ( )             word is alphanumeric string, first character
- *    word ( arglist )       must be a letter
- *  arglist:
- *    word
- *    word , arglist
+/** Parse an entire rule.
+ * @param[in] rule Text form of rule.
+ * @return CRuleNode for rule, or NULL if there was a parse error.
  */
 struct CRuleNode* crule_parse(const char *rule)
 {
@@ -416,6 +461,12 @@ struct CRuleNode* crule_parse(const char *rule)
   return 0;
 }
 
+/** Parse an or expression.
+ * @param[out] orrootp Receives parsed node.
+ * @param[in,out] next_tokp Next input token type.
+ * @param[in,out] ruleptr Next input character.
+ * @return A crule_errcode value.
+ */
 static int crule_parseorexpr(CRuleNodePtr * orrootp, int *next_tokp, const char** ruleptr)
 {
   int errcode = CR_NOERR;
@@ -471,6 +522,12 @@ static int crule_parseorexpr(CRuleNodePtr * orrootp, int *next_tokp, const char*
   return (errcode);
 }
 
+/** Parse an and expression.
+ * @param[out] androotp Receives parsed node.
+ * @param[in,out] next_tokp Next input token type.
+ * @param[in,out] ruleptr Next input character.
+ * @return A crule_errcode value.
+ */
 static int crule_parseandexpr(CRuleNodePtr * androotp, int *next_tokp, const char** ruleptr)
 {
   int errcode = CR_NOERR;
@@ -526,6 +583,12 @@ static int crule_parseandexpr(CRuleNodePtr * androotp, int *next_tokp, const cha
   return (errcode);
 }
 
+/** Parse a primary expression.
+ * @param[out] primrootp Receives parsed node.
+ * @param[in,out] next_tokp Next input token type.
+ * @param[in,out] ruleptr Next input character.
+ * @return A crule_errcode value.
+ */
 static int crule_parseprimary(CRuleNodePtr* primrootp, int *next_tokp, const char** ruleptr)
 {
   CRuleNodePtr *insertionp;
@@ -581,6 +644,12 @@ static int crule_parseprimary(CRuleNodePtr* primrootp, int *next_tokp, const cha
   return (errcode);
 }
 
+/** Parse a function call.
+ * @param[out] funcrootp Receives parsed node.
+ * @param[in,out] next_tokp Next input token type.
+ * @param[in,out] ruleptr Next input character.
+ * @return A crule_errcode value.
+ */
 static int crule_parsefunction(CRuleNodePtr* funcrootp, int* next_tokp, const char** ruleptr)
 {
   int errcode = CR_NOERR;
@@ -625,6 +694,12 @@ static int crule_parsefunction(CRuleNodePtr* funcrootp, int* next_tokp, const ch
     return (CR_EXPCTOPEN);
 }
 
+/** Parse the argument list to a CRuleNode.
+ * @param[in,out] argrootp Node whos argument list is being populated.
+ * @param[in,out] next_tokp Next input token type.
+ * @param[in,out] ruleptr Next input character.
+ * @return A crule_errcode value.
+ */
 static int crule_parsearglist(CRuleNodePtr argrootp, int *next_tokp, const char** ruleptr)
 {
   int errcode = CR_NOERR;
@@ -662,7 +737,7 @@ static int crule_parsearglist(CRuleNodePtr argrootp, int *next_tokp, const char*
 #if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
         collapse(currarg);
 #endif
-        if (!BadPtr(currarg))
+        if (currarg[0] != '\0')
         {
           DupString(argelemp, currarg);
           argrootp->arg[argrootp->numargs++] = (void *)argelemp;
@@ -679,9 +754,12 @@ static int crule_parsearglist(CRuleNodePtr argrootp, int *next_tokp, const char*
 
 /*
  * This function is recursive..  I wish I knew a nonrecursive way but
- * I dont.  anyway, recursion is fun..  :)
- * DO NOT CALL THIS FUNTION WITH A POINTER TO A NULL POINTER
- * (ie: If *elem is NULL, you're doing it wrong - seg fault)
+ * I don't.  Anyway, recursion is fun..  :)
+ * DO NOT CALL THIS FUNCTION WITH A POINTER TO A NULL POINTER
+ * (i.e.: If *elem is NULL, you're doing it wrong - seg fault)
+ */
+/** Free a connection rule and all its children.
+ * @param[in,out] elem Pointer to pointer to element to free.  MUST NOT BE NULL.
  */
 void crule_free(struct CRuleNode** elem)
 {
@@ -689,7 +767,7 @@ void crule_free(struct CRuleNode** elem)
 
   if ((*(elem))->funcptr == crule__not)
   {
-    /* type conversions and ()'s are fun! ;)  here have an asprin.. */
+    /* type conversions and ()'s are fun! ;)  here have an aspirin.. */
     if ((*(elem))->arg[0] != NULL)
       crule_free((struct CRuleNode**) &((*(elem))->arg[0]));
   }
@@ -713,6 +791,9 @@ void crule_free(struct CRuleNode** elem)
 }
 
 #ifdef CR_DEBUG
+/** Display a connection rule as text.
+ * @param[in] printelem Connection rule to display.
+ */
 static void print_tree(CRuleNodePtr printelem)
 {
   int funcnum, arg;
@@ -757,6 +838,9 @@ static void print_tree(CRuleNodePtr printelem)
 #endif
 
 #ifdef CR_DEBUG
+/** Read connection rules from stdin and display parsed forms as text.
+ * @return Zero.
+ */
 int main(void)
 {
   char indata[256];