PATCH: Support for Pascal strings -- Take 2

Ziemowit Laski zlaski@apple.com
Fri Jun 29 12:10:00 GMT 2001


Ok, here is a new, "leaner and meaner" version of the Pascal string patch
that I submitted on June 15.  Per Zack Weinberg's suggestion, I removed
all modifications in cpplib sources, and moved \p handling to 
lex_string().
Also, I've added a blurb in extend.texi describing the usage of Pascal
literals.

Unfortunately, Pascal literals do have to be 'const unsigned char *'.
While I certainly agree with Mark Mitchell that this is "weird," we
nevertheless have to support this to be (backwards) compatible with
other tools on the MacOS platform -- c'est la vie. :(

Please take a look at this patch, and give Stan and/or myself a
"yea" or "nay."  Thanks!

--Zem

Index: gcc/c-common.c
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/c-common.c,v
retrieving revision 1.14
diff -c -3 -p -r1.14 c-common.c
*** c-common.c  2001/06/26 00:46:16     1.14
--- c-common.c  2001/06/29 19:01:42
*************** APPLE LOCAL: AltiVec
*** 151,156 ****
--- 151,161 ----

         tree char_array_type_node;

+    Type `unsigned char[SOMENUMBER]'.
+    Used for pascal-type strings ("\pstring").
+
+       tree pascal_string_type_node;
+
      Type `int[SOMENUMBER]' or something like it.
      Used when an array of int needed and the size is irrelevant.

*************** int flag_short_wchar;
*** 206,211 ****
--- 211,221 ----
   /* Nonzero means enable AltiVec extensions.  */
   int flag_altivec;

+ /* Nonzero means initial "\p" in string becomes a length byte and
+    string type becomes _unsigned_ char* .  */
+
+ int flag_pascal_strings;
+
   /* Nonzero means warn about possible violations of sequence point 
rules.  */

   int warn_sequence_point;
*************** fname_decl (rid, id)
*** 529,534 ****
--- 539,556 ----
     return decl;
   }

+ /* Given a wide flag and a pascal_string flag,
+     return the node indicating the type for combine_strings
+     to assign to the resulting string. */
+
+ static tree
+ choose_string_type (wide_flag, ps_flag)
+      int wide_flag, ps_flag;
+ {
+   /* Pascal strings are not supported in wide mode */
+   return (wide_flag ? wchar_type_node : (ps_flag ? 
unsigned_char_type_node : char_type_node));
+ }
+
   /* Given a chain of STRING_CST nodes,
      concatenate them into one STRING_CST
      and give it a suitable array-of-chars data type.  */
*************** combine_strings (strings)
*** 544,550 ****
--- 566,580 ----
     int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
     int nchars;
     const int nchars_max = flag_isoc99 ? 4095 : 509;
+   int is_pascal_string = 0;

+   /* If first string is a pascal-string, that "wins". */
+   if (TREE_TYPE (strings) == pascal_string_type_node)
+     {
+       is_pascal_string = 1;
+       length = 2;   /* account for the \p length byte, and the NUL. */
+     }
+
     if (TREE_CHAIN (strings))
       {
         /* More than one in the chain, so concatenate.  */
*************** combine_strings (strings)
*** 560,565 ****
--- 590,605 ----
               wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);
               wide_flag = 1;
             }
+         else if (TREE_TYPE (t) == pascal_string_type_node)
+           {
+             /* This one is a pascal-string -- don't count its
+                length byte.  */
+             length += (TREE_STRING_LENGTH (t) - 2);
+
+             /* If the first string was *not* a Pascal string, emit a 
warning. */
+             if (t != strings && !is_pascal_string)
+               warning ("Pascal string-length escape (\\p) ignored in 
concatenation");
+           }
           else
             length += (TREE_STRING_LENGTH (t) - 1);
         }
