]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
c: Support C++11 string literals
authorDaiki Ueno <ueno@gnu.org>
Tue, 2 Dec 2014 06:11:26 +0000 (15:11 +0900)
committerDaiki Ueno <ueno@gnu.org>
Tue, 2 Dec 2014 08:14:43 +0000 (17:14 +0900)
* x-c.c (phase5_get): Recognize C++ string literals, defined in
ISO/IEC 9899:2011.  Reported at:
<https://savannah.gnu.org/bugs/?39499>.

gettext-tools/src/ChangeLog
gettext-tools/src/x-c.c

index 4fb7bdbf0b0f102ffbe7c19e41ec22f6344f7d66..8b46953478e2cef71ae3ad115667ffd9586a421f 100644 (file)
@@ -1,3 +1,10 @@
+2014-12-02  Daiki Ueno  <ueno@gnu.org>
+
+       c: Support C++11 string literals
+       * x-c.c (phase5_get): Recognize C++ string literals, defined in
+       ISO/IEC 9899:2011.  Reported at:
+       <https://savannah.gnu.org/bugs/?39499>.
+
 2014-12-01  Daiki Ueno  <ueno@gnu.org>
 
        c#: Recognize Unicode surrogate character pair
index a5978c9f63764a1f320df5e92567dc26d274d291..5ce6f49345cae35de001a37f4dde92d2c4f933a2 100644 (file)
@@ -1097,6 +1097,7 @@ phase5_get (token_ty *tp)
   int bufpos;
   int c;
   int last_was_backslash;
+  bool raw_expected = false;
 
   if (phase5_pushback_length)
     {
@@ -1176,6 +1177,52 @@ phase5_get (token_ty *tp)
               continue;
 
             default:
+              /* Recognize C++ string literals prefixed by R, u8, u8R,
+                 u, uR, U, UR, L, or LR.  It is defined in ISO/IEC
+                 9899:2011 2.14.5.  Since gettext's argument is a byte
+                 sequence, we are only interested in u8, R, and u8R.  */
+              if (c == '"')
+                {
+                  bool is_prefix = false;
+
+                  switch (buffer[0])
+                    {
+                    case 'R':
+                      if (bufpos == 1)
+                        is_prefix = true;
+                      break;
+                    case 'u':
+                      if (bufpos == 1)
+                        is_prefix = true;
+                      else
+                        switch (buffer[1])
+                          {
+                          case 'R':
+                            if (bufpos == 2)
+                              is_prefix = true;
+                            break;
+                          case '8':
+                            if (bufpos == 2
+                                || (bufpos == 3 && buffer[2] == 'R'))
+                              is_prefix = true;
+                            break;
+                          }
+                      break;
+                    case 'U':
+                    case 'L':
+                      if (bufpos == 1
+                          || (bufpos == 2 && buffer[1] == 'R'))
+                        is_prefix = true;
+                      break;
+                    }
+
+                  if (is_prefix)
+                    {
+                      raw_expected = is_prefix && buffer[bufpos - 1] == 'R';
+                      bufpos = 0;
+                      goto string;
+                    }
+                }
               phase4_ungetc (c);
               break;
             }
@@ -1309,6 +1356,7 @@ phase5_get (token_ty *tp)
 
     case '"':
       {
+      string:
         /* We could worry about the 'L' before wide string constants,
            but since gettext's argument is not a wide character string,
            let the compiler complain about the argument not matching the
@@ -1335,21 +1383,26 @@ phase5_get (token_ty *tp)
                 last_was_backslash = true;
                 /* FALLTHROUGH */
               default:
-                if (bufpos >= bufmax)
+                if (c == '\n' && !raw_expected)
                   {
-                    bufmax = 2 * bufmax + 10;
-                    buffer = xrealloc (buffer, bufmax);
+                    error_with_progname = false;
+                    error (0, 0, _("%s:%d: warning: unterminated string literal"),
+                           logical_file_name, line_number - 1);
+                    error_with_progname = true;
+                    phase3_ungetc ('\n');
+                    break;
+                  }
+                else
+                  {
+                    if (bufpos >= bufmax)
+                      {
+                        bufmax = 2 * bufmax + 10;
+                        buffer = xrealloc (buffer, bufmax);
+                      }
+                    buffer[bufpos++] = c;
+                    continue;
                   }
-                buffer[bufpos++] = c;
-                continue;
 
-              case '\n':
-                error_with_progname = false;
-                error (0, 0, _("%s:%d: warning: unterminated string literal"),
-                       logical_file_name, line_number - 1);
-                error_with_progname = true;
-                phase3_ungetc ('\n');
-                break;
               case EOF: case '"':
                 break;
               }
@@ -1361,6 +1414,31 @@ phase5_get (token_ty *tp)
             buffer = xrealloc (buffer, bufmax);
           }
         buffer[bufpos] = 0;
+
+        if (raw_expected)
+          {
+            char *delimiter_left_end;
+            char *delimiter_right_start;
+
+            if (!(delimiter_left_end = strchr (buffer, '('))
+                || !(delimiter_right_start = strrchr (buffer, ')'))
+                || strncmp (buffer, delimiter_right_start + 1,
+                            (delimiter_left_end - buffer)) != 0)
+              {
+                error_with_progname = false;
+                error (0, 0, _("%s:%d: warning: unterminated string literal"),
+                       logical_file_name, line_number - 1);
+                error_with_progname = true;
+              }
+            else
+              {
+                *delimiter_right_start = '\0';
+                tp->type = token_type_string_literal;
+                tp->string = xstrdup (delimiter_left_end + 1);
+                tp->comment = add_reference (savable_comment);
+                return;
+              }
+          }
         tp->type = token_type_string_literal;
         tp->string = xstrdup (buffer);
         tp->comment = add_reference (savable_comment);