]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Add fdi argument to format_parse functions.
authorBruno Haible <bruno@clisp.org>
Mon, 27 Nov 2006 12:46:22 +0000 (12:46 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:14:24 +0000 (12:14 +0200)
25 files changed:
gettext-tools/src/ChangeLog
gettext-tools/src/format-awk.c
gettext-tools/src/format-boost.c
gettext-tools/src/format-c.c
gettext-tools/src/format-csharp.c
gettext-tools/src/format-elisp.c
gettext-tools/src/format-gcc-internal.c
gettext-tools/src/format-java.c
gettext-tools/src/format-librep.c
gettext-tools/src/format-lisp.c
gettext-tools/src/format-pascal.c
gettext-tools/src/format-perl-brace.c
gettext-tools/src/format-perl.c
gettext-tools/src/format-php.c
gettext-tools/src/format-python.c
gettext-tools/src/format-qt.c
gettext-tools/src/format-scheme.c
gettext-tools/src/format-sh.c
gettext-tools/src/format-tcl.c
gettext-tools/src/format-ycp.c
gettext-tools/src/format.c
gettext-tools/src/format.h
gettext-tools/src/msgmerge.c
gettext-tools/src/read-mo.c
gettext-tools/src/xgettext.c

index 1c3c9f8c5b062e0ea637f29bdb3e1cf9c557136c..a050e913b666f259f8187d89bb80bcf273d147c0 100644 (file)
@@ -1,3 +1,41 @@
+2006-11-26  Bruno Haible  <bruno@clisp.org>
+
+       * format.h (FMTDIR_START, FMTDIR_END, FMTDIR_ERROR): New enum values.
+       (FDI_SET): New macro.
+       (struct formatstring_parser): Add fdi argument to 'parse' method.
+       * format.c (check_msgid_msgstr_format): Update.
+       * format-awk.c (format_parse): Add fdi argument. Invoke FDI_SET.
+       * format-boost.c (format_parse): Likewise.
+       * format-c.c (format_parse): Add fdi argument. Invoke FDI_SET.
+       (format_c_parse, format_objc_parse): Add fdi argument.
+       (get_sysdep_c_format_directives): Update.
+       * format-csharp.c (format_parse): Add fdi argument. Invoke FDI_SET.
+       * format-elisp.c (format_parse): Likewise.
+       * format-gcc-internal.c (format_parse): Likewise.
+       * format-java.c (message_format_parse): Add fdi argument. Invoke
+       FDI_SET.
+       (choice_format_parse): Update.
+       (format_parse): Add fdi argument.
+       * format-librep.c (format_parse): Add fdi argument. Invoke FDI_SET.
+       * format-lisp.c (parse_upto): Add fdi argument. Invoke FDI_SET.
+       (format_parse): Add fdi argument.
+       * format-pascal.c (format_parse): Add fdi argument. Invoke FDI_SET.
+       * format-perl.c (format_parse): Likewise.
+       * format-perl-brace.c (format_parse): Likewise.
+       * format-php.c (format_parse): Likewise.
+       * format-python.c (format_parse): Add fdi argument. Invoke FDI_SET.
+       (get_python_format_unnamed_arg_count): Update.
+       * format-qt.c (format_parse): Add fdi argument. Invoke FDI_SET.
+       * format-scheme.c (parse_upto): Add fdi argument. Invoke FDI_SET.
+       (format_parse): Add fdi argument.
+       * format-sh.c (format_parse): Add fdi argument. Invoke FDI_SET.
+       * format-tcl.c (format_parse): Likewise.
+       * format-ycp.c (format_parse): Likewise.
+       * msgmerge.c (msgfmt_check_pair_fails): Update.
+       * read-mo.c (read_mo_file): Update.
+       * xgettext.c (set_format_flags_from_context, remember_a_message,
+       remember_a_message_plural): Update.
+
 2006-11-25  Bruno Haible  <bruno@clisp.org>
 
        * message.h (message_list_copy, msgdomain_list_copy): New declarations.
index 8cdbc5ad431a4d3a5b165b8994ba2f99e95ce4fb..db3f09e4c6367b352c7abfad0b802de55fde2197 100644 (file)
@@ -94,8 +94,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   unsigned int unnumbered_arg_count;
   struct spec *result;
@@ -113,6 +115,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
        unsigned int number = 0;
        enum format_arg_type type;
 
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (isdigit (*format))
@@ -132,6 +135,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (m == 0)
                  {
                    *invalid_reason = INVALID_ARGNO_0 (spec.directives);
+                   FDI_SET (f, FMTDIR_ERROR);
                    goto bad_format;
                  }
                number = m;
@@ -169,6 +173,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                      {
                        *invalid_reason =
                          INVALID_WIDTH_ARGNO_0 (spec.directives);
+                       FDI_SET (f, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    width_number = m;
@@ -184,6 +189,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (unnumbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -204,6 +210,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (spec.numbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -251,6 +258,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                          {
                            *invalid_reason =
                              INVALID_PRECISION_ARGNO_0 (spec.directives);
+                           FDI_SET (f, FMTDIR_ERROR);
                            goto bad_format;
                          }
                        precision_number = m;
@@ -266,6 +274,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (unnumbered_arg_count > 0)
                      {
                        *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
 
@@ -286,6 +295,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (spec.numbered_arg_count > 0)
                      {
                        *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
 
@@ -326,10 +336,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            type = FAT_FLOAT;
            break;
          default:
-           *invalid_reason =
-             (*format == '\0'
-              ? INVALID_UNTERMINATED_DIRECTIVE ()
-              : INVALID_CONVERSION_SPECIFIER (spec.directives, *format));
+           if (*format == '\0')
+             {
+               *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
+             }
+           else
+             {
+               *invalid_reason =
+                 INVALID_CONVERSION_SPECIFIER (spec.directives, *format);
+               FDI_SET (format, FMTDIR_ERROR);
+             }
            goto bad_format;
          }
 
@@ -343,6 +360,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (unnumbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -363,6 +381,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (spec.numbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -377,6 +396,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
              }
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -618,7 +639,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 8f1e3cbe1c0bd2215ddfa796e51f1b7b206251a3..318f4b6bd77bda844239ed1c27d7a4d298d95da3 100644 (file)
@@ -114,8 +114,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   unsigned int unnumbered_arg_count;
   struct spec *result;
@@ -130,6 +132,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
     if (*format++ == '%')
       {
        /* A directive.  */
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (*format == '%')
@@ -164,6 +167,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (m == 0) /* can happen if m overflows */
                      {
                        *invalid_reason = INVALID_ARGNO_0 (spec.directives);
+                       FDI_SET (f, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    number = m;
@@ -215,6 +219,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                              {
                                *invalid_reason =
                                  INVALID_WIDTH_ARGNO_0 (spec.directives);
+                               FDI_SET (f, FMTDIR_ERROR);
                                goto bad_format;
                              }
                            width_number = m;
@@ -232,6 +237,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                          {
                            *invalid_reason =
                              INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                           FDI_SET (format - 1, FMTDIR_ERROR);
                            goto bad_format;
                          }
 
@@ -254,6 +260,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                          {
                            *invalid_reason =
                              INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                           FDI_SET (format - 1, FMTDIR_ERROR);
                            goto bad_format;
                          }
 
@@ -301,6 +308,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                                  {
                                    *invalid_reason =
                                      INVALID_PRECISION_ARGNO_0 (spec.directives);
+                                   FDI_SET (f, FMTDIR_ERROR);
                                    goto bad_format;
                                  }
                                precision_number = m;
@@ -318,6 +326,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                              {
                                *invalid_reason =
                                  INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                               FDI_SET (format - 1, FMTDIR_ERROR);
                                goto bad_format;
                              }
 
@@ -340,6 +349,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                              {
                                *invalid_reason =
                                  INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                               FDI_SET (format - 1, FMTDIR_ERROR);
                                goto bad_format;
                              }
 
@@ -392,6 +402,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (*format == '\0')
                      {
                        *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    format++;
@@ -410,22 +421,36 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    /*FALLTHROUGH*/
                  default:
                    --format;
-                   *invalid_reason =
-                     (*format == '\0'
-                      ? INVALID_UNTERMINATED_DIRECTIVE ()
-                      : INVALID_CONVERSION_SPECIFIER (spec.directives,
-                                                      *format));
+                   if (*format == '\0')
+                     {
+                       *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
+                     }
+                   else
+                     {
+                       *invalid_reason =
+                         INVALID_CONVERSION_SPECIFIER (spec.directives,
+                                                       *format);
+                       FDI_SET (format, FMTDIR_ERROR);
+                     }
                    goto bad_format;
                  }
                if (brackets)
                  {
                    if (*format != '|')
                      {
-                       *invalid_reason =
-                         (*format == '\0'
-                          ? INVALID_UNTERMINATED_DIRECTIVE ()
-                          : xasprintf (_("The directive number %u starts with | but does not end with |."),
-                                       spec.directives));
+                       if (*format == '\0')
+                         {
+                           *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                           FDI_SET (format - 1, FMTDIR_ERROR);
+                         }
+                       else
+                         {
+                           *invalid_reason =
+                             xasprintf (_("The directive number %u starts with | but does not end with |."),
+                                        spec.directives);
+                           FDI_SET (format, FMTDIR_ERROR);
+                         }
                        goto bad_format;
                      }
                    format++;
@@ -442,6 +467,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (unnumbered_arg_count > 0)
                      {
                        *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
 
@@ -462,6 +488,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (spec.numbered_arg_count > 0)
                      {
                        *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
 
@@ -476,6 +503,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                  }
              }
          }
+
+       FDI_SET (format - 1, FMTDIR_END);
       }
 
   /* Convert the unnumbered argument array to numbered arguments.  */
@@ -718,7 +747,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index b953f413acb653a6e7e75b24c5a159d61e4bcae8..7c65fe0d6a6c3315b91e090fc7919bdf4ef69678 100644 (file)
@@ -183,8 +183,9 @@ numbered_arg_compare (const void *p1, const void *p2)
 
 static void *
 format_parse (const char *format, bool translated, bool objc_extensions,
-             char **invalid_reason)
+             char *fdi, char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   unsigned int numbered_arg_count;
   struct numbered_arg *numbered;
@@ -208,6 +209,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
        format_arg_type_t type;
        format_arg_type_t size;
 
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (isdigit (*format))
@@ -227,6 +229,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                if (m == 0)
                  {
                    *invalid_reason = INVALID_ARGNO_0 (spec.directives);
+                   FDI_SET (f, FMTDIR_ERROR);
                    goto bad_format;
                  }
                number = m;
@@ -281,6 +284,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                      {
                        *invalid_reason =
                          INVALID_WIDTH_ARGNO_0 (spec.directives);
+                       FDI_SET (f, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    width_number = m;
@@ -296,6 +300,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                if (spec.unnumbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -316,6 +321,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                if (numbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -362,6 +368,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                          {
                            *invalid_reason =
                              INVALID_PRECISION_ARGNO_0 (spec.directives);
+                           FDI_SET (f, FMTDIR_ERROR);
                            goto bad_format;
                          }
                        precision_number = m;
@@ -377,6 +384,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                    if (spec.unnumbered_arg_count > 0)
                      {
                        *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
 
@@ -397,6 +405,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                    if (numbered_arg_count > 0)
                      {
                        *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
 
@@ -432,18 +441,21 @@ format_parse (const char *format, bool translated, bool objc_extensions,
            if (*format != 'P')
              {
                *invalid_reason = INVALID_C99_MACRO (spec.directives);
+               FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
                goto bad_format;
              }
            format++;
            if (*format != 'R')
              {
                *invalid_reason = INVALID_C99_MACRO (spec.directives);
+               FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
                goto bad_format;
              }
            format++;
            if (*format != 'I')
              {
                *invalid_reason = INVALID_C99_MACRO (spec.directives);
+               FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
                goto bad_format;
              }
            format++;
@@ -458,6 +470,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                break;
              default:
                *invalid_reason = INVALID_C99_MACRO (spec.directives);
+               FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
                goto bad_format;
              }
            format++;
@@ -501,6 +514,8 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                    else
                      {
                        *invalid_reason = INVALID_C99_MACRO (spec.directives);
+                       FDI_SET (*format == '\0' ? format - 1 : format,
+                                FMTDIR_ERROR);
                        goto bad_format;
                      }
                  }
@@ -531,6 +546,8 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                    else
                      {
                        *invalid_reason = INVALID_C99_MACRO (spec.directives);
+                       FDI_SET (*format == '\0' ? format - 1 : format,
+                                FMTDIR_ERROR);
                        goto bad_format;
                      }
                  }
@@ -559,6 +576,8 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                    else
                      {
                        *invalid_reason = INVALID_C99_MACRO (spec.directives);
+                       FDI_SET (*format == '\0' ? format - 1 : format,
+                                FMTDIR_ERROR);
                        goto bad_format;
                      }
                  }
@@ -568,6 +587,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
              {
                *invalid_reason =
                  xasprintf (_("In the directive number %u, the token after '<' is not followed by '>'."), spec.directives);
+               FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
                goto bad_format;
              }
 
@@ -670,10 +690,17 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                break;
              other:
              default:
-               *invalid_reason =
-                 (*format == '\0'
-                  ? INVALID_UNTERMINATED_DIRECTIVE ()
-                  : INVALID_CONVERSION_SPECIFIER (spec.directives, *format));
+               if (*format == '\0')
+                 {
+                   *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                 }
+               else
+                 {
+                   *invalid_reason =
+                     INVALID_CONVERSION_SPECIFIER (spec.directives, *format);
+                   FDI_SET (format, FMTDIR_ERROR);
+                 }
                goto bad_format;
              }
          }
@@ -688,6 +715,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                if (spec.unnumbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -708,6 +736,7 @@ format_parse (const char *format, bool translated, bool objc_extensions,
                if (numbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -721,6 +750,8 @@ format_parse (const char *format, bool translated, bool objc_extensions,
              }
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -811,15 +842,17 @@ format_parse (const char *format, bool translated, bool objc_extensions,
 }
 
 static void *
-format_c_parse (const char *format, bool translated, char **invalid_reason)
+format_c_parse (const char *format, bool translated, char *fdi,
+               char **invalid_reason)
 {
-  return format_parse (format, translated, false, invalid_reason);
+  return format_parse (format, translated, false, fdi, invalid_reason);
 }
 
 static void *
-format_objc_parse (const char *format, bool translated, char **invalid_reason)
+format_objc_parse (const char *format, bool translated, char *fdi,
+                  char **invalid_reason)
 {
-  return format_parse (format, translated, true, invalid_reason);
+  return format_parse (format, translated, true, fdi, invalid_reason);
 }
 
 static void
@@ -913,7 +946,8 @@ get_sysdep_c_format_directives (const char *string, bool translated,
      particular language.)  */
   char *invalid_reason = NULL;
   struct spec *descr =
-    (struct spec *) format_parse (string, translated, true, &invalid_reason);
+    (struct spec *)
+    format_parse (string, translated, true, NULL, &invalid_reason);
 
   if (descr != NULL && descr->sysdep_directives_count > 0)
     {
@@ -1084,7 +1118,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_c_parse (line, false, &invalid_reason);
+      descr = format_c_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index e72506e3f037d4a89e58e4903ec06fb2ddddd660..0b57d8eda7a2a7f7d3110e5300ce1a6817335e44 100644 (file)
@@ -57,8 +57,10 @@ struct spec
 };
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
 
@@ -71,6 +73,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
 
       if (c == '{')
        {
+         FDI_SET (format - 1, FMTDIR_START);
          if (*format == '{')
            format++;
          else
@@ -84,6 +87,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                {
                  *invalid_reason =
                    xasprintf (_("In the directive number %u, '{' is not followed by an argument number."), spec.directives);
+                 FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
                  return NULL;
                }
              number = 0;
@@ -104,6 +108,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    {
                      *invalid_reason =
                        xasprintf (_("In the directive number %u, ',' is not followed by a number."), spec.directives);
+                     FDI_SET (*format == '\0' ? format - 1 : format,
+                              FMTDIR_ERROR);
                      return NULL;
                    }
                  do
@@ -123,6 +129,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                {
                  *invalid_reason =
                    xstrdup (_("The string ends in the middle of a directive: found '{' without matching '}'."));
+                 FDI_SET (format - 1, FMTDIR_ERROR);
                  return NULL;
                }
 
@@ -132,6 +139,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    (c_isprint (*format)
                     ? xasprintf (_("The directive number %u ends with an invalid character '%c' instead of '}'."), spec.directives, *format)
                     : xasprintf (_("The directive number %u ends with an invalid character instead of '}'."), spec.directives));
+                 FDI_SET (format, FMTDIR_ERROR);
                  return NULL;
                }
 
@@ -140,9 +148,11 @@ format_parse (const char *format, bool translated, char **invalid_reason)
              if (spec.numbered_arg_count <= number)
                spec.numbered_arg_count = number + 1;
            }
+         FDI_SET (format - 1, FMTDIR_END);
        }
       else if (c == '}')
        {
+         FDI_SET (format - 1, FMTDIR_START);
          if (*format == '}')
            format++;
          else
@@ -151,8 +161,10 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                (spec.directives == 0
                 ? xstrdup (_("The string starts in the middle of a directive: found '}' without matching '{'."))
                 : xasprintf (_("The string contains a lone '}' after directive number %u."), spec.directives));
+             FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR);
              return NULL;
            }
+         FDI_SET (format - 1, FMTDIR_END);
        }
     }
 
@@ -259,7 +271,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index b47a2627787820f153b46b067345b6a95926aaa9..34455d81bdd94db4871dca8c9c1cc05b74a8a99c 100644 (file)
@@ -95,8 +95,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
   unsigned int number;
@@ -113,6 +115,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
        /* A directive.  */
        enum format_arg_type type;
 
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (isdigit (*format))
@@ -207,10 +210,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            type = FAT_OBJECT;
            break;
          default:
-           *invalid_reason =
-             (*format == '\0'
-              ? INVALID_UNTERMINATED_DIRECTIVE ()
-              : INVALID_CONVERSION_SPECIFIER (spec.directives, *format));
+           if (*format == '\0')
+             {
+               *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
+             }
+           else
+             {
+               *invalid_reason =
+                 INVALID_CONVERSION_SPECIFIER (spec.directives, *format);
+               FDI_SET (format, FMTDIR_ERROR);
+             }
            goto bad_format;
          }
 
@@ -228,6 +238,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            number++;
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -466,7 +478,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index ee15eff83529ff80afceec4c09db10500fff0b91..bbed625efff65d6bc5caeeeb91018a54a3fad631 100644 (file)
@@ -157,8 +157,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   unsigned int unnumbered_arg_count;
   struct spec *result;
@@ -174,6 +176,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
     if (*format++ == '%')
       {
        /* A directive.  */
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (*format == '%' || *format == '<' || *format == '>'
@@ -209,6 +212,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (m == 0)
                      {
                        *invalid_reason = INVALID_ARGNO_0 (spec.directives);
+                       FDI_SET (f, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    number = m;
@@ -248,6 +252,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    continue;
                  invalid_flags:
                    *invalid_reason = xasprintf (_("In the directive number %u, the flags combination is invalid."), spec.directives);
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  default:
                    break;
@@ -275,10 +280,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
 
                    if (*format != 's')
                      {
-                       *invalid_reason =
-                         (*format == '\0'
-                          ? INVALID_UNTERMINATED_DIRECTIVE ()
-                          : xasprintf (_("In the directive number %u, a precision is not allowed before '%c'."), spec.directives, *format));
+                       if (*format == '\0')
+                         {
+                           *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                           FDI_SET (format - 1, FMTDIR_ERROR);
+                         }
+                       else
+                         {
+                           *invalid_reason =
+                             xasprintf (_("In the directive number %u, a precision is not allowed before '%c'."), spec.directives, *format);
+                           FDI_SET (format, FMTDIR_ERROR);
+                         }
                        goto bad_format;
                      }
 
@@ -307,16 +319,19 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                            if (m == 0)
                              {
                                *invalid_reason = INVALID_WIDTH_ARGNO_0 (spec.directives);
+                               FDI_SET (f, FMTDIR_ERROR);
                                goto bad_format;
                              }
                            if (unnumbered_arg_count > 0 || number == 0)
                              {
                                *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                               FDI_SET (f, FMTDIR_ERROR);
                                goto bad_format;
                              }
                            if (m != number - 1)
                              {
                                *invalid_reason = xasprintf (_("In the directive number %u, the argument number for the precision must be equal to %u."), spec.directives, number - 1);
+                               FDI_SET (f, FMTDIR_ERROR);
                                goto bad_format;
                              }
                            precision_number = m;
@@ -332,6 +347,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                        if (unnumbered_arg_count > 0)
                          {
                            *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                           FDI_SET (format - 1, FMTDIR_ERROR);
                            goto bad_format;
                          }
 
@@ -352,6 +368,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                        if (spec.numbered_arg_count > 0)
                          {
                            *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                           FDI_SET (format - 1, FMTDIR_ERROR);
                            goto bad_format;
                          }
 
@@ -369,16 +386,25 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                      type = FAT_STRING;
                    else
                      {
-                       *invalid_reason =
-                         (*format == '\0'
-                          ? INVALID_UNTERMINATED_DIRECTIVE ()
-                          : xasprintf (_("In the directive number %u, a precision is not allowed before '%c'."), spec.directives, *format));
+                       if (*format == '\0')
+                         {
+                           *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                           FDI_SET (format - 1, FMTDIR_ERROR);
+                         }
+                       else
+                         {
+                           *invalid_reason =
+                             xasprintf (_("In the directive number %u, a precision is not allowed before '%c'."), spec.directives, *format);
+                           FDI_SET (format, FMTDIR_ERROR);
+                         }
                        goto bad_format;
                      }
                  }
                else
                  {
                    *invalid_reason = xasprintf (_("In the directive number %u, the precision specification is invalid."), spec.directives);
+                   FDI_SET (*format == '\0' ? format - 1 : format,
+                            FMTDIR_ERROR);
                    goto bad_format;
                  }
              }
@@ -418,17 +444,24 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                  type = FAT_TREE | FAT_TREE_CV;
                else
                  {
-                   *invalid_reason =
-                     (*format == '\0'
-                      ? INVALID_UNTERMINATED_DIRECTIVE ()
-                      : (*format == 'c'
-                         || *format == 's'
-                         || *format == 'i' || *format == 'd'
-                         || *format == 'o' || *format == 'u' || *format == 'x'
-                         || *format == 'H'
-                         ? xasprintf (_("In the directive number %u, flags are not allowed before '%c'."), spec.directives, *format)
-                         : INVALID_CONVERSION_SPECIFIER (spec.directives,
-                                                         *format)));
+                   if (*format == '\0')
+                     {
+                       *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
+                     }
+                   else
+                     {
+                       *invalid_reason =
+                         (*format == 'c'
+                          || *format == 's'
+                          || *format == 'i' || *format == 'd'
+                          || *format == 'o' || *format == 'u' || *format == 'x'
+                          || *format == 'H'
+                          ? xasprintf (_("In the directive number %u, flags are not allowed before '%c'."), spec.directives, *format)
+                          : INVALID_CONVERSION_SPECIFIER (spec.directives,
+                                                          *format));
+                       FDI_SET (format, FMTDIR_ERROR);
+                     }
                    goto bad_format;
                  }
              }
@@ -441,6 +474,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (unnumbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -461,6 +495,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (spec.numbered_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -475,6 +510,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
              }
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -784,7 +821,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 38aaaa399e9d410a99b7f43585ddf69ed5b99243..5135e3adb3f770a0f85b1a13bb427d4a37bfa938 100644 (file)
@@ -149,9 +149,10 @@ static bool choice_format_parse (const char *format, struct spec *spec,
 /* Return true if a format is a valid messageFormatPattern.
    Extracts argument type information into spec.  */
 static bool
-message_format_parse (const char *format, struct spec *spec,
+message_format_parse (const char *format, char *fdi, struct spec *spec,
                      char **invalid_reason)
 {
+  const char *const format_start = format;
   bool quoting = false;
 
   for (;;)
@@ -168,6 +169,7 @@ message_format_parse (const char *format, struct spec *spec,
          unsigned int number;
          enum format_arg_type type;
 
+         FDI_SET (format, FMTDIR_START);
          spec->directives++;
 
          element_start = ++format;
@@ -188,6 +190,7 @@ message_format_parse (const char *format, struct spec *spec,
            {
              *invalid_reason =
                xstrdup (_("The string ends in the middle of a directive: found '{' without matching '}'."));
+             FDI_SET (format - 1, FMTDIR_ERROR);
              return false;
            }
          element_end = format++;
@@ -201,6 +204,7 @@ message_format_parse (const char *format, struct spec *spec,
            {
              *invalid_reason =
                xasprintf (_("In the directive number %u, '{' is not followed by an argument number."), spec->directives);
+             FDI_SET (format - 1, FMTDIR_ERROR);
              freesa (element_alloced);
              return false;
            }
@@ -235,6 +239,7 @@ message_format_parse (const char *format, struct spec *spec,
                    {
                      *invalid_reason =
                        xasprintf (_("In the directive number %u, the substring \"%s\" is not a valid date/time style."), spec->directives, element);
+                     FDI_SET (format - 1, FMTDIR_ERROR);
                      freesa (element_alloced);
                      return false;
                    }
@@ -245,6 +250,7 @@ message_format_parse (const char *format, struct spec *spec,
                  element -= 4;
                  *invalid_reason =
                    xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element);
+                 FDI_SET (format - 1, FMTDIR_ERROR);
                  freesa (element_alloced);
                  return false;
                }
@@ -267,6 +273,7 @@ message_format_parse (const char *format, struct spec *spec,
                    {
                      *invalid_reason =
                        xasprintf (_("In the directive number %u, the substring \"%s\" is not a valid number style."), spec->directives, element);
+                     FDI_SET (format - 1, FMTDIR_ERROR);
                      freesa (element_alloced);
                      return false;
                    }
@@ -277,6 +284,7 @@ message_format_parse (const char *format, struct spec *spec,
                  element -= 6;
                  *invalid_reason =
                    xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element);
+                 FDI_SET (format - 1, FMTDIR_ERROR);
                  freesa (element_alloced);
                  return false;
                }
@@ -294,6 +302,7 @@ message_format_parse (const char *format, struct spec *spec,
                    ;
                  else
                    {
+                     FDI_SET (format - 1, FMTDIR_ERROR);
                      freesa (element_alloced);
                      return false;
                    }
@@ -304,6 +313,7 @@ message_format_parse (const char *format, struct spec *spec,
                  element -= 6;
                  *invalid_reason =
                    xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element);
+                 FDI_SET (format - 1, FMTDIR_ERROR);
                  freesa (element_alloced);
                  return false;
                }
@@ -312,6 +322,7 @@ message_format_parse (const char *format, struct spec *spec,
            {
              *invalid_reason =
                xasprintf (_("In the directive number %u, the argument number is not followed by a comma and one of \"%s\", \"%s\", \"%s\", \"%s\"."), spec->directives, "time", "date", "number", "choice");
+             FDI_SET (format - 1, FMTDIR_ERROR);
              freesa (element_alloced);
              return false;
            }
@@ -325,12 +336,16 @@ message_format_parse (const char *format, struct spec *spec,
          spec->numbered[spec->numbered_arg_count].number = number;
          spec->numbered[spec->numbered_arg_count].type = type;
          spec->numbered_arg_count++;
+
+         FDI_SET (format - 1, FMTDIR_END);
        }
       /* The doc says "ab}de" is invalid.  Even though JDK accepts it.  */
       else if (!quoting && *format == '}')
        {
+         FDI_SET (format, FMTDIR_START);
          *invalid_reason =
            xstrdup (_("The string starts in the middle of a directive: found '}' without matching '{'."));
+         FDI_SET (format, FMTDIR_ERROR);
          return false;
        }
       else if (*format != '\0')
@@ -581,7 +596,8 @@ choice_format_parse (const char *format, struct spec *spec,
        }
       *mp = '\0';
 
-      msgformat_valid = message_format_parse (msgformat, spec, invalid_reason);
+      msgformat_valid =
+       message_format_parse (msgformat, NULL, spec, invalid_reason);
 
       freesa (msgformat);
 
@@ -608,7 +624,8 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -618,7 +635,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
   spec.allocated = 0;
   spec.numbered = NULL;
 
-  if (!message_format_parse (format, &spec, invalid_reason))
+  if (!message_format_parse (format, fdi, &spec, invalid_reason))
     goto bad_format;
 
   /* Sort the numbered argument array, and eliminate duplicates.  */
@@ -852,7 +869,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index c44c9683e5dda96add60bd6b5fa8069ef0ff7b41..bd460b7cb19a97868d92e1048d024770d40ebff2 100644 (file)
@@ -92,8 +92,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
   unsigned int number;
@@ -110,6 +112,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
        /* A directive.  */
        enum format_arg_type type;
 
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (isdigit (*format))
@@ -171,10 +174,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            type = FAT_OBJECT;
            break;
          default:
-           *invalid_reason =
-             (*format == '\0'
-              ? INVALID_UNTERMINATED_DIRECTIVE ()
-              : INVALID_CONVERSION_SPECIFIER (spec.directives, *format));
+           if (*format == '\0')
+             {
+               *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
+             }
+           else
+             {
+               *invalid_reason =
+                 INVALID_CONVERSION_SPECIFIER (spec.directives, *format);
+               FDI_SET (format, FMTDIR_ERROR);
+             }
            goto bad_format;
          }
 
@@ -192,6 +202,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            number++;
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -427,7 +439,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 4dd6bbf0de4aa2a95f73ae49590019053f734b31..aa6f64245de109b3a20e5430a472d8ef278ff439 100644 (file)
@@ -2434,6 +2434,7 @@ nocheck_params (struct format_arg_list **listp,
    spec is the global struct spec.
    terminator is the directive that terminates this parse.
    separator specifies if ~; separators are allowed.
+   fdi is an array to be filled with format directive indicators, or NULL.
    If the format string is invalid, false is returned and *invalid_reason is
    set to an error message explaining why.  */
 static bool
@@ -2441,9 +2442,10 @@ parse_upto (const char **formatp,
            int *positionp, struct format_arg_list **listp,
            struct format_arg_list **escapep, int *separatorp,
            struct spec *spec, char terminator, bool separator,
-           char **invalid_reason)
+           char *fdi, char **invalid_reason)
 {
   const char *format = *formatp;
+  const char *const format_start = format;
   int position = *positionp;
   struct format_arg_list *list = *listp;
   struct format_arg_list *escape = *escapep;
@@ -2456,6 +2458,8 @@ parse_upto (const char **formatp,
        unsigned int paramcount = 0;
        struct param *params = NULL;
 
+       FDI_SET (format - 1, FMTDIR_START);
+
        /* Count number of directives.  */
        spec->directives++;
 
@@ -2482,10 +2486,17 @@ parse_upto (const char **formatp,
                format++;
                if (!c_isdigit (*format))
                  {
-                   *invalid_reason =
-                     (*format == '\0'
-                      ? INVALID_UNTERMINATED_DIRECTIVE ()
-                      : xasprintf (_("In the directive number %u, '%c' is not followed by a digit."), spec->directives, format[-1]));
+                   if (*format == '\0')
+                     {
+                       *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
+                     }
+                   else
+                     {
+                       *invalid_reason =
+                         xasprintf (_("In the directive number %u, '%c' is not followed by a digit."), spec->directives, format[-1]);
+                       FDI_SET (format, FMTDIR_ERROR);
+                     }
                    return false;
                  }
                do
@@ -2504,6 +2515,7 @@ parse_upto (const char **formatp,
                if (*format == '\0')
                  {
                    *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
                    return false;
                  }
                format++;
@@ -2560,7 +2572,10 @@ parse_upto (const char **formatp,
          case 'S': case 's': /* 22.3.4.2 FORMAT-S-EXPRESSION */
            if (!check_params (&list, paramcount, params, 4, IIIC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_OBJECT);
            break;
@@ -2568,7 +2583,10 @@ parse_upto (const char **formatp,
          case 'W': case 'w': /* 22.3.4.3 FORMAT-WRITE */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_OBJECT);
            break;
@@ -2579,7 +2597,10 @@ parse_upto (const char **formatp,
          case 'X': case 'x': /* 22.3.2.5 FORMAT-HEXADECIMAL */
            if (!check_params (&list, paramcount, params, 4, ICCI,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_INTEGER);
            break;
@@ -2587,7 +2608,10 @@ parse_upto (const char **formatp,
          case 'R': case 'r': /* 22.3.2.1 FORMAT-RADIX */
            if (!check_params (&list, paramcount, params, 5, IICCI,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_INTEGER);
            break;
@@ -2595,7 +2619,10 @@ parse_upto (const char **formatp,
          case 'P': case 'p': /* 22.3.8.3 FORMAT-PLURAL */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (colon_p)
              {
                /* Go back by 1 argument.  */
@@ -2609,7 +2636,10 @@ parse_upto (const char **formatp,
          case 'C': case 'c': /* 22.3.1.1 FORMAT-CHARACTER */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_CHARACTER);
            break;
@@ -2617,7 +2647,10 @@ parse_upto (const char **formatp,
          case 'F': case 'f': /* 22.3.3.1 FORMAT-FIXED-FLOAT */
            if (!check_params (&list, paramcount, params, 5, IIICC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_REAL);
            break;
@@ -2626,7 +2659,10 @@ parse_upto (const char **formatp,
          case 'G': case 'g': /* 22.3.3.3 FORMAT-GENERAL-FLOAT */
            if (!check_params (&list, paramcount, params, 7, IIIICCC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_REAL);
            break;
@@ -2634,7 +2670,10 @@ parse_upto (const char **formatp,
          case '$': /* 22.3.3.4 FORMAT-DOLLARS-FLOAT */
            if (!check_params (&list, paramcount, params, 4, IIIC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_REAL);
            break;
@@ -2646,26 +2685,38 @@ parse_upto (const char **formatp,
          case 'I': case 'i': /* 22.3.5.3 */
            if (!check_params (&list, paramcount, params, 1, I,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            break;
 
          case '\n': /* 22.3.9.3 #\Newline */
          case '_': /* 22.3.5.1 */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            break;
 
          case 'T': case 't': /* 22.3.6.1 FORMAT-TABULATE */
            if (!check_params (&list, paramcount, params, 2, II,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            break;
 
          case '*': /* 22.3.7.1 FORMAT-GOTO */
            if (!check_params (&list, paramcount, params, 1, I,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            {
              int n; /* value of first parameter */
              if (paramcount == 0
@@ -2684,6 +2735,7 @@ parse_upto (const char **formatp,
                  /* invalid argument */
                  *invalid_reason =
                    xasprintf (_("In the directive number %u, the argument %d is negative."), spec->directives, n);
+                 FDI_SET (format - 1, FMTDIR_ERROR);
                  return false;
                }
              if (atsign_p)
@@ -2719,7 +2771,10 @@ parse_upto (const char **formatp,
          case '?': /* 22.3.7.6 FORMAT-INDIRECTION */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_FORMATSTRING);
            if (atsign_p)
@@ -2737,7 +2792,10 @@ parse_upto (const char **formatp,
          case '/': /* 22.3.5.4 FORMAT-CALL-USER-FUNCTION */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_OBJECT);
            while (*format != '\0' && *format != '/')
@@ -2746,6 +2804,7 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xstrdup (_("The string ends in the middle of a ~/.../ directive."));
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            format++;
@@ -2754,7 +2813,10 @@ parse_upto (const char **formatp,
          case '(': /* 22.3.8.1 FORMAT-CASE-CONVERSION */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -2762,8 +2824,12 @@ parse_upto (const char **formatp,
            {
              if (!parse_upto (formatp, positionp, listp, escapep,
                               NULL, spec, ')', false,
-                              invalid_reason))
-               return false;
+                              NULL, invalid_reason))
+               {
+                 FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                          FMTDIR_ERROR);
+                 return false;
+               }
            }
            format = *formatp;
            position = *positionp;
@@ -2776,11 +2842,15 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("Found '~%c' without matching '~%c'."), ')', '(');
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -2792,6 +2862,7 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("In the directive number %u, both the @ and the : modifiers are given."), spec->directives);
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            else if (atsign_p)
@@ -2801,7 +2872,10 @@ parse_upto (const char **formatp,
 
                if (!check_params (&list, paramcount, params, 0, NULL,
                                   spec->directives, invalid_reason))
-                 return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
 
                *formatp = format;
                *escapep = escape;
@@ -2823,8 +2897,12 @@ parse_upto (const char **formatp,
                    (list != NULL ? copy_list (list) : NULL);
                  if (!parse_upto (formatp, &sub_position, &sub_list, escapep,
                                   NULL, spec, ']', false,
-                                  invalid_reason))
-                   return false;
+                                  NULL, invalid_reason))
+                   {
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
+                     return false;
+                   }
                  if (sub_list != NULL)
                    {
                      if (position >= 0)
@@ -2859,7 +2937,10 @@ parse_upto (const char **formatp,
 
                if (!check_params (&list, paramcount, params, 0, NULL,
                                   spec->directives, invalid_reason))
-                 return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
 
                if (position >= 0)
                  add_req_type_constraint (&list, position++, FAT_OBJECT);
@@ -2884,12 +2965,18 @@ parse_upto (const char **formatp,
                    }
                  if (!parse_upto (formatp, &sub_position, &sub_list, escapep,
                                   &sub_separator, spec, ']', true,
-                                  invalid_reason))
-                   return false;
+                                  NULL, invalid_reason))
+                   {
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
+                     return false;
+                   }
                  if (!sub_separator)
                    {
                      *invalid_reason =
                        xasprintf (_("In the directive number %u, '~:[' is not followed by two clauses, separated by '~;'."), spec->directives);
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
                      return false;
                    }
                  if (sub_list != NULL)
@@ -2904,8 +2991,12 @@ parse_upto (const char **formatp,
                    (list != NULL ? copy_list (list) : NULL);
                  if (!parse_upto (formatp, &sub_position, &sub_list, escapep,
                                   NULL, spec, ']', false,
-                                  invalid_reason))
-                   return false;
+                                  NULL, invalid_reason))
+                   {
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
+                     return false;
+                   }
                  if (sub_list != NULL)
                    {
                      if (union_position == -2)
@@ -2935,7 +3026,10 @@ parse_upto (const char **formatp,
 
                if (!check_params (&list, paramcount, params, 1, I,
                                   spec->directives, invalid_reason))
-                 return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
 
                /* If there was no first parameter, an argument is consumed.  */
                arg_position = -1;
@@ -2961,8 +3055,12 @@ parse_upto (const char **formatp,
                    int sub_separator = 0;
                    if (!parse_upto (formatp, &sub_position, &sub_list, escapep,
                                     &sub_separator, spec, ']', !last_alternative,
-                                    invalid_reason))
-                     return false;
+                                    NULL, invalid_reason))
+                     {
+                       FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                                FMTDIR_ERROR);
+                       return false;
+                     }
                    /* If this alternative is chosen, the argument arg_position
                       is an integer, namely the index of this alternative.  */
                    if (!last_alternative && arg_position >= 0)
@@ -3009,11 +3107,15 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("Found '~%c' without matching '~%c'."), ']', '[');
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -3023,7 +3125,10 @@ parse_upto (const char **formatp,
          case '{': /* 22.3.7.4 FORMAT-ITERATION */
            if (!check_params (&list, paramcount, params, 1, I,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            {
              int sub_position = 0;
@@ -3034,8 +3139,12 @@ parse_upto (const char **formatp,
              sub_spec.list = sub_list;
              if (!parse_upto (formatp, &sub_position, &sub_list, &sub_escape,
                               NULL, &sub_spec, '}', false,
-                              invalid_reason))
-               return false;
+                              NULL, invalid_reason))
+               {
+                 FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                          FMTDIR_ERROR);
+                 return false;
+               }
              spec->directives += sub_spec.directives;
 
              /* If the sub-formatstring is empty, except for the terminating
@@ -3115,11 +3224,15 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("Found '~%c' without matching '~%c'."), '}', '{');
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -3129,7 +3242,10 @@ parse_upto (const char **formatp,
          case '<': /* 22.3.6.2, 22.3.5.2 FORMAT-JUSTIFICATION */
            if (!check_params (&list, paramcount, params, 4, IIIC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            {
              struct format_arg_list *sub_escape = NULL;
 
@@ -3142,8 +3258,12 @@ parse_upto (const char **formatp,
                  int sub_separator = 0;
                  if (!parse_upto (formatp, positionp, listp, &sub_escape,
                                   &sub_separator, spec, '>', true,
-                                  invalid_reason))
-                   return false;
+                                  NULL, invalid_reason))
+                   {
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
+                     return false;
+                   }
                  if (!sub_separator)
                    break;
                }
@@ -3164,11 +3284,15 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("Found '~%c' without matching '~%c'."), '>', '<');
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -3178,7 +3302,10 @@ parse_upto (const char **formatp,
          case '^': /* 22.3.9.2 FORMAT-UP-AND-OUT */
            if (!check_params (&list, paramcount, params, 3, THREE,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0 && list != NULL && is_required (list, position))
              /* This ~^ can never be executed.  Ignore it.  */
              break;
@@ -3198,19 +3325,26 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("In the directive number %u, '~;' is used in an invalid position."), spec->directives);
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (terminator == '>')
              {
                if (!check_params (&list, paramcount, params, 1, I,
                                   spec->directives, invalid_reason))
-                  return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
              }
            else
              {
                if (!check_params (&list, paramcount, params, 0, NULL,
                                   spec->directives, invalid_reason))
-                  return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
              }
            *formatp = format;
            *positionp = position;
@@ -3222,7 +3356,10 @@ parse_upto (const char **formatp,
          case '!': /* FORMAT-CALL, a CLISP extension */
            if (!nocheck_params (&list, paramcount, params,
                                 spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              {
                add_req_type_constraint (&list, position++, FAT_FUNCTION);
@@ -3232,13 +3369,22 @@ parse_upto (const char **formatp,
 
          default:
            --format;
-           *invalid_reason =
-             (*format == '\0'
-              ? INVALID_UNTERMINATED_DIRECTIVE ()
-              : INVALID_CONVERSION_SPECIFIER (spec->directives, *format));
+           if (*format == '\0')
+             {
+               *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
+             }
+           else
+             {
+               *invalid_reason =
+                 INVALID_CONVERSION_SPECIFIER (spec->directives, *format);
+               FDI_SET (format, FMTDIR_ERROR);
+             }
            return false;
          }
 
+       FDI_SET (format - 1, FMTDIR_END);
+
        free (params);
       }
 
@@ -3259,7 +3405,8 @@ parse_upto (const char **formatp,
 /* ============== Top level format string handling functions ============== */
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -3272,7 +3419,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
 
   if (!parse_upto (&format, &position, &spec.list, &escape,
                   NULL, &spec, '\0', false,
-                  invalid_reason))
+                  fdi, invalid_reason))
     /* Invalid format string.  */
     return NULL;
 
@@ -3487,7 +3634,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 0857aa4796f8861507f8a305975e66166c1429e8..5ba0d0fe0a0270a307e7a14a880d9d44831fca87 100644 (file)
@@ -103,8 +103,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   unsigned int directives;
   unsigned int numbered_arg_count;
   unsigned int allocated;
@@ -129,6 +131,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
     if (*format++ == '%')
       {
        /* A directive.  */
+       FDI_SET (format - 1, FMTDIR_START);
        directives++;
 
        if (*format != '%')
@@ -241,10 +244,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                type = FAT_INTEGER;
                break;
              default:
-               *invalid_reason =
-                 (*format == '\0'
-                  ? INVALID_UNTERMINATED_DIRECTIVE ()
-                  : INVALID_CONVERSION_SPECIFIER (directives, *format));
+               if (*format == '\0')
+                 {
+                   *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                 }
+               else
+                 {
+                   *invalid_reason =
+                     INVALID_CONVERSION_SPECIFIER (directives, *format);
+                   FDI_SET (format, FMTDIR_ERROR);
+                 }
                goto bad_format;
              }
 
@@ -275,6 +285,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            numbered_arg_count++;
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -519,7 +531,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index dfc45ae197a3a2609e89804d2e50ed42bbff9819..e72aff13aa1bbaa5f26fb98e9648d59fd29c0894 100644 (file)
@@ -60,8 +60,10 @@ named_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
 
@@ -91,6 +93,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                const char *name_end = f;
                size_t n = name_end - name_start;
 
+               FDI_SET (format - 1, FMTDIR_START);
+
                name = XNMALLOC (n + 1, char);
                memcpy (name, name_start, n);
                name[n] = '\0';
@@ -105,6 +109,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                spec.named[spec.named_arg_count].name = name;
                spec.named_arg_count++;
 
+               FDI_SET (f, FMTDIR_END);
+
                format = ++f;
              }
          }
@@ -266,7 +272,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 1c928099b02681d5a567d0f68a242fa2637b9ff5..c87de485c95c9524ed85a9c2611752c5dc173404 100644 (file)
@@ -134,8 +134,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   unsigned int directives;
   unsigned int numbered_arg_count;
   unsigned int allocated;
@@ -158,6 +160,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
        format_arg_type_t type;
        format_arg_type_t size;
 
+       FDI_SET (format - 1, FMTDIR_START);
        directives++;
 
        if (isnonzerodigit (*format))
@@ -429,6 +432,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
              {
                *invalid_reason =
                  xasprintf (_("In the directive number %u, the size specifier is incompatible with the conversion specifier '%c'."), directives, *format);
+               FDI_SET (format, FMTDIR_ERROR);
                goto bad_format;
              }
            type = FAT_DOUBLE | size;
@@ -440,10 +444,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            type = FAT_COUNT_POINTER | size;
            break;
          default:
-           *invalid_reason =
-             (*format == '\0'
-              ? INVALID_UNTERMINATED_DIRECTIVE ()
-              : INVALID_CONVERSION_SPECIFIER (directives, *format));
+           if (*format == '\0')
+             {
+               *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
+             }
+           else
+             {
+               *invalid_reason =
+                 INVALID_CONVERSION_SPECIFIER (directives, *format);
+               FDI_SET (format, FMTDIR_ERROR);
+             }
            goto bad_format;
          }
 
@@ -460,6 +471,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            numbered_arg_count++;
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -731,7 +744,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 601a033d551e6cd5ad69312a3a4315b57bcf7f43..1b0f4a4b9514f05dbc9eccea9781b1b3f554b73c 100644 (file)
@@ -94,8 +94,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   unsigned int directives;
   unsigned int numbered_arg_count;
   unsigned int allocated;
@@ -113,6 +115,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
     if (*format++ == '%')
       {
        /* A directive.  */
+       FDI_SET (format - 1, FMTDIR_START);
        directives++;
 
        if (*format != '%')
@@ -139,6 +142,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (m == 0)
                      {
                        *invalid_reason = INVALID_ARGNO_0 (directives);
+                       FDI_SET (f, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    number = m;
@@ -158,6 +162,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (*format == '\0')
                      {
                        *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    format++;
@@ -208,10 +213,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                type = FAT_STRING;
                break;
              default:
-               *invalid_reason =
-                 (*format == '\0'
-                  ? INVALID_UNTERMINATED_DIRECTIVE ()
-                  : INVALID_CONVERSION_SPECIFIER (directives, *format));
+               if (*format == '\0')
+                 {
+                   *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                 }
+               else
+                 {
+                   *invalid_reason =
+                     INVALID_CONVERSION_SPECIFIER (directives, *format);
+                   FDI_SET (format, FMTDIR_ERROR);
+                 }
                goto bad_format;
              }
 
@@ -225,6 +237,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            numbered_arg_count++;
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -463,7 +477,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index e8a973a5f626f8a070d2923f509a03c960b0b853..3c3148910ad5b1721563fd6a8bc9e869200b198c 100644 (file)
@@ -113,8 +113,10 @@ named_arg_compare (const void *p1, const void *p2)
   xstrdup (_("The string refers to arguments both through argument names and through unnamed argument specifications."))
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
 
@@ -132,6 +134,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
        char *name = NULL;
        enum format_arg_type type;
 
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (*format == '(')
@@ -158,6 +161,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            if (*format == '\0')
              {
                *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
                goto bad_format;
              }
            name_end = format++;
@@ -180,6 +184,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            if (spec.named_arg_count > 0)
              {
                *invalid_reason = INVALID_MIXES_NAMED_UNNAMED ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
                goto bad_format;
              }
 
@@ -208,6 +213,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (spec.named_arg_count > 0)
                  {
                    *invalid_reason = INVALID_MIXES_NAMED_UNNAMED ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
                    goto bad_format;
                  }
 
@@ -246,10 +252,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            type = FAT_FLOAT;
            break;
          default:
-           *invalid_reason =
-             (*format == '\0'
-              ? INVALID_UNTERMINATED_DIRECTIVE ()
-              : INVALID_CONVERSION_SPECIFIER (spec.directives, *format));
+           if (*format == '\0')
+             {
+               *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
+             }
+           else
+             {
+               *invalid_reason =
+                 INVALID_CONVERSION_SPECIFIER (spec.directives, *format);
+               FDI_SET (format, FMTDIR_ERROR);
+             }
            goto bad_format;
          }
 
@@ -261,6 +274,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            if (spec.unnamed_arg_count > 0)
              {
                *invalid_reason = INVALID_MIXES_NAMED_UNNAMED ();
+               FDI_SET (format, FMTDIR_ERROR);
                goto bad_format;
              }
 
@@ -281,6 +295,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            if (spec.named_arg_count > 0)
              {
                *invalid_reason = INVALID_MIXES_NAMED_UNNAMED ();
+               FDI_SET (format, FMTDIR_ERROR);
                goto bad_format;
              }
 
@@ -293,6 +308,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            spec.unnamed_arg_count++;
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -518,7 +535,7 @@ get_python_format_unnamed_arg_count (const char *string)
   /* Parse the format string.  */
   char *invalid_reason = NULL;
   struct spec *descr =
-    (struct spec *) format_parse (string, false, &invalid_reason);
+    (struct spec *) format_parse (string, false, NULL, &invalid_reason);
 
   if (descr != NULL)
     {
@@ -639,7 +656,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 67aad7a594a438f6fbab05fb59c818a1ef3a9028..90cc0f513d60baa08dbecebc5bf8f13d67020258 100644 (file)
@@ -51,8 +51,10 @@ struct spec
 
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
 
@@ -66,6 +68,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
          /* A directive.  */
          unsigned int number;
 
+         FDI_SET (format - 1, FMTDIR_START);
          spec.directives++;
 
          number = *format - '0';
@@ -76,10 +79,13 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            {
              *invalid_reason =
                xasprintf (_("Multiple references to %%%c."), *format);
+             FDI_SET (format, FMTDIR_ERROR);
              goto bad_format;
            }
          spec.args_used[number] = true;
 
+         FDI_SET (format, FMTDIR_END);
+
          format++;
        }
 
@@ -201,7 +207,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 78ee865b93183949b498b56091f61c1739960064..bc021b9d61a83979b8f34a5c54e4569ccb8df3b2 100644 (file)
@@ -2437,6 +2437,7 @@ check_params (struct format_arg_list **listp,
    spec is the global struct spec.
    terminator is the directive that terminates this parse.
    separator specifies if ~; separators are allowed.
+   fdi is an array to be filled with format directive indicators, or NULL.
    If the format string is invalid, false is returned and *invalid_reason is
    set to an error message explaining why.  */
 static bool
@@ -2444,9 +2445,10 @@ parse_upto (const char **formatp,
            int *positionp, struct format_arg_list **listp,
            struct format_arg_list **escapep, int *separatorp,
            struct spec *spec, char terminator, bool separator,
-           char **invalid_reason)
+           char *fdi, char **invalid_reason)
 {
   const char *format = *formatp;
+  const char *const format_start = format;
   int position = *positionp;
   struct format_arg_list *list = *listp;
   struct format_arg_list *escape = *escapep;
@@ -2459,6 +2461,8 @@ parse_upto (const char **formatp,
        unsigned int paramcount = 0;
        struct param *params = NULL;
 
+       FDI_SET (format - 1, FMTDIR_START);
+
        /* Count number of directives.  */
        spec->directives++;
 
@@ -2485,10 +2489,17 @@ parse_upto (const char **formatp,
                format++;
                if (!c_isdigit (*format))
                  {
-                   *invalid_reason =
-                     (*format == '\0'
-                      ? INVALID_UNTERMINATED_DIRECTIVE ()
-                      : xasprintf (_("In the directive number %u, '%c' is not followed by a digit."), spec->directives, format[-1]));
+                   if (*format == '\0')
+                     {
+                       *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
+                     }
+                   else
+                     {
+                       *invalid_reason =
+                         xasprintf (_("In the directive number %u, '%c' is not followed by a digit."), spec->directives, format[-1]);
+                       FDI_SET (format, FMTDIR_ERROR);
+                     }
                    return false;
                  }
                do
@@ -2507,6 +2518,7 @@ parse_upto (const char **formatp,
                if (*format == '\0')
                  {
                    *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
                    return false;
                  }
                format++;
@@ -2563,7 +2575,10 @@ parse_upto (const char **formatp,
          case 'S': case 's': /* 22.3.4.2 FORMAT-S-EXPRESSION */
            if (!check_params (&list, paramcount, params, 4, IIIC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_OBJECT);
            break;
@@ -2571,7 +2586,10 @@ parse_upto (const char **formatp,
          case 'C': case 'c': /* FORMAT-CHARACTER */
            if (!check_params (&list, paramcount, params, 1, I,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (paramcount == 0
                || (paramcount == 1 && params[0].type == PT_NIL))
              if (position >= 0)
@@ -2584,7 +2602,10 @@ parse_upto (const char **formatp,
          case 'X': case 'x': /* 22.3.2.5 FORMAT-HEXADECIMAL */
            if (!check_params (&list, paramcount, params, 4, ICCI,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_INTEGER);
            break;
@@ -2592,7 +2613,10 @@ parse_upto (const char **formatp,
          case 'R': case 'r': /* 22.3.2.1 FORMAT-RADIX */
            if (!check_params (&list, paramcount, params, 5, IICCI,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_INTEGER);
            break;
@@ -2600,7 +2624,10 @@ parse_upto (const char **formatp,
          case 'P': case 'p': /* 22.3.8.3 FORMAT-PLURAL */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (colon_p)
              {
                /* Go back by 1 argument.  */
@@ -2614,7 +2641,10 @@ parse_upto (const char **formatp,
          case 'F': case 'f': /* 22.3.3.1 FORMAT-FIXED-FLOAT */
            if (!check_params (&list, paramcount, params, 5, IIICC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_REAL);
            break;
@@ -2623,7 +2653,10 @@ parse_upto (const char **formatp,
          case 'G': case 'g': /* 22.3.3.3 FORMAT-GENERAL-FLOAT */
            if (!check_params (&list, paramcount, params, 7, IIIICCC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_REAL);
            break;
@@ -2631,7 +2664,10 @@ parse_upto (const char **formatp,
          case '$': /* 22.3.3.4 FORMAT-DOLLARS-FLOAT */
            if (!check_params (&list, paramcount, params, 4, IIIC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_REAL);
            break;
@@ -2639,7 +2675,10 @@ parse_upto (const char **formatp,
          case 'I': case 'i': /* FORMAT-FIXED-FLOAT-COMPLEX */
            if (!check_params (&list, paramcount, params, 5, IIICC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_COMPLEX);
            break;
@@ -2647,7 +2686,10 @@ parse_upto (const char **formatp,
          case 'Y': case 'y': /* FORMAT-PRETTY */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_OBJECT);
            break;
@@ -2660,7 +2702,10 @@ parse_upto (const char **formatp,
          case '~': /* 22.3.1.5 FORMAT-TILDE */
            if (!check_params (&list, paramcount, params, 1, I,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            break;
 
          case '!': /* FORMAT-FORCE-OUTPUT */
@@ -2668,19 +2713,28 @@ parse_upto (const char **formatp,
          case 'Q': case 'q': /* FORMAT-IMPLEMENTATION */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            break;
 
          case 'T': case 't': /* FORMAT-TABULATE */
            if (!check_params (&list, paramcount, params, 3, IIC,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            break;
 
          case '*': /* 22.3.7.1 FORMAT-GOTO */
            if (!check_params (&list, paramcount, params, 1, I,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            {
              int n; /* value of first parameter */
              if (paramcount == 0
@@ -2699,6 +2753,7 @@ parse_upto (const char **formatp,
                  /* invalid argument */
                  *invalid_reason =
                    xasprintf (_("In the directive number %u, the argument %d is negative."), spec->directives, n);
+                 FDI_SET (format - 1, FMTDIR_ERROR);
                  return false;
                }
              if (atsign_p)
@@ -2734,7 +2789,10 @@ parse_upto (const char **formatp,
          case '?': case 'K': case 'k': /* 22.3.7.6 FORMAT-INDIRECTION */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0)
              add_req_type_constraint (&list, position++, FAT_FORMATSTRING);
            if (atsign_p)
@@ -2752,7 +2810,10 @@ parse_upto (const char **formatp,
          case '(': /* 22.3.8.1 FORMAT-CASE-CONVERSION */
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -2760,8 +2821,12 @@ parse_upto (const char **formatp,
            {
              if (!parse_upto (formatp, positionp, listp, escapep,
                               NULL, spec, ')', false,
-                              invalid_reason))
-               return false;
+                              NULL, invalid_reason))
+               {
+                 FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                          FMTDIR_ERROR);
+                 return false;
+               }
            }
            format = *formatp;
            position = *positionp;
@@ -2774,11 +2839,15 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("Found '~%c' without matching '~%c'."), ')', '(');
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -2790,6 +2859,7 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("In the directive number %u, both the @ and the : modifiers are given."), spec->directives);
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            else if (atsign_p)
@@ -2799,7 +2869,10 @@ parse_upto (const char **formatp,
 
                if (!check_params (&list, paramcount, params, 0, NULL,
                                   spec->directives, invalid_reason))
-                 return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
 
                *formatp = format;
                *escapep = escape;
@@ -2821,8 +2894,12 @@ parse_upto (const char **formatp,
                    (list != NULL ? copy_list (list) : NULL);
                  if (!parse_upto (formatp, &sub_position, &sub_list, escapep,
                                   NULL, spec, ']', false,
-                                  invalid_reason))
-                   return false;
+                                  NULL, invalid_reason))
+                   {
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
+                     return false;
+                   }
                  if (sub_list != NULL)
                    {
                      if (position >= 0)
@@ -2857,7 +2934,10 @@ parse_upto (const char **formatp,
 
                if (!check_params (&list, paramcount, params, 0, NULL,
                                   spec->directives, invalid_reason))
-                 return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
 
                if (position >= 0)
                  add_req_type_constraint (&list, position++, FAT_OBJECT);
@@ -2882,12 +2962,18 @@ parse_upto (const char **formatp,
                    }
                  if (!parse_upto (formatp, &sub_position, &sub_list, escapep,
                                   &sub_separator, spec, ']', true,
-                                  invalid_reason))
-                   return false;
+                                  NULL, invalid_reason))
+                   {
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
+                     return false;
+                   }
                  if (!sub_separator)
                    {
                      *invalid_reason =
                        xasprintf (_("In the directive number %u, '~:[' is not followed by two clauses, separated by '~;'."), spec->directives);
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
                      return false;
                    }
                  if (sub_list != NULL)
@@ -2902,8 +2988,12 @@ parse_upto (const char **formatp,
                    (list != NULL ? copy_list (list) : NULL);
                  if (!parse_upto (formatp, &sub_position, &sub_list, escapep,
                                   NULL, spec, ']', false,
-                                  invalid_reason))
-                   return false;
+                                  NULL, invalid_reason))
+                   {
+                     FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                              FMTDIR_ERROR);
+                     return false;
+                   }
                  if (sub_list != NULL)
                    {
                      if (union_position == -2)
@@ -2933,7 +3023,10 @@ parse_upto (const char **formatp,
 
                if (!check_params (&list, paramcount, params, 1, I,
                                   spec->directives, invalid_reason))
-                 return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
 
                /* If there was no first parameter, an argument is consumed.  */
                arg_position = -1;
@@ -2959,8 +3052,12 @@ parse_upto (const char **formatp,
                    int sub_separator = 0;
                    if (!parse_upto (formatp, &sub_position, &sub_list, escapep,
                                     &sub_separator, spec, ']', !last_alternative,
-                                    invalid_reason))
-                     return false;
+                                    NULL, invalid_reason))
+                     {
+                       FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                                FMTDIR_ERROR);
+                       return false;
+                     }
                    /* If this alternative is chosen, the argument arg_position
                       is an integer, namely the index of this alternative.  */
                    if (!last_alternative && arg_position >= 0)
@@ -3007,11 +3104,15 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("Found '~%c' without matching '~%c'."), ']', '[');
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -3021,7 +3122,10 @@ parse_upto (const char **formatp,
          case '{': /* 22.3.7.4 FORMAT-ITERATION */
            if (!check_params (&list, paramcount, params, 1, I,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            {
              int sub_position = 0;
@@ -3032,8 +3136,12 @@ parse_upto (const char **formatp,
              sub_spec.list = sub_list;
              if (!parse_upto (formatp, &sub_position, &sub_list, &sub_escape,
                               NULL, &sub_spec, '}', false,
-                              invalid_reason))
-               return false;
+                              NULL, invalid_reason))
+               {
+                 FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp,
+                          FMTDIR_ERROR);
+                 return false;
+               }
              spec->directives += sub_spec.directives;
 
              /* If the sub-formatstring is empty, except for the terminating
@@ -3113,11 +3221,15 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("Found '~%c' without matching '~%c'."), '}', '{');
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (!check_params (&list, paramcount, params, 0, NULL,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            *formatp = format;
            *positionp = position;
            *listp = list;
@@ -3127,7 +3239,10 @@ parse_upto (const char **formatp,
          case '^': /* 22.3.9.2 FORMAT-UP-AND-OUT */
            if (!check_params (&list, paramcount, params, 3, THREE,
                               spec->directives, invalid_reason))
-             return false;
+             {
+               FDI_SET (format - 1, FMTDIR_ERROR);
+               return false;
+             }
            if (position >= 0 && list != NULL && is_required (list, position))
              /* This ~^ can never be executed.  Ignore it.  */
              break;
@@ -3147,19 +3262,26 @@ parse_upto (const char **formatp,
              {
                *invalid_reason =
                  xasprintf (_("In the directive number %u, '~;' is used in an invalid position."), spec->directives);
+               FDI_SET (format - 1, FMTDIR_ERROR);
                return false;
              }
            if (terminator == '>')
              {
                if (!check_params (&list, paramcount, params, 1, I,
                                   spec->directives, invalid_reason))
-                  return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
              }
            else
              {
                if (!check_params (&list, paramcount, params, 0, NULL,
                                   spec->directives, invalid_reason))
-                  return false;
+                 {
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                   return false;
+                 }
              }
            *formatp = format;
            *positionp = position;
@@ -3170,13 +3292,22 @@ parse_upto (const char **formatp,
 
          default:
            --format;
-           *invalid_reason =
-             (*format == '\0'
-              ? INVALID_UNTERMINATED_DIRECTIVE ()
-              : INVALID_CONVERSION_SPECIFIER (spec->directives, *format));
+           if (*format == '\0')
+             {
+               *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
+             }
+           else
+             {
+               *invalid_reason =
+                 INVALID_CONVERSION_SPECIFIER (spec->directives, *format);
+               FDI_SET (format, FMTDIR_ERROR);
+             }
            return false;
          }
 
+       FDI_SET (format - 1, FMTDIR_END);
+
        free (params);
       }
 
@@ -3197,7 +3328,8 @@ parse_upto (const char **formatp,
 /* ============== Top level format string handling functions ============== */
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
   struct spec spec;
   struct spec *result;
@@ -3210,7 +3342,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
 
   if (!parse_upto (&format, &position, &spec.list, &escape,
                   NULL, &spec, '\0', false,
-                  invalid_reason))
+                  fdi, invalid_reason))
     /* Invalid format string.  */
     return NULL;
 
@@ -3425,7 +3557,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 8390e7226c6a484197b9b21b4bd72ff89731722e..097be8c4bf447f6d11731c8b904cd94ef01c9e30 100644 (file)
@@ -86,8 +86,10 @@ named_arg_compare (const void *p1, const void *p2)
   xstrdup (_("The string refers to a shell variable with an empty name."))
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
 
@@ -102,6 +104,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
        /* A variable substitution.  */
        char *name;
 
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (*format == '{')
@@ -118,6 +121,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (!c_isascii (*format))
                  {
                    *invalid_reason = INVALID_NON_ASCII_VARIABLE ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
                if (format > name_start
@@ -125,18 +129,21 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                        || *format == '?' || *format == ':'))
                  {
                    *invalid_reason = INVALID_SHELL_SYNTAX ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
                if (!(c_isalnum (*format) || *format == '_')
                    || (format == name_start && c_isdigit (*format)))
                  {
                    *invalid_reason = INVALID_CONTEXT_DEPENDENT_VARIABLE ();
+                   FDI_SET (format, FMTDIR_ERROR);
                    goto bad_format;
                  }
              }
            if (*format == '\0')
              {
                *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
                goto bad_format;
              }
            name_end = format++;
@@ -145,6 +152,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            if (n == 0)
              {
                *invalid_reason = INVALID_EMPTY_VARIABLE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
                goto bad_format;
              }
            name = XNMALLOC (n + 1, char);
@@ -173,17 +181,20 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            if (!c_isascii (*format))
              {
                *invalid_reason = INVALID_NON_ASCII_VARIABLE ();
+               FDI_SET (format, FMTDIR_ERROR);
                goto bad_format;
              }
            else
              {
                *invalid_reason = INVALID_CONTEXT_DEPENDENT_VARIABLE ();
+               FDI_SET (format, FMTDIR_ERROR);
                goto bad_format;
              }
          }
        else
          {
            *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+           FDI_SET (format - 1, FMTDIR_ERROR);
            goto bad_format;
          }
 
@@ -195,6 +206,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
          }
        spec.named[spec.named_arg_count].name = name;
        spec.named_arg_count++;
+
+       FDI_SET (format - 1, FMTDIR_END);
       }
 
   /* Sort the named argument array, and eliminate duplicates.  */
@@ -367,7 +380,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index f98add8a912bf428cca54015a875149e84adf6e9..35831f14820b7fe078459c3a580607facc417fa5 100644 (file)
@@ -98,8 +98,10 @@ numbered_arg_compare (const void *p1, const void *p2)
 }
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
   bool seen_numbered_arg;
@@ -118,6 +120,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
     if (*format++ == '%')
       {
        /* A directive.  */
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (*format != '%')
@@ -144,6 +147,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (m == 0)
                      {
                        *invalid_reason = INVALID_ARGNO_0 (spec.directives);
+                       FDI_SET (f, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    number = m;
@@ -153,6 +157,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                    if (seen_unnumbered_arg)
                      {
                        *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                       FDI_SET (format - 1, FMTDIR_ERROR);
                        goto bad_format;
                      }
                    is_numbered_arg = true;
@@ -166,6 +171,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                if (seen_numbered_arg)
                  {
                    *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
                    goto bad_format;
                  }
                seen_unnumbered_arg = true;
@@ -248,10 +254,17 @@ format_parse (const char *format, bool translated, char **invalid_reason)
                type = FAT_FLOAT;
                break;
              default:
-               *invalid_reason =
-                 (*format == '\0'
-                  ? INVALID_UNTERMINATED_DIRECTIVE ()
-                  : INVALID_CONVERSION_SPECIFIER (spec.directives, *format));
+               if (*format == '\0')
+                 {
+                   *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+                   FDI_SET (format - 1, FMTDIR_ERROR);
+                 }
+               else
+                 {
+                   *invalid_reason =
+                     INVALID_CONVERSION_SPECIFIER (spec.directives, *format);
+                   FDI_SET (format, FMTDIR_ERROR);
+                 }
                goto bad_format;
              }
 
@@ -267,6 +280,8 @@ format_parse (const char *format, bool translated, char **invalid_reason)
            number++;
          }
 
+       FDI_SET (format, FMTDIR_END);
+
        format++;
       }
 
@@ -511,7 +526,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 8929cffaac2fafe42acaf668594adc69f37b0ebb..7f8f83d568888df34ee88cdbca22b4c29a1bf2fa 100644 (file)
@@ -48,8 +48,10 @@ struct spec
 
 
 static void *
-format_parse (const char *format, bool translated, char **invalid_reason)
+format_parse (const char *format, bool translated, char *fdi,
+             char **invalid_reason)
 {
+  const char *const format_start = format;
   struct spec spec;
   struct spec *result;
 
@@ -60,6 +62,7 @@ format_parse (const char *format, bool translated, char **invalid_reason)
     if (*format++ == '%')
       {
        /* A directive.  */
+       FDI_SET (format - 1, FMTDIR_START);
        spec.directives++;
 
        if (*format == '%')
@@ -76,14 +79,23 @@ format_parse (const char *format, bool translated, char **invalid_reason)
          }
        else
          {
-           *invalid_reason =
-             (*format == '\0'
-              ? INVALID_UNTERMINATED_DIRECTIVE ()
-              : (c_isprint (*format)
-                 ? xasprintf (_("In the directive number %u, the character '%c' is not a digit between 1 and 9."), spec.directives, *format)
-                 : xasprintf (_("The character that terminates the directive number %u is not a digit between 1 and 9."), spec.directives)));
+           if (*format == '\0')
+             {
+               *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE ();
+               FDI_SET (format - 1, FMTDIR_ERROR);
+             }
+           else
+             {
+               *invalid_reason =
+                 (c_isprint (*format)
+                  ? xasprintf (_("In the directive number %u, the character '%c' is not a digit between 1 and 9."), spec.directives, *format)
+                  : xasprintf (_("The character that terminates the directive number %u is not a digit between 1 and 9."), spec.directives));
+               FDI_SET (format, FMTDIR_ERROR);
+             }
            goto bad_format;
          }
+
+       FDI_SET (format - 1, FMTDIR_END);
       }
 
   result = XMALLOC (struct spec);
@@ -212,7 +224,7 @@ main ()
        line[--line_len] = '\0';
 
       invalid_reason = NULL;
-      descr = format_parse (line, false, &invalid_reason);
+      descr = format_parse (line, false, NULL, &invalid_reason);
 
       format_print (descr);
       printf ("\n");
index 198707a3f65db6b0ff96fce07ab4c44bb3305f82..2e4fbac6f73751dc69a184edeea6eceb5648e1e3 100644 (file)
@@ -99,7 +99,7 @@ check_msgid_msgstr_format (const char *msgid, const char *msgid_plural,
        char *invalid_reason = NULL;
        void *msgid_descr =
          parser->parse (msgid_plural != NULL ? msgid_plural : msgid,
-                        false, &invalid_reason);
+                        false, NULL, &invalid_reason);
 
        if (msgid_descr != NULL)
          {
@@ -119,7 +119,7 @@ check_msgid_msgstr_format (const char *msgid, const char *msgid_plural,
                    pretty_msgstr = buf;
                  }
 
-               msgstr_descr = parser->parse (p, true, &invalid_reason);
+               msgstr_descr = parser->parse (p, true, NULL, &invalid_reason);
 
                if (msgstr_descr != NULL)
                  {
index 112f1ae20924b9e4e69e61355a043e0c15ba97bb..6502325a4b98901bf02804e255e05bde7dd64d42 100644 (file)
@@ -31,6 +31,26 @@ extern "C" {
 #endif
 
 
+/* These indicators are set by the parse function at the appropriate
+   positions.  */
+enum
+{
+  /* Set on the first byte of a format directive.  */
+  FMTDIR_START  = 1 << 0,
+  /* Set on the last byte of a format directive.  */
+  FMTDIR_END    = 1 << 1,
+  /* Set on the last byte of an invalid format directive, where a parse error
+     was recognized.  */
+  FMTDIR_ERROR  = 1 << 2
+};
+
+/* Macro for use inside a parser:
+   Sets an indicator at the position corresponding to PTR.
+   Assumes local variables 'fdi' and 'format_start' are defined.  */
+#define FDI_SET(ptr, flag) \
+  if (fdi != NULL) \
+    fdi[(ptr) - format_start] |= (flag)/*;*/
+
 /* This type of callback is responsible for showing an error.  */
 typedef void (*formatstring_error_logger_t) (const char *format, ...)
 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
@@ -44,12 +64,14 @@ struct formatstring_parser
   /* Parse the given string as a format string.
      If translated is true, some extensions available only to msgstr but not
      to msgid strings are recognized.
+     If fdi is non-NULL, it must be a an array of strlen (string) zero bytes.
      Return a freshly allocated structure describing
        1. the argument types/names needed for the format string,
        2. the total number of format directives.
      Return NULL if the string is not a valid format string. In this case,
-     also set *invalid_reason to an error message explaining why.  */
-  void * (*parse) (const char *string, bool translated, char **invalid_reason);
+     also set *invalid_reason to an error message explaining why.
+     In both cases, set FMTDIR_* bits at the appropriate positions in fdi.  */
+  void * (*parse) (const char *string, bool translated, char *fdi, char **invalid_reason);
 
   /* Free a format string descriptor, returned by parse().  */
   void (*free) (void *descr);
index e51a62e7e6492c4afb0ba6cb7ee46d95cd2f3bb8..ad12d3774b7513da319e452c3598035d279e2499 100644 (file)
@@ -738,7 +738,7 @@ msgfmt_check_pair_fails (const lex_pos_ty *pos,
   struct formatstring_parser *parser = formatstring_parsers[fmt];
   char *invalid_reason = NULL;
   void *msgid_descr =
-    parser->parse (msgid_plural != NULL ? msgid_plural : msgid, false,
+    parser->parse (msgid_plural != NULL ? msgid_plural : msgid, false, NULL,
                   &invalid_reason);
 
   failure = false;
@@ -749,7 +749,8 @@ msgfmt_check_pair_fails (const lex_pos_ty *pos,
 
       for (p = msgstr; p < p_end; p += strlen (p) + 1)
        {
-         void *msgstr_descr = parser->parse (msgstr, true, &invalid_reason);
+         void *msgstr_descr =
+           parser->parse (msgstr, true, NULL, &invalid_reason);
 
          if (msgstr_descr != NULL)
            {
index 6f2b392f8588f3d7e3fde9a9dcbc5390bfb4ad93..7129e2692f6e3503f971f7355a6add6cfffd028b 100644 (file)
@@ -404,7 +404,8 @@ read_mo_file (message_list_ty *mlp, const char *filename)
                  for (str = msgid; str < str_end; str += strlen (str) + 1)
                    {
                      char *invalid_reason = NULL;
-                     void *descr = parser->parse (str, false, &invalid_reason);
+                     void *descr =
+                       parser->parse (str, false, NULL, &invalid_reason);
 
                      if (descr != NULL)
                        parser->free (descr);
@@ -422,7 +423,7 @@ read_mo_file (message_list_ty *mlp, const char *filename)
                        {
                          char *invalid_reason = NULL;
                          void *descr =
-                           parser->parse (str, true, &invalid_reason);
+                           parser->parse (str, true, NULL, &invalid_reason);
 
                          if (descr != NULL)
                            parser->free (descr);
index 49bede3cfe014d01050d25c83ec5e7b3b9041ef6..be4bec15f1ee4dfeba9c71c030be8f8a4e622a2b 100644 (file)
@@ -1899,7 +1899,7 @@ set_format_flags_from_context (enum is_format is_format[NFORMATS],
          {
            struct formatstring_parser *parser = formatstring_parsers[i];
            char *invalid_reason = NULL;
-           void *descr = parser->parse (string, false, &invalid_reason);
+           void *descr = parser->parse (string, false, NULL, &invalid_reason);
 
            if (descr != NULL)
              parser->free (descr);
@@ -2156,7 +2156,7 @@ meta information, not the empty string.\n")));
        {
          struct formatstring_parser *parser = formatstring_parsers[i];
          char *invalid_reason = NULL;
-         void *descr = parser->parse (mp->msgid, false, &invalid_reason);
+         void *descr = parser->parse (mp->msgid, false, NULL, &invalid_reason);
 
          if (descr != NULL)
            {
@@ -2269,7 +2269,7 @@ remember_a_message_plural (message_ty *mp, char *string,
            struct formatstring_parser *parser = formatstring_parsers[i];
            char *invalid_reason = NULL;
            void *descr =
-             parser->parse (mp->msgid_plural, false, &invalid_reason);
+             parser->parse (mp->msgid_plural, false, NULL, &invalid_reason);
 
            if (descr != NULL)
              {