*************** combine_strings (strings)
*** 576,589 ****
          for any individual strings that are not wide.  */

         q = p;
         for (t = strings; t; t = TREE_CHAIN (t))
         {
           int len = (TREE_STRING_LENGTH (t)
                      - ((TREE_TYPE (t) == wchar_array_type_node)
                         ? wchar_bytes : 1));
           if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
             {
!             memcpy (q, TREE_STRING_POINTER (t), len);
               q += len;
             }
           else
--- 616,635 ----
          for any individual strings that are not wide.  */

         q = p;
+       if (is_pascal_string)
+       ++q;
         for (t = strings; t; t = TREE_CHAIN (t))
         {
           int len = (TREE_STRING_LENGTH (t)
                      - ((TREE_TYPE (t) == wchar_array_type_node)
                         ? wchar_bytes : 1));
+         char *string_ptr = TREE_STRING_POINTER (t);
+         /* Skip the length byte in Pascal strings. */
+         if (TREE_TYPE (t) == pascal_string_type_node)
+           ++string_ptr, --len;
           if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
             {
!             memcpy (q, string_ptr, len);
               q += len;
             }
           else
*************** combine_strings (strings)
*** 595,605 ****
                     {
                       for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; 
j++)
                         *q++ = 0;
!                     *q++ = TREE_STRING_POINTER (t)[i];
                     }
                   else
                     {
!                     *q++ = TREE_STRING_POINTER (t)[i];
                       for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; 
j++)
                         *q++ = 0;
                     }
--- 641,651 ----
                     {
                       for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; 
j++)
                         *q++ = 0;
!                     *q++ = string_ptr[i];
                     }
                   else
                     {
!                     *q++ = string_ptr[i];
                       for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; 
j++)
                         *q++ = 0;
                     }
*************** combine_strings (strings)
*** 615,620 ****
--- 661,675 ----
         else
         *q = 0;

+       if (is_pascal_string)
+       {
+         *p = length - 2;
+         if (length -2 > 255)
+           {
+             pedwarn ("Pascal string too long");
+           }
+       }
+
         value = build_string (length, p);
       }
     else
*************** combine_strings (strings)
*** 640,646 ****
         && (! flag_traditional  && ! flag_writable_strings))
       {
         tree elements
!       = build_type_variant (wide_flag ? wchar_type_node : 
char_type_node,
                               1, 0);
         TREE_TYPE (value)
         = build_array_type (elements,
--- 695,701 ----
         && (! flag_traditional  && ! flag_writable_strings))
       {
         tree elements
!       = build_type_variant (choose_string_type (wide_flag, 
is_pascal_string),
                               1, 0);
         TREE_TYPE (value)
         = build_array_type (elements,
*************** combine_strings (strings)
*** 648,654 ****
       }
     else
       TREE_TYPE (value)
!       = build_array_type (wide_flag ? wchar_type_node : char_type_node,
                           build_index_type (build_int_2 (nchars - 1, 
0)));

     TREE_CONSTANT (value) = 1;
--- 703,709 ----
       }
     else
       TREE_TYPE (value)
!       = build_array_type (choose_string_type (wide_flag, 
is_pascal_string),
                           build_index_type (build_int_2 (nchars - 1, 
0)));

     TREE_CONSTANT (value) = 1;
*************** c_common_nodes_and_builtins ()
*** 3094,3099 ****
--- 3149,3157 ----
        array type.  */
     char_array_type_node
       = build_array_type (char_type_node, array_domain_type);
+   /* Pascal-type strings ("\pstuff") must be unsigned char* */
+   pascal_string_type_node
+     = build_array_type (unsigned_char_type_node, array_domain_type);

     /* Likewise for arrays of ints.  */
     int_array_type_node
Index: gcc/c-common.h
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/c-common.h,v
retrieving revision 1.13
diff -c -3 -p -r1.13 c-common.h
*** c-common.h  2001/06/26 00:46:16     1.13
--- c-common.h  2001/06/29 19:01:42
*************** enum c_tree_index
*** 142,147 ****
--- 142,148 ----
       CTI_WIDEST_UINT_LIT_TYPE,

       CTI_CHAR_ARRAY_TYPE,
+     CTI_PASCAL_STRING_TYPE,    /* for Pascal strings */
       CTI_WCHAR_ARRAY_TYPE,
       CTI_INT_ARRAY_TYPE,
       CTI_STRING_TYPE,
*************** struct c_common_identifier
*** 205,210 ****
--- 206,212 ----
   #define c_bool_false_node             c_global_trees[CTI_C_BOOL_FALSE]

   #define char_array_type_node          
c_global_trees[CTI_CHAR_ARRAY_TYPE]
+ #define pascal_string_type_node       
c_global_trees[CTI_PASCAL_STRING_TYPE]
   #define wchar_array_type_node         
c_global_trees[CTI_WCHAR_ARRAY_TYPE]
   #define int_array_type_node           
c_global_trees[CTI_INT_ARRAY_TYPE]
   #define string_type_node              c_global_trees[CTI_STRING_TYPE]
Index: gcc/c-lex.c
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/c-lex.c,v
retrieving revision 1.10
diff -c -3 -p -r1.10 c-lex.c
*** c-lex.c     2001/05/29 23:13:07     1.10
--- c-lex.c     2001/06/29 19:01:42
*************** lex_string (str, len, wide)
*** 1293,1298 ****
--- 1293,1299 ----
     unsigned int c;
     unsigned width = wide ? WCHAR_TYPE_SIZE
                         : TYPE_PRECISION (char_type_node);
+   int is_pascal_string = 0, is_pascal_escape = 0;

   #ifdef MULTIBYTE_CHARS
     /* Reset multibyte conversion state.  */
*************** lex_string (str, len, wide)
*** 1321,1326 ****
--- 1322,1328 ----
         c = *p++;
   #endif

+       is_pascal_escape = 0;
         if (c == '\\' && !ignore_escape_flag)
         {
           unsigned int mask;
*************** lex_string (str, len, wide)
*** 1329,1339 ****
             mask = ((unsigned int) 1 << width) - 1;
           else
             mask = ~0;
!         c = cpp_parse_escape (parse_in, (const unsigned char **) &p,
!                               (const unsigned char *) limit,
!                               mask, flag_traditional);
         }

         /* Add this single character into the buffer either as a wchar_t
          or as a single byte.  */
         if (wide)
--- 1331,1364 ----
             mask = ((unsigned int) 1 << width) - 1;
           else
             mask = ~0;
!
!         if(flag_pascal_strings && *p == 'p')
!           {
!             is_pascal_escape = 1;
!             p++;
!           }
!         else
!           c = cpp_parse_escape (parse_in, (const unsigned char **) &p,
!                                 (const unsigned char *) limit,
!                                 mask, flag_traditional);
         }

