]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Move option name parsing into its own function. Use parse_cshl to parse colon-seper...
authorTed Lemon <source@isc.org>
Mon, 20 Apr 1998 18:05:19 +0000 (18:05 +0000)
committerTed Lemon <source@isc.org>
Mon, 20 Apr 1998 18:05:19 +0000 (18:05 +0000)
server/confpars.c

index 9fef50f13f48fb11e89beed5cb38b41a0ce69025..909121b0d3a45b7c325fc4fd33d3da3275badda5 100644 (file)
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: confpars.c,v 1.49 1998/04/09 04:38:24 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: confpars.c,v 1.50 1998/04/20 18:05:19 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -886,74 +886,16 @@ void parse_option_param (cfile, group)
        char *val;
        int token;
        unsigned char buf [4];
-       char *vendor;
+       int len;
+       unsigned char *ob;
        char *fmt;
-       struct universe *universe;
        struct option *option;
        struct tree *tree = (struct tree *)0;
        struct tree *t;
 
-       token = next_token (&val, cfile);
-       if (!is_identifier (token)) {
-               parse_warn ("expecting identifier after option keyword.");
-               if (token != SEMI)
-                       skip_to_semi (cfile);
+       option = parse_option_name (cfile);
+       if (!option)
                return;
-       }
-       vendor = malloc (strlen (val) + 1);
-       if (!vendor)
-               error ("no memory for vendor token.");
-       strcpy (vendor, val);
-       token = peek_token (&val, cfile);
-       if (token == DOT) {
-               /* Go ahead and take the DOT token... */
-               token = next_token (&val, cfile);
-
-               /* The next token should be an identifier... */
-               token = next_token (&val, cfile);
-               if (!is_identifier (token)) {
-                       parse_warn ("expecting identifier after '.'");
-                       if (token != SEMI)
-                               skip_to_semi (cfile);
-                       return;
-               }
-
-               /* Look up the option name hash table for the specified
-                  vendor. */
-               universe = ((struct universe *)
-                           hash_lookup (&universe_hash,
-                                        (unsigned char *)vendor, 0));
-               /* If it's not there, we can't parse the rest of the
-                  declaration. */
-               if (!universe) {
-                       parse_warn ("no vendor named %s.", vendor);
-                       skip_to_semi (cfile);
-                       return;
-               }
-       } else {
-               /* Use the default hash table, which contains all the
-                  standard dhcp option names. */
-               val = vendor;
-               universe = &dhcp_universe;
-       }
-
-       /* Look up the actual option info... */
-       option = ((struct option *)
-                 hash_lookup (universe -> hash, (unsigned char *)val, 0));
-
-       /* If we didn't get an option structure, it's an undefined option. */
-       if (!option) {
-               if (val == vendor)
-                       parse_warn ("no option named %s", val);
-               else
-                       parse_warn ("no option named %s for vendor %s",
-                                   val, vendor);
-               skip_to_semi (cfile);
-               return;
-       }
-
-       /* Free the initial identifier token. */
-       free (vendor);
 
        token = peek_token (&val, cfile);
        if (token == SEMI) {
@@ -980,22 +922,10 @@ void parse_option_param (cfile, group)
                                token = peek_token (&val, cfile);
                                if (token == NUMBER_OR_NAME ||
                                    token == NUMBER) {
-                                       do {
-                                               token = next_token
-                                                       (&val, cfile);
-                                               if (token != NUMBER
-                                                   && token != NUMBER_OR_NAME)
-                                                       goto need_number;
-                                               convert_num (buf, val, 16, 8);
-                                               tree = tree_concat
-                                                       (tree,
-                                                        tree_const (buf, 1));
-                                               token = peek_token
-                                                       (&val, cfile);
-                                               if (token == COLON)
-                                                       token = next_token
-                                                               (&val, cfile);
-                                       } while (token == COLON);
+                                       ob = parse_cshl (cfile, &len);
+                                       tree = tree_concat (tree,
+                                                           tree_const (ob,
+                                                                       len));
                                } else if (token == STRING) {
                                        token = next_token (&val, cfile);
                                        tree = tree_concat
@@ -1362,4 +1292,371 @@ void parse_address_range (cfile, subnet)
        new_address_range (low, high, subnet, dynamic);
 }
 
+struct match_expr *parse_boolean_expression (cfile, lose)
+       FILE *cfile;
+       int *lose;
+{
+       int token;
+       char *val;
+       struct collection *col;
+       struct match_expr buf, *rv;
+       struct match_expr *left, *right;
+
+       token = peek_token (&val, cfile);
+
+       /* Check for unary operators... */
+       switch (token) {
+             case CHECK:
+               token = next_token (&val, cfile);
+               token = next_token (&val, cfile);
+               if (token != STRING) {
+                       parse_warn ("string expected.");
+                       skip_to_semi (cfile);
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+               for (col = collections; col; col = col -> next)
+                       if (!strcmp (col -> name, val))
+                               break;
+               if (!col) {
+                       parse_warn ("unknown collection.");
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+               buf.op = match_check;
+               buf.data.check = col;
+               goto have_expr;
+
+             case NOT:
+               token = next_token (&val, cfile);
+               buf.op = match_not;
+               buf.data.not = parse_boolean_expression (cfile, lose);
+               if (!buf.data.not) {
+                       if (!*lose) {
+                               parse_warn ("match expression expected");
+                               skip_to_semi (cfile);
+                       }
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+               goto have_expr;
+       }
+
+       /* If we're going to find an expression at this point, it must
+          involve a binary operator seperating two subexpressions. */
+       left = parse_data_expression (cfile, lose);
+       if (!left)
+               return left;
+       token = peek_token (&val, cfile);
+       switch (token) {
+             case EQUAL:
+               buf.op = match_equal;
+               break;
+             case AND:
+               buf.op = match_and;
+               break;
+             case OR:
+               buf.op = match_or;
+               break;
+             default:
+               parse_warn ("Expecting a boolean expression.");
+               skip_to_semi (cfile);
+               *lose = 1;
+               return;
+       }
+       token = next_token (&val, cfile);
+
+       /* Now find the RHS of the expression. */
+       right = parse_data_expression (cfile, lose);
+       if (!right) {
+               if (!*lose) {
+                       if (buf.op == match_equal)
+                               parse_warn ("Expecting a data expression.");
+                       else
+                               parse_warn ("Expecting a boolean expression.");
+                       skip_to_semi (cfile);
+               }
+               return right;
+       }
+
+       /* Store the LHS and RHS. */
+       buf.data.equal [0] = left;
+       buf.data.equal [1] = right;
+
+      have_expr:
+       rv = (struct match_expr *)dmalloc (sizeof (struct match_expr),
+                                          "parse_boolean_expression");
+       if (!rv)
+               error ("No memory for boolean expression.");
+       *rv = buf;
+       return rv;
+}      
+
+struct match_expr *parse_data_expression (cfile, lose)
+       FILE *cfile;
+       int *lose;
+{
+       int token;
+       char *val;
+       struct collection *col;
+       struct match_expr buf, *rv;
+       struct match_expr *left, *right;
+       struct option *option;
+
+       token = peek_token (&val, cfile);
+
+       switch (token) {
+             case SUBSTRING:
+               token = next_token (&val, cfile);
+               buf.op = match_substring;
+
+               token = next_token (&val, cfile);
+               if (token != LPAREN) {
+                     nolparen:
+                       parse_warn ("left parenthesis expected.");
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+
+               buf.data.substring.expr = parse_data_expression (cfile, lose);
+               if (!buf.data.substring.expr) {
+                     nodata:
+                       parse_warn ("expecting data expression.");
+                       skip_to_semi (cfile);
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+
+               token = next_token (&val, cfile);
+               if (token != COMMA) {
+                     nocomma:
+                       parse_warn ("comma expected.");
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+
+               buf.data.substring.offset =
+                       parse_numeric_expression (cfile, lose);
+               if (!buf.data.substring.offset) {
+                     nonum:
+                       if (!*lose) {
+                               parse_warn ("expecting numeric expression.");
+                               skip_to_semi (cfile);
+                               *lose = 1;
+                       }
+                       return (struct match_expr *)0;
+               }
+
+               token = next_token (&val, cfile);
+               if (token != COMMA)
+                       goto nocomma;
+
+               buf.data.substring.len =
+                       parse_numeric_expression (cfile, lose);
+               if (!buf.data.substring.len)
+                       goto nonum;
+
+               token = next_token (&val, cfile);
+               if (token != RPAREN) {
+                     norparen:
+                       parse_warn ("right parenthesis expected.");
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+               goto have_expr;
+
+             case SUFFIX:
+               token = next_token (&val, cfile);
+               buf.op = match_suffix;
+
+               token = next_token (&val, cfile);
+               if (token != LPAREN)
+                       goto nolparen;
+
+               buf.data.suffix.expr = parse_data_expression (cfile, lose);
+               if (!buf.data.suffix.expr)
+                       goto nodata;
+
+               token = next_token (&val, cfile);
+               if (token != COMMA)
+                       goto nocomma;
+
+               buf.data.suffix.len = parse_numeric_expression (cfile, lose);
+               if (!buf.data.suffix.len)
+                       goto nonum;
+
+               token = next_token (&val, cfile);
+               if (token != RPAREN)
+                       goto norparen;
+               goto have_expr;
+
+             case OPTION:
+               token = next_token (&val, cfile);
+               buf.op = match_option;
+               buf.data.option = parse_option_name (cfile);
+               if (!buf.data.option) {
+                       *lose = 1;
+                       return;
+               }
+               goto have_expr;
+
+             case HARDWARE:
+               token = next_token (&val, cfile);
+               buf.op = match_hardware;
+               goto have_expr;
+
+             case PACKET:
+               token = next_token (&val, cfile);
+               buf.op = match_packet;
+
+               token = next_token (&val, cfile);
+               if (token != LPAREN)
+                       goto nolparen;
+
+               buf.data.packet.offset =
+                       parse_numeric_expression (cfile, lose);
+               if (!buf.data.packet.offset)
+                       goto nonum;
+
+               token = next_token (&val, cfile);
+               if (token != COMMA)
+                       goto nocomma;
+
+               buf.data.packet.len =
+                       parse_numeric_expression (cfile, lose);
+               if (!buf.data.substring.len)
+                       goto nonum;
+
+               token = next_token (&val, cfile);
+               if (token != RPAREN)
+                       goto norparen;
+               goto have_expr;
+               
+             case STRING:
+               token = next_token (&val, cfile);
+               buf.op = match_const_data;
+               memset (&buf.data, 0, sizeof buf.data);
+               buf.data.const_data.len = strlen (val);
+               buf.data.const_data.data =
+                       dmalloc (buf.data.const_data.len + 1,
+                                "string expression");
+               if (!buf.data.const_data.data)
+                       error ("no memory for string expression.");
+               buf.data.const_data.terminated = 1;
+               strcpy (buf.data.const_data.data, val);
+               goto have_expr;
+
+             case NUMBER:
+             case NUMBER_OR_NAME:
+               buf.op = match_const_data;
+               memset (&buf.data, 0, sizeof buf.data);
+               buf.data.const_data.data =
+                       parse_cshl (cfile, &buf.data.const_data.len);
+               goto have_expr;
+
+             default:
+               return (struct match_expr *)0;
+       }
+
+      have_expr:
+       rv = (struct match_expr *)dmalloc (sizeof (struct match_expr),
+                                          "parse_boolean_expression");
+       if (!rv)
+               error ("No memory for boolean expression.");
+       *rv = buf;
+       return rv;
+}
+
+struct match_expr *parse_numeric_expression (cfile, lose)
+       FILE *cfile;
+       int *lose;
+{
+       int token;
+       char *val;
+       struct collection *col;
+       struct match_expr buf, *rv;
+       struct match_expr *left, *right;
+       struct option *option;
+
+       token = peek_token (&val, cfile);
+
+       switch (token) {
+             case EXTRACT_INT:
+               token = next_token (&val, cfile);       
+
+               token = next_token (&val, cfile);
+               if (token != LPAREN) {
+                       parse_warn ("left parenthesis expected.");
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+
+               buf.data.extract_int.expr =
+                       parse_data_expression (cfile, lose);
+               if (!buf.data.extract_int.expr) {
+                       parse_warn ("expecting data expression.");
+                       skip_to_semi (cfile);
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+
+               token = next_token (&val, cfile);
+               if (token != COMMA) {
+                       parse_warn ("comma expected.");
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+
+               token = next_token (&val, cfile);
+               if (token != NUMBER) {
+                       parse_warn ("number expected.");
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+               buf.data.extract_int.width = (struct match_expr *)0;
+               switch (atoi (val)) {
+                     case 8:
+                       buf.op = match_extract_int8;
+                       break;
+
+                     case 16:
+                       buf.op = match_extract_int16;
+                       break;
+
+                     case 32:
+                       buf.op = match_extract_int32;
+                       break;
+
+                     default:
+                       parse_warn ("unsupported integer size %d", atoi (val));
+                       *lose = 1;
+                       skip_to_semi (cfile);
+                       return (struct match_expr *)0;
+               }
+
+               token = next_token (&val, cfile);
+               if (token != RPAREN) {
+                       parse_warn ("right parenthesis expected.");
+                       *lose = 1;
+                       return (struct match_expr *)0;
+               }
+               goto have_expr;
+       
+             case NUMBER:
+               buf.op = match_const_int;
+               buf.data.const_int = atoi (val);
+               goto have_expr;
+
+             default:
+               return (struct match_expr *)0;
+       }
+
+      have_expr:
+       rv = (struct match_expr *)dmalloc (sizeof (struct match_expr),
+                                          "parse_boolean_expression");
+       if (!rv)
+               error ("No memory for boolean expression.");
+       *rv = buf;
+       return rv;
+}