]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add support for parsing <tag>[=<value>]
authorMark Andrews <marka@isc.org>
Wed, 25 Sep 2019 08:02:38 +0000 (18:02 +1000)
committerMark Andrews <marka@isc.org>
Wed, 18 Aug 2021 03:49:48 +0000 (13:49 +1000)
where <value> may be a quoted string.  Previously quoted string
only supported opening quotes at the start of the string.

lib/isc/include/isc/lex.h
lib/isc/lex.c

index fdbe10b92a82bdc3d2f4a5f606d92f6a35768085..84d4f42486044075063b3bef375b79affacbd983 100644 (file)
@@ -61,11 +61,11 @@ ISC_LANG_BEGINDECLS
  * Various options for isc_lex_gettoken().
  */
 
-#define ISC_LEXOPT_EOL      0x01 /*%< Want end-of-line token. */
-#define ISC_LEXOPT_EOF      0x02 /*%< Want end-of-file token. */
-#define ISC_LEXOPT_INITIALWS 0x04 /*%< Want initial whitespace. */
-#define ISC_LEXOPT_NUMBER    0x08 /*%< Recognize numbers. */
-#define ISC_LEXOPT_QSTRING   0x10 /*%< Recognize qstrings. */
+#define ISC_LEXOPT_EOL      0x0001 /*%< Want end-of-line token. */
+#define ISC_LEXOPT_EOF      0x0002 /*%< Want end-of-file token. */
+#define ISC_LEXOPT_INITIALWS 0x0004 /*%< Want initial whitespace. */
+#define ISC_LEXOPT_NUMBER    0x0008 /*%< Recognize numbers. */
+#define ISC_LEXOPT_QSTRING   0x0010 /*%< Recognize qstrings. */
 /*@}*/
 
 /*@{*/
@@ -76,14 +76,16 @@ ISC_LANG_BEGINDECLS
  * the paren count is > 0.  To use this option, '(' and ')' must be special
  * characters.
  */