+
+       /* Pascal string-length escape (\p) may appear only as first 
char of a string
+        literal, and never in wide strings. */
+       if (is_pascal_escape)
+       {
+         if (wide || q != buf)
+           {
+             pedwarn (wide?
+                      "Pascal string-length escape (\\p) not allowed in 
wide string":
+                      "Pascal string-length escape (\\p) must be at 
beginning of string");
+             c = 'p';
+           }
+         else
+           is_pascal_string = 1;
+       }
+
         /* Add this single character into the buffer either as a wchar_t
          or as a single byte.  */
         if (wide)
*************** lex_string (str, len, wide)
*** 1362,1367 ****
--- 1387,1403 ----
         }
       }

+   /* Truncate pascal string to 255 chars + length byte */
+   if (is_pascal_string)
+     {
+       if (q - buf > 256)
+       {
+         pedwarn ("Pascal string too long");
+         q = buf + 256;
+       }
+       *buf = q - buf - 1;   /* initialize length byte */
+     }
+
     /* Terminate the string value, either with a single byte zero
        or with a wide zero.  */

*************** lex_string (str, len, wide)
*** 1379,1384 ****
--- 1415,1422 ----

     if (wide)
       TREE_TYPE (value) = wchar_array_type_node;
+   else if (is_pascal_string)
+     TREE_TYPE (value) = pascal_string_type_node;
     else
       TREE_TYPE (value) = char_array_type_node;
     return value;
Index: gcc/c-typeck.c
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/c-typeck.c,v
retrieving revision 1.11
diff -c -3 -p -r1.11 c-typeck.c
*** c-typeck.c  2001/06/14 22:14:20     1.11
--- c-typeck.c  2001/06/29 19:01:42
*************** digest_init (type, init, require_constan
*** 4866,4878 ****

           if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
                != char_type_node)
               && TYPE_PRECISION (typ1) == TYPE_PRECISION 
(char_type_node))
             {
               error_init ("char-array initialized from wide string");
               return error_mark_node;
             }
!         if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
                == char_type_node)
               && TYPE_PRECISION (typ1) != TYPE_PRECISION 
(char_type_node))
             {
               error_init ("int-array initialized from non-wide string");
--- 4866,4882 ----

           if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
                != char_type_node)
+             && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
+              != unsigned_char_type_node)
               && TYPE_PRECISION (typ1) == TYPE_PRECISION 
(char_type_node))
             {
               error_init ("char-array initialized from wide string");
               return error_mark_node;
             }
!         if (((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
                == char_type_node)
+             || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
+              == unsigned_char_type_node))
               && TYPE_PRECISION (typ1) != TYPE_PRECISION 
