]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Recognize $(...) syntax also inside double-quotes.
authorBruno Haible <bruno@clisp.org>
Thu, 22 Jun 2006 11:26:07 +0000 (11:26 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:13:26 +0000 (12:13 +0200)
gettext-tools/src/ChangeLog
gettext-tools/src/x-sh.c
gettext-tools/tests/ChangeLog
gettext-tools/tests/Makefile.am

index 065afdc2cb5ce9be65027627c748661c5af6b086..7e6b2a2090cab5512b5cac9b9d2699560bd00232 100644 (file)
@@ -1,3 +1,9 @@
+2006-06-21  Bruno Haible  <bruno@clisp.org>
+
+       * x-sh.c (read_word): Recognize $(...) and $((...)) also inside
+       double-quoted strings. 
+       Reported by Michelle Konzack <linux4michelle@freenet.de>.
+
 2006-06-04  Bruno Haible  <bruno@clisp.org>
 
        * msgl-check.c (check_plural_eval): Declare 'distribution' as volatile,
index 45bef34b453ce42a7a8bd39931a3ae2630c50776..8b18d40bc07144646bf0f43b1df2aca26784f520 100644 (file)
@@ -503,6 +503,9 @@ is_operator_start (int c)
 #define OPENING_BACKQUOTE (2 * (UCHAR_MAX + 1) + '`')
 #define CLOSING_BACKQUOTE (3 * (UCHAR_MAX + 1) + '`')
 
+/* 2 characters of pushback are supported.
+   2 characters of pushback occur only when the first is an 'x'; in all
+   other cases only one character of pushback is needed.  */
 static int phase2_pushback[2];
 static int phase2_pushback_length;
 
@@ -835,10 +838,39 @@ read_word (struct word *wp, int looking_for, flag_context_ty context)
 
       if (c == '$')
        {
-         int c2 = phase2_getc ();
+         int c2;
+
+         /* An unquoted dollar indicates we are not inside '...'.  */
+         if (open_singlequote)
+           abort ();
+         /* After reading a dollar, we know that there is no pushed back
+            character from an earlier lookahead.  */
+         if (phase2_pushback_length > 0)
+           abort ();
+         /* Therefore we can use phase1 without interfering with phase2.
+            We need to recognize $( outside and inside double-quotes.
+            It would be incorrect to do
+               c2 = phase2_getc ();
+               if (c2 == '(' || c2 == QUOTED ('('))
+            because that would also trigger for $\(.  */
+         c2 = phase1_getc ();
          if (c2 == '(')
            {
-             int c3 = phase2_getc ();
+             bool saved_open_doublequote;
+             int c3;
+
+             phase1_ungetc (c2);
+
+             /* The entire inner command or arithmetic expression is read
+                ignoring possible surrounding double-quotes.  */
+             saved_open_doublequote = open_doublequote;
+             open_doublequote = false;
+
+             c2 = phase2_getc ();
+             if (c2 != '(')
+               abort ();
+
+             c3 = phase2_getc ();
              if (c3 == '(')
                {
                  /* Arithmetic expression.  Skip until the matching closing
@@ -862,178 +894,187 @@ read_word (struct word *wp, int looking_for, flag_context_ty context)
                  phase2_ungetc (c3);
                  read_command_list (')', context);
                }
+
+             open_doublequote = saved_open_doublequote;
            }
-         else if (c2 == '\'' && !open_singlequote)
+         else
            {
-             /* Bash builtin for string with ANSI-C escape sequences.  */
-             saw_opening_singlequote ();
-             for (;;)
+             phase1_ungetc (c2);
+             c2 = phase2_getc ();
+
+             if (c2 == '\'' && !open_singlequote)
                {
-                 c = phase2_getc ();
-                 if (c == EOF)
-                   break;
-                 if (c == '\'')
-                   {
-                     saw_closing_singlequote ();
-                     break;
-                   }
-                 if (c == '\\')
+                 /* Bash builtin for string with ANSI-C escape sequences.  */
+                 saw_opening_singlequote ();
+                 for (;;)
                    {
                      c = phase2_getc ();
-                     switch (c)
+                     if (c == EOF)
+                       break;
+                     if (c == '\'')
                        {
-                       default:
-                         phase2_ungetc (c);
-                         c = '\\';
-                         break;
-
-                       case '\\':
-                         break;
-                       case '\'':
-                         /* Don't call saw_closing_singlequote () here.  */
-                         break;
-
-                       case 'a':
-                         c = '\a';
-                         break;
-                       case 'b':
-                         c = '\b';
-                         break;
-                       case 'e':
-                         c = 0x1b; /* ESC */
-                         break;
-                       case 'f':
-                         c = '\f';
-                         break;
-                       case 'n':
-                         c = '\n';
+                         saw_closing_singlequote ();
                          break;
-                       case 'r':
-                         c = '\r';
-                         break;
-                       case 't':
-                         c = '\t';
-                         break;
-                       case 'v':
-                         c = '\v';
-                         break;
-
-                       case 'x':
+                       }
+                     if (c == '\\')
+                       {
                          c = phase2_getc ();
-                         if ((c >= '0' && c <= '9')
-                             || (c >= 'A' && c <= 'F')
-                             || (c >= 'a' && c <= 'f'))
+                         switch (c)
                            {
-                             int n;
-
-                             if (c >= '0' && c <= '9')
-                               n = c - '0';
-                             else if (c >= 'A' && c <= 'F')
-                               n = 10 + c - 'A';
-                             else if (c >= 'a' && c <= 'f')
-                               n = 10 + c - 'a';
-                             else
-                               abort ();
-
+                           default:
+                             phase2_ungetc (c);
+                             c = '\\';
+                             break;
+
+                           case '\\':
+                             break;
+                           case '\'':
+                             /* Don't call saw_closing_singlequote ()
+                                here.  */
+                             break;
+
+                           case 'a':
+                             c = '\a';
+                             break;
+                           case 'b':
+                             c = '\b';
+                             break;
+                           case 'e':
+                             c = 0x1b; /* ESC */
+                             break;
+                           case 'f':
+                             c = '\f';
+                             break;
+                           case 'n':
+                             c = '\n';
+                             break;
+                           case 'r':
+                             c = '\r';
+                             break;
+                           case 't':
+                             c = '\t';
+                             break;
+                           case 'v':
+                             c = '\v';
+                             break;
+
+                           case 'x':
                              c = phase2_getc ();
                              if ((c >= '0' && c <= '9')
                                  || (c >= 'A' && c <= 'F')
                                  || (c >= 'a' && c <= 'f'))
                                {
+                                 int n;
+
                                  if (c >= '0' && c <= '9')
-                                   n = n * 16 + c - '0';
+                                   n = c - '0';
                                  else if (c >= 'A' && c <= 'F')
-                                   n = n * 16 + 10 + c - 'A';
+                                   n = 10 + c - 'A';
                                  else if (c >= 'a' && c <= 'f')
-                                   n = n * 16 + 10 + c - 'a';
+                                   n = 10 + c - 'a';
                                  else
                                    abort ();
-                               }
-                             else
-                               phase2_ungetc (c);
 
-                             c = n;
-                           }
-                         else
-                           {
-                             phase2_ungetc (c);
-                             phase2_ungetc ('x');
-                             c = '\\';
-                           }
-                         break;
+                                 c = phase2_getc ();
+                                 if ((c >= '0' && c <= '9')
+                                     || (c >= 'A' && c <= 'F')
+                                     || (c >= 'a' && c <= 'f'))
+                                   {
+                                     if (c >= '0' && c <= '9')
+                                       n = n * 16 + c - '0';
+                                     else if (c >= 'A' && c <= 'F')
+                                       n = n * 16 + 10 + c - 'A';
+                                     else if (c >= 'a' && c <= 'f')
+                                       n = n * 16 + 10 + c - 'a';
+                                     else
+                                       abort ();
+                                   }
+                                 else
+                                   phase2_ungetc (c);
 
-                       case '0': case '1': case '2': case '3':
-                       case '4': case '5': case '6': case '7':
-                         {
-                           int n = c - '0';
+                                 c = n;
+                               }
+                             else
+                               {
+                                 phase2_ungetc (c);
+                                 phase2_ungetc ('x');
+                                 c = '\\';
+                               }
+                             break;
 
-                           c = phase2_getc ();
-                           if (c >= '0' && c <= '7')
+                           case '0': case '1': case '2': case '3':
+                           case '4': case '5': case '6': case '7':
                              {
-                               n = n * 8 + c - '0';
+                               int n = c - '0';
 
                                c = phase2_getc ();
                                if (c >= '0' && c <= '7')
-                                 n = n * 8 + c - '0';
+                                 {
+                                   n = n * 8 + c - '0';
+
+                                   c = phase2_getc ();
+                                   if (c >= '0' && c <= '7')
+                                     n = n * 8 + c - '0';
+                                   else
+                                     phase2_ungetc (c);
+                                 }
                                else
                                  phase2_ungetc (c);
-                             }
-                           else
-                             phase2_ungetc (c);
 
-                           c = n;
-                         }
-                         break;
+                               c = n;
+                             }
+                             break;
+                           }
+                       }
+                     if (wp->type == t_string)
+                       {
+                         grow_token (wp->token);
+                         wp->token->chars[wp->token->charcount++] =
+                           (unsigned char) c;
                        }
                    }
-                 if (wp->type == t_string)
-                   {
-                     grow_token (wp->token);
-                     wp->token->chars[wp->token->charcount++] =
-                       (unsigned char) c;
-                   }
+                 /* The result is a literal string.  Don't change wp->type.  */
+                 continue;
                }
-             /* The result is a literal string.  Don't change wp->type.  */
-             continue;
-           }
-         else if (c2 == '"' && !open_doublequote)
-           {
-             /* Bash builtin for internationalized string.  */
-             lex_pos_ty pos;
-             struct token string;
-
-             saw_opening_singlequote ();
-             open_singlequote_terminator = '"';
-             pos.file_name = logical_file_name;
-             pos.line_number = line_number;
-             init_token (&string);
-             for (;;)
+             else if (c2 == '"' && !open_doublequote)
                {
-                 c = phase2_getc ();
-                 if (c == EOF)
-                   break;
-                 if (c == '"')
+                 /* Bash builtin for internationalized string.  */
+                 lex_pos_ty pos;
+                 struct token string;
+
+                 saw_opening_singlequote ();
+                 open_singlequote_terminator = '"';
+                 pos.file_name = logical_file_name;
+                 pos.line_number = line_number;
+                 init_token (&string);
+                 for (;;)
                    {
-                     saw_closing_singlequote ();
-                     break;
+                     c = phase2_getc ();
+                     if (c == EOF)
+                       break;
+                     if (c == '"')
+                       {
+                         saw_closing_singlequote ();
+                         break;
+                       }
+                     grow_token (&string);
+                     string.chars[string.charcount++] = (unsigned char) c;
                    }
-                 grow_token (&string);
-                 string.chars[string.charcount++] = (unsigned char) c;
-               }
-             remember_a_message (mlp, NULL, string_of_token (&string),
-                                 context, &pos, savable_comment);
-             free_token (&string);
+                 remember_a_message (mlp, NULL, string_of_token (&string),
+                                     context, &pos, savable_comment);
+                 free_token (&string);
 
-             error_with_progname = false;
-             error (0, 0, _("%s:%lu: warning: the syntax $\"...\" is deprecated due to security reasons; use eval_gettext instead"),
-                    pos.file_name, (unsigned long) pos.line_number);
-             error_with_progname = true;
+                 error_with_progname = false;
+                 error (0, 0, _("%s:%lu: warning: the syntax $\"...\" is deprecated due to security reasons; use eval_gettext instead"),
+                        pos.file_name, (unsigned long) pos.line_number);
+                 error_with_progname = true;
 
-             /* The result at runtime is not constant. Therefore we
-                change wp->type.  */
+                 /* The result at runtime is not constant. Therefore we
+                    change wp->type.  */
+               }
+             else
+               phase2_ungetc (c2);
            }