-#define ISC_LEXOPT_DNSMULTILINE 0x20 /*%< Handle '(' and ')'. */
-#define ISC_LEXOPT_NOMORE      0x40 /*%< Want "no more" token. */
-
-#define ISC_LEXOPT_CNUMBER         0x80  /*%< Recognize octal and hex. */
-#define ISC_LEXOPT_ESCAPE          0x100 /*%< Recognize escapes. */
-#define ISC_LEXOPT_QSTRINGMULTILINE 0x200 /*%< Allow multiline "" strings */
-#define ISC_LEXOPT_OCTAL           0x400 /*%< Expect a octal number. */
-#define ISC_LEXOPT_BTEXT           0x800 /*%< Bracketed text. */
+#define ISC_LEXOPT_DNSMULTILINE 0x0020 /*%< Handle '(' and ')'. */
+#define ISC_LEXOPT_NOMORE      0x0040 /*%< Want "no more" token. */
+
+#define ISC_LEXOPT_CNUMBER         0x0080 /*%< Recognize octal and hex. */
+#define ISC_LEXOPT_ESCAPE          0x0100 /*%< Recognize escapes. */
+#define ISC_LEXOPT_QSTRINGMULTILINE 0x0200 /*%< Allow multiline "" strings */
+#define ISC_LEXOPT_OCTAL           0x0400 /*%< Expect a octal number. */
+#define ISC_LEXOPT_BTEXT           0x0800 /*%< Bracketed text. */
+#define ISC_LEXOPT_VPAIR           0x1000 /*%< Recognize value pair. */
+#define ISC_LEXOPT_QVPAIR          0x2000 /*%< Recognize quoted value pair. */
 /*@}*/
 /*@{*/
 /*!
@@ -117,7 +119,9 @@ typedef enum {
        isc_tokentype_initialws = 6,
        isc_tokentype_special = 7,
        isc_tokentype_nomore = 8,
-       isc_tokentype_btext = 8
+       isc_tokentype_btext = 9,
+       isc_tokentype_vpair = 10,
+       isc_tokentype_qvpair = 11,
 } isc_tokentype_t;
 
 typedef union {
index 3aef691694e60639e71451e0c04d6d33df488c71..8ab368287397aade4368be6f780fcd53ce85322a 100644 (file)
@@ -293,7 +293,10 @@ typedef enum {
        lexstate_ccommentend,
        lexstate_eatline,
        lexstate_qstring,
-       lexstate_btext
+       lexstate_btext,
+       lexstate_vpair,
+       lexstate_vpairstart,
+       lexstate_qvpair,
 } lexstate;
 
 #define IWSEOL (ISC_LEXOPT_INITIALWS | ISC_LEXOPT_EOL)
@@ -663,6 +666,29 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) {
                        remaining--;
                        break;
                case lexstate_string:
+                       if (!escaped && c == '=' &&
+                           (options & ISC_LEXOPT_VPAIR) != 0) {
+                               INSIST(remaining > 0U);
+                               *curr++ = c;
+                               *curr = '\0';
+                               remaining--;
+                               state = lexstate_vpairstart;
+                               break;
+                       }
+                       /* FALLTHROUGH */
+               case lexstate_vpairstart:
+                       if (state == lexstate_vpairstart) {
+                               if (c == '"' &&
+                                   (options & ISC_LEXOPT_QVPAIR) != 0) {
+                                       INSIST(remaining > 0U);
+                                       no_comments = true;
+                                       state = lexstate_qvpair;
+                                       break;
+                               }
+                               state = lexstate_vpair;
+                       }
+                       /* FALLTHROUGH */
+               case lexstate_vpair:
                        /*
                         * EOF needs to be checked before lex->specials[c]
                         * as lex->specials[EOF] is not a good idea.
@@ -676,7 +702,13 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) {
                                        result = source->result;
                                        goto done;
                                }
-                               tokenp->type = isc_tokentype_string;
+                               if (escaped && c == EOF) {
+                                       result = ISC_R_UNEXPECTEDEND;
+                                       goto done;
+                               }
+                               tokenp->type = (state == lexstate_string)
+                                                      ? isc_tokentype_string
+                                                      : isc_tokentype_vpair;
                                tokenp->value.as_textregion.base = lex->data;
                                tokenp->value.as_textregion.length =
                                        (unsigned int)(lex->max_token -
@@ -753,6 +785,7 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) {
                        }
                        break;
                case lexstate_qstring:
+               case lexstate_qvpair:
                        if (c == EOF) {
                                result = ISC_R_UNEXPECTEDEND;
                                goto done;
@@ -766,7 +799,10 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) {
                                        INSIST(prev != NULL);
                                        *prev = '"';
                                } else {
-                                       tokenp->type = isc_tokentype_qstring;
+                                       tokenp->type =
+                                               (state == lexstate_qstring)
+                                                       ? isc_tokentype_qstring
+                                                       : isc_tokentype_qvpair;
                                        tokenp->value.as_textregion.base =
                                                lex->data;
                                        tokenp->value.as_textregion.length =
@@ -876,7 +912,12 @@ isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token,
                               ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
        isc_result_t result;
 
-       if (expect == isc_tokentype_qstring) {
+       if (expect == isc_tokentype_vpair) {
+               options |= ISC_LEXOPT_VPAIR;
+       } else if (expect == isc_tokentype_qvpair) {
+               options |= ISC_LEXOPT_VPAIR;
+               options |= ISC_LEXOPT_QVPAIR;
+       } else if (expect == isc_tokentype_qstring) {
                options |= ISC_LEXOPT_QSTRING;
        } else if (expect == isc_tokentype_number) {
                options |= ISC_LEXOPT_NUMBER;
@@ -895,7 +936,12 @@ isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token,
                return (ISC_R_SUCCESS);
        }
        if (token->type == isc_tokentype_string &&
-           expect == isc_tokentype_qstring) {
+           (expect == isc_tokentype_qstring || expect == isc_tokentype_qvpair))
+       {
+               return (ISC_R_SUCCESS);
+       }
+       if (token->type == isc_tokentype_vpair &&
+           expect == isc_tokentype_qvpair) {
                return (ISC_R_SUCCESS);
        }
        if (token->type != expect) {