(char_type_node))
             {
               error_init ("int-array initialized from non-wide string");
Index: gcc/flags.h
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/flags.h,v
retrieving revision 1.4
diff -c -3 -p -r1.4 flags.h
*** flags.h     2001/05/29 23:13:11     1.4
--- flags.h     2001/06/29 19:01:42
*************** extern int flag_print_asm_name;
*** 221,226 ****
--- 221,231 ----

   extern int flag_signed_char;

+ /* Nonzero means initial "\p" in string becomes a length byte and
+    string type becomes _unsigned_ char* .  */
+
+ extern int flag_pascal_strings;
+
   /* Nonzero means give an enum type only as many bytes as it needs.  */

   extern int flag_short_enums;
Index: gcc/toplev.c
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/toplev.c,v
retrieving revision 1.22
diff -c -3 -p -r1.22 toplev.c
*** toplev.c    2001/06/15 18:35:56     1.22
--- toplev.c    2001/06/29 19:01:44
*************** lang_independent_options f_options[] =
*** 1178,1183 ****
--- 1178,1185 ----
      N_("Report on permanent memory allocation at end of run") },
     { "trapv", &flag_trapv, 1,
      N_("Trap for signed overflow in addition / subtraction / 
multiplication.") },
+   { "pascal-strings", &flag_pascal_strings, 1,
+    N_("Allow Pascal-style string literals.") },
   };

   /* Table of language-specific options.  */
Index: gcc/cp/decl2.c
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/cp/decl2.c,v
retrieving revision 1.17
diff -c -3 -p -r1.17 decl2.c
*** decl2.c     2001/06/13 01:28:26     1.17
--- decl2.c     2001/06/29 19:01:45
*************** lang_f_options[] =
*** 453,458 ****
--- 453,459 ----
     {"short-wchar", &flag_short_wchar, 1},
     {"asm", &flag_no_asm, 0},
     {"builtin", &flag_no_builtin, 0},
+   {"pascal-strings", &flag_pascal_strings, 1},

     /* C++-only options.  */
     {"access-control", &flag_access_control, 1},
Index: gcc/cp/typeck2.c
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/cp/typeck2.c,v
retrieving revision 1.1.1.8
diff -c -3 -p -r1.1.1.8 typeck2.c
*** typeck2.c   2001/06/12 23:38:00     1.1.1.8
--- typeck2.c   2001/06/29 19:01:45
*************** digest_init (type, init, tail)
*** 519,531 ****

           if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
                != char_type_node)
               && TYPE_PRECISION (typ1) == BITS_PER_UNIT)
             {
               error ("char-array initialized from wide string");
               return error_mark_node;
             }
!         if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
                == char_type_node)
               && TYPE_PRECISION (typ1) != BITS_PER_UNIT)
             {
               error ("int-array initialized from non-wide string");
--- 519,535 ----

           if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
                != char_type_node)
+             && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
+              != unsigned_char_type_node)
               && TYPE_PRECISION (typ1) == BITS_PER_UNIT)
             {
               error ("char-array initialized from wide string");
               return error_mark_node;
             }