-         else
-           phase2_ungetc (c2);
          wp->type = t_other;
          continue;
        }
index fae9dcaf033ebad1c2a01128ada51144edcd89c6..2b79cad12ac32c4eedd6748c539caa8b622ea396 100644 (file)
@@ -1,3 +1,8 @@
+2006-06-21  Bruno Haible  <bruno@clisp.org>
+
+       * xgettext-sh-5: New file.
+       * Makefile.am (TESTS): Add it.
+
 2006-06-17  Bruno Haible  <bruno@clisp.org>
 
        * recode-sr-latin-2 (LOCALE_JA_EUCJP): Determine locale name depending
index 92c162de84603f5b38bbfbca42b309ffc54b71ab..31aeb1fb8b38766242d2fe857bce901c803e3287 100644 (file)
@@ -84,7 +84,7 @@ TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 gettext-6 gettext-7 \
        xgettext-properties-1 \
        xgettext-python-1 xgettext-python-2 xgettext-python-3 \
        xgettext-scheme-1 \
-       xgettext-sh-1 xgettext-sh-2 xgettext-sh-3 xgettext-sh-4 \
+       xgettext-sh-1 xgettext-sh-2 xgettext-sh-3 xgettext-sh-4 xgettext-sh-5 \
        xgettext-smalltalk-1 \
        xgettext-stringtable-1 \
        xgettext-tcl-1 xgettext-tcl-2 \