!         if (((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
                == char_type_node)
+             || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)))
+              == unsigned_char_type_node))
               && TYPE_PRECISION (typ1) != BITS_PER_UNIT)
             {
               error ("int-array initialized from non-wide string");
Index: gcc/doc/extend.texi
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/doc/extend.texi,v
retrieving revision 1.1.1.3
diff -c -3 -p -r1.1.1.3 extend.texi
*** extend.texi 2001/06/21 18:01:16     1.1.1.3
--- extend.texi 2001/06/29 19:01:45
*************** extensions, accepted by GCC in C89 mode
*** 59,64 ****
--- 59,66 ----
   * C++ Comments::        C++ comments are recognized.
   * Dollar Signs::        Dollar sign is allowed in identifiers.
   * Character Escapes::   @samp{\e} stands for the character @key{ESC}.
+ * Pascal Strings::      Constructing string literals with a 
Pascal-style
+                          length byte.
   * Variable Attributes::       Specifying attributes of variables.
   * Type Attributes::   Specifying attributes of types.
   * Alignment::           Inquiring about the alignment of a type or 
variable.
*************** machines, typically because the target a
*** 2340,2345 ****
--- 2342,2375 ----

   You can use the sequence @samp{\e} in a string or character constant to
   stand for the ASCII character @key{ESC}.
+
+ @node Pascal Strings
+ @section Constructing String Literals with a Pascal-style Length Byte
+ @cindex Pascal length byte
+ @cindex Pascal strings
+
+ Specifying the @w{@option{-fpascal-strings}} option will cause the
+ compiler to recognize and construct Pascal-style string literals.  This
+ functionality is disabled by default; furthermore, its use in new code
+ is discouraged.
+
+ Pascal string literals take the form @samp{"\pstring"}.  The special
+ escape sequence @samp{\p} denotes the Pascal length byte for the 
string,
+ and will be replaced at compile time with the number of characters that
+ follow.  The @samp{\p} may only appear at the beginning of a string
+ literal, and may @emph{not} appear in wide string literals or as an
+ integral constant.
+
+ As is the case with C string literals, Pascal string literals are
+ terminated with a NULL character; this character is @emph{not} counted
+ when computing the value of the length byte.
+
+ Pascal-style literals are useful for calling external routines that
+ expect Pascal strings as arguments, as is true with some Apple MacOS
+ Toolbox calls.  Unlike ordinary string literals, which are of type
+ @samp{const char *}, Pascal-style literals are treated by the compiler
+ as being of type @samp{const unsigned char *}.  This is necessary in
+ order to maintain backward compatibility with other MacOS compilers.

   @node Alignment
   @section Inquiring on Alignment of Types or Variables
Index: gcc/doc/invoke.texi
===================================================================
RCS file: /cvs/repository/CoreTools/gcc3/gcc/doc/invoke.texi,v
retrieving revision 1.1.1.4
diff -c -3 -p -r1.1.1.4 invoke.texi
*** invoke.texi 2001/06/21 18:01:19     1.1.1.4
--- invoke.texi 2001/06/29 19:01:49
*************** in the following sections.
*** 164,170 ****
   -fallow-single-precision  -fcond-mismatch @gol
   -fsigned-bitfields  -fsigned-char @gol
   -funsigned-bitfields  -funsigned-char @gol
! -fwritable-strings  -fshort-wchar}

   @item C++ Language Options
   @xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
--- 164,171 ----
   -fallow-single-precision  -fcond-mismatch @gol
   -fsigned-bitfields  -fsigned-char @gol
   -funsigned-bitfields  -funsigned-char @gol
! -fwritable-strings  -fshort-wchar @gol
! -fpascal-strings}

   @item C++ Language Options
   @xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
*************** with ISO or GNU C conventions (the defau
*** 1228,1233 ****
--- 1229,1241 ----
   Override the underlying type for @samp{wchar_t} to be @samp{short
   unsigned int} instead of the default for the target.  This option is
   useful for building programs to run under WINE.
+
+ @item -fpascal-strings
+ Allow for Pascal-style string literals to be constructed.
+
+ @xref{Pascal Strings,,Constructing String Literals with a Pascal-style
+ Length Byte}, for more information on the syntax and semantics of 
Pascal
+ string literals.
   @end table

   @node C++ Dialect Options
Index: gcc/testsuite/g++.dg/pascal-strings-1.C
===================================================================
RCS file: pascal-strings-1.C
diff -N pascal-strings-1.C
*** /dev/null   Fri Jun 29 12:03:01 2001
--- pascal-strings-1.C  Fri Jun 29 12:01:54 2001
***************
*** 0 ****
--- 1,37 ----
+ /* Test for handling of Pascal-style string literals */
+ /* Origin: Ziemowit Laski <zlaski@apple.com> */
+ /* { dg-do run } */
+ /* { dg-options "-fpascal-strings" } */
+
+ extern "C" void abort (void);
+
+ int
+ strlen (const unsigned char *s)
+ {
+   int l = 0;
+   while (*s++) l++;
+   return l;
+ }
+
+ const unsigned char *pascalStr1 = "\pHello, World!";
+ const unsigned char *concat1 = "\pHi" "there";
+ const char *concat2 = "Hi" "\pthere";  /* { dg-warning "ignored in 
concatenation" } */
+
+ int
+ main (void)
+ {
+   const unsigned char *pascalStr2 = "\pGood-bye!";
+
+   if (strlen (pascalStr1) != 14)
+     abort ();
+   if (*pascalStr1 != 13)
+     abort ();  /* the length byte does not include trailing null */
+
+   if (strlen (pascalStr2) != 10)
+     abort ();
+   if (*pascalStr2 != 9)
+     abort ();
+
+   return 0;
+ }
+
Index: gcc/testsuite/g++.dg/pascal-strings-2.C
===================================================================
RCS file: pascal-strings-2.C
diff -N pascal-strings-2.C
*** /dev/null   Fri Jun 29 12:03:01 2001
--- pascal-strings-2.C  Fri Jun 29 12:01:54 2001
***************
*** 0 ****
--- 1,13 ----
+ /* Test for handling of Pascal-style string literals */
+ /* Origin: Ziemowit Laski <zlaski@apple.com> */
+ /* { dg-do compile } */
+ /* { dg-options "-std=iso9899:1999 -fpascal-strings" } */
+
+ const wchar_t *pascalStr1 = L"\pHi!"; /* { dg-error "not allowed in 
wide" } */
+ const wchar_t *pascalStr2 = L"Bye\p!"; /* { dg-error "not allowed in 
wide" } */
+
+ const char *pascalStr3 = "Hello\p, World!"; /* { dg-error "must be at 
beginning" } */
+
+ const char *concat2 = "Hi" "\pthere"; /* { dg-warning "ignored in 
concatenation" } */
+ const char *concat3 = "Hi" "there\p"; /* { dg-error "must be at 
beginning" } */
+
Index: gcc/testsuite/gcc.dg/pascal-strings-1.c
===================================================================
RCS file: pascal-strings-1.c
diff -N pascal-strings-1.c
*** /dev/null   Fri Jun 29 12:03:01 2001
--- pascal-strings-1.c  Fri Jun 29 12:01:55 2001
***************
*** 0 ****
--- 1,43 ----
+ /* Test for handling of Pascal-style string literals */
+ /* Origin: Ziemowit Laski <zlaski@apple.com> */
+ /* { dg-do run } */
+ /* { dg-options "-fpascal-strings" } */
+
+ extern void abort (void);
+
+ int
+ strlen (const char *s)
+ {
+   int l = 0;
+   while (*s++) l++;
+   return l;
+ }
+
+ const char *pascalStr1 = "\pHello, World!";
+ const char *pascalStr3 = "Hello\p, World!"; /* { dg-warning "must be 
at beginning" } */
+
+ const char *concat1 = "\pHi" "there";
+ const char *concat2 = "Hi" "\pthere"; /* { dg-warning "ignored in 
concatenation" } */
+ const char *concat3 = "Hi" "there\p"; /* { dg-warning "must be at 
beginning" } */
+
+ int
+ main (void)
+ {
+   const char *pascalStr2 = "\pGood-bye!";
+
+   if (strlen (pascalStr1) != 14)
+     abort ();
+   if (*pascalStr1 != 13)
+     abort ();  /* the length byte does not include trailing null */
+
+   if (strlen (pascalStr2) != 10)
+     abort ();
+   if (*pascalStr2 != 9)
+     abort ();
+
+   if (*pascalStr3 == 13)
+     abort ();  /* *not* a Pascal string! */
+
+   return 0;
+ }
+
Index: gcc/testsuite/gcc.dg/pascal-strings-2.c
===================================================================
RCS file: pascal-strings-2.c
diff -N pascal-strings-2.c
*** /dev/null   Fri Jun 29 12:03:01 2001
--- pascal-strings-2.c  Fri Jun 29 12:01:55 2001
***************
*** 0 ****
--- 1,20 ----
+ /* Test for handling of Pascal-style string literals */
+ /* Origin: Ziemowit Laski <zlaski@apple.com> */
+ /* { dg-do run } */
+ /* { dg-options "-std=iso9899:1999 -fpascal-strings" } */
+
+ typedef __WCHAR_TYPE__ wchar_t;
+ extern void abort (void);
+
+ const wchar_t *pascalStr1 = L"\pHi!"; /* { dg-warning "not allowed in 
wide" } */
+ const wchar_t *pascalStr2 = L"Bye\p!"; /* { dg-warning "not allowed in 
wide" } */
+
+ int
+ main (void)
+ {
+   if (*pascalStr1 != L'p')
+     abort ();  /* compiler should convert '\p' to 'p' */
+
+   return 0;
+ }
+

--------------------------------------------------------------
Ziemowit Laski                   Apple Computer, Inc.
zlaski@apple.com                 2 Infinite Loop, MS 302-4SN
+1.408.974.6229  Fax .1344       Cupertino, CA  95014-2085



More information about the Gcc-patches mailing list