This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

PATCH: Support for Pascal strings


Hello,

I would humbly like to propose to add support for Pascal-style string 
literals
in gcc.  The changelog entry and diffs appear below.

Pascal-style literals are written as "\pstring", where \p is a special 
escape
sequence designating the length byte; the compiler fills that initial 
byte
with the actual length of the string.  Pascal strings in C/C++ have 
widespread
use in MacOS X since numerous legacy APIs require Pascal layout for 
strings.
However, the nature of the change is platform-independent.  Note also 
that
the functionality is disabled unless the '-fpascal-strings' command-line 
option
is given. In the future, Pascal strings may prove useful when integrating
GNU Pascal with gcc.

I look forward to your comments/suggestions.  Thanks,

--Zem

P.S. Tested on powerpc-apple-darwin1.3.3.
--------------------------------------------------------------
Ziemowit Laski                   Apple Computer, Inc.
zlaski@apple.com                 2 Infinite Loop, MS 302-4SN
+1.408.974.6229  Fax .1344       Cupertino, CA  95014-2085


==========================================================================
==

2001-06-15  Ziemowit Laski  <zlaski@apple.com>

	* gcc/c-common.c: Support for Pascal string concatenation 
(combine_string)
	* gcc/c-common.h: Add CTI_UNSIGNED_CHAR_ARRAY_TYPE, 
unsigned_char_array_type_node
	* gcc/c-lex.c: Creation of Pascal string literals (lex_string)
	* gcc/c-typeck.c: Distinguish Pascal strings from wide strings 
(digest_init)
	* gcc/cpplex.c: Handling of '\p' escape sequence (cpp_parse_escape)
	* gcc/cpplib.h: Add 'flag_pascal_strings' extern decl
	* gcc/flags.h: Add 'flag_pascal-strings' extern decl
	* gcc/toplev.c: Add '-fpascal-strings' command-line option
	* gcc/cp/decl2.c: Add '-fpascal-strings' command-line option
	* gcc/cp/typeck2.c: Distinguish Pascal strings from wide strings 
(digest_init)
	* gcc/doc/invoke.texi: Add description of '-fpascal-strings'
      * gcc/testsuite/g++.dg/pascal-strings-1.C: New C++ test case
      * gcc/testsuite/g++.dg/pascal-strings-2.C: New C++ test case
      * gcc/testsuite/gcc.dg/pascal-strings-1.c: New C test case
      * gcc/testsuite/gcc.dg/pascal-strings-2.c: New C test case

Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.237
diff -c -3 -p -r1.237 c-common.c
*** c-common.c  2001/06/05 08:03:43     1.237
--- c-common.c  2001/06/15 22:17:28
*************** cpp_reader *parse_in;           /* Declared in c-
*** 138,143 ****
--- 138,148 ----

         tree char_array_type_node;

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

*************** fname_decl (rid, id)
*** 511,516 ****
--- 516,533 ----
     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)
*** 526,531 ****
--- 543,556 ----
     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) == unsigned_char_array_type_node)
+     {
+       is_pascal_string = 1;
+       length = 2;   /* account for the \p length byte, and the NUL. */
+     }

     if (TREE_CHAIN (strings))
       {
*************** combine_strings (strings)
*** 542,547 ****
--- 567,582 ----
               wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);
               wide_flag = 1;
             }
+         else if (TREE_TYPE (t) == unsigned_char_array_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)
*** 558,571 ****
          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
--- 593,612 ----
          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) == unsigned_char_array_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)
*** 577,587 ****
                     {
                       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;
                     }
--- 618,628 ----
                     {
                       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)
*** 597,602 ****
--- 638,652 ----
         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)
*** 622,628 ****
         && (! 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,
--- 672,678 ----
         && (! 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)
*** 630,636 ****
       }
     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;
--- 680,686 ----
       }
     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 ()
*** 2999,3004 ****
--- 3049,3057 ----
        array type.  */
     char_array_type_node
       = build_array_type (char_type_node, array_domain_type);
+   /* Pascal-type strings ("\pstuff") must be unsigned char* */
+   unsigned_char_array_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/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.74
diff -c -3 -p -r1.74 c-common.h
*** c-common.h  2001/06/05 08:03:44     1.74
--- c-common.h  2001/06/15 22:17:28
*************** enum c_tree_index
*** 133,138 ****
--- 133,139 ----
       CTI_WIDEST_UINT_LIT_TYPE,

       CTI_CHAR_ARRAY_TYPE,
+     CTI_UNSIGNED_CHAR_ARRAY_TYPE,    /* for Pascal strings */
       CTI_WCHAR_ARRAY_TYPE,
       CTI_INT_ARRAY_TYPE,
       CTI_STRING_TYPE,
*************** struct c_common_identifier
*** 196,201 ****
--- 197,203 ----
   #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 unsigned_char_array_type_node 
c_global_trees[CTI_UNSIGNED_CHAR_ARRAY_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/gcc/gcc/gcc/c-lex.c,v
retrieving revision 1.141
diff -c -3 -p -r1.141 c-lex.c
*** c-lex.c     2001/05/23 19:05:37     1.141
--- c-lex.c     2001/06/15 22:17:28
*************** 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)
*** 1331,1338 ****
             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.  */
--- 1333,1353 ----
             mask = ~0;
           c = cpp_parse_escape (parse_in, (const unsigned char **) &p,
                                 (const unsigned char *) limit,
!                               mask, flag_traditional, 
&is_pascal_escape);
         }
+
+       if (flag_pascal_strings && 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.  */
*************** lex_string (str, len, wide)
*** 1362,1367 ****
--- 1377,1393 ----
         }
       }

+   /* 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 ****
--- 1405,1412 ----

     if (wide)
       TREE_TYPE (value) = wchar_array_type_node;
+   else if (is_pascal_string)
+     TREE_TYPE (value) = unsigned_char_array_type_node;
     else
       TREE_TYPE (value) = char_array_type_node;
     return value;
Index: gcc/c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.125
diff -c -3 -p -r1.125 c-typeck.c
*** c-typeck.c  2001/06/12 12:15:43     1.125
--- c-typeck.c  2001/06/15 22:17:28
*************** digest_init (type, init, require_constan
*** 4708,4726 ****
            || typ1 == signed_wchar_type_node)
           && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
         {
           if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
                          TYPE_MAIN_VARIANT (type)))
             return inside_init;

!         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");
--- 4708,4727 ----
            || typ1 == signed_wchar_type_node)
           && ((inside_init && TREE_CODE (inside_init) == STRING_CST)))
         {
+         tree typ2;
           if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
                          TYPE_MAIN_VARIANT (type)))
             return inside_init;

!         typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)));
!
!         if (typ2 != char_type_node && typ2 != 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 ((typ2 == char_type_node || typ2 == unsigned_char_type_node)
               && TYPE_PRECISION (typ1) != TYPE_PRECISION 
(char_type_node))
             {
               error_init ("int-array initialized from non-wide string");
Index: gcc/cpplex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplex.c,v
retrieving revision 1.145
diff -c -3 -p -r1.145 cpplex.c
*** cpplex.c    2001/05/30 21:22:00     1.145
--- cpplex.c    2001/06/15 22:17:28
*************** maybe_read_ucs (pfile, pstr, limit, pc)
*** 1753,1758 ****
--- 1753,1763 ----
     return 0;
   }

+ /* Nonzero means initial "\p" in string becomes a length byte and
+    string type becomes _unsigned_ char* .  */
+
+ int flag_pascal_strings;
+
   /* Interpret an escape sequence, and return its value.  PSTR points to
      the input pointer, which is just after the backslash.  LIMIT is how
      much text we have.  MASK is a bitmask for the precision for the
*************** maybe_read_ucs (pfile, pstr, limit, pc)
*** 1762,1773 ****
      Handles all relevant diagnostics.  */

   unsigned int
! cpp_parse_escape (pfile, pstr, limit, mask, traditional)
        cpp_reader *pfile;
        const unsigned char **pstr;
        const unsigned char *limit;
        unsigned HOST_WIDE_INT mask;
        int traditional;
   {
     int unknown = 0;
     const unsigned char *str = *pstr;
--- 1767,1779 ----
      Handles all relevant diagnostics.  */

   unsigned int
! cpp_parse_escape (pfile, pstr, limit, mask, traditional, pascal_p)
        cpp_reader *pfile;
        const unsigned char **pstr;
        const unsigned char *limit;
        unsigned HOST_WIDE_INT mask;
        int traditional;
+      int *pascal_p;  /* indicates if a "\p" was seen */
   {
     int unknown = 0;
     const unsigned char *str = *pstr;
*************** cpp_parse_escape (pfile, pstr, limit, ma
*** 1862,1867 ****
--- 1868,1882 ----
         }
         break;

+     case 'p':
+       if (flag_pascal_strings && pascal_p)
+       {
+         *pascal_p = 1;
+         c = 0;
+         break;
+       }
+       /* otherwise fall through, treat as unknown */
+
       default:
         unknown = 1;
         break;
*************** cpp_interpret_charconst (pfile, token, w
*** 1909,1914 ****
--- 1924,1930 ----
     unsigned int width, max_chars, c;
     unsigned HOST_WIDE_INT mask;
     HOST_WIDE_INT result = 0;
+   int is_pascal_char = 0;

   #ifdef MULTIBYTE_CHARS
     (void) local_mbtowc (NULL, NULL, 0);
*************** cpp_interpret_charconst (pfile, token, w
*** 1948,1955 ****
   #endif

         if (c == '\\')
!       c = cpp_parse_escape (pfile, &str, limit, mask, traditional);

   #ifdef MAP_CHARACTER
         if (ISPRINT (c))
         c = MAP_CHARACTER (c);
--- 1964,1978 ----
   #endif

         if (c == '\\')
!       c = cpp_parse_escape (pfile, &str, limit, mask, traditional, 
&is_pascal_char);

+       if (flag_pascal_strings && is_pascal_char)
+       {
+         cpp_pedwarn (pfile, "Pascal string-length escape (\\p) not"
+                       " allowed in character constant");
+         c = 'p';
+       }
+
   #ifdef MAP_CHARACTER
         if (ISPRINT (c))
         c = MAP_CHARACTER (c);
Index: gcc/cpplib.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.h,v
retrieving revision 1.176
diff -c -3 -p -r1.176 cpplib.h
*** cpplib.h    2001/05/26 01:31:34     1.176
--- cpplib.h    2001/06/15 22:17:28
*************** extern int cpp_ideq                     PARAMS ((const 
cpp
*** 601,610 ****
   extern void cpp_output_line           PARAMS ((cpp_reader *, FILE *));
   extern void cpp_output_token          PARAMS ((const cpp_token *, 
FILE *));
   extern const char *cpp_type2name      PARAMS ((enum cpp_ttype));
   extern unsigned int cpp_parse_escape  PARAMS ((cpp_reader *,
                                                  const unsigned char **,
                                                  const unsigned char *,
!                                                unsigned HOST_WIDE_INT, 
int));

   /* In cpphash.c */

--- 601,612 ----
   extern void cpp_output_line           PARAMS ((cpp_reader *, FILE *));
   extern void cpp_output_token          PARAMS ((const cpp_token *, 
FILE *));
   extern const char *cpp_type2name      PARAMS ((enum cpp_ttype));
+
+ extern int flag_pascal_strings;
   extern unsigned int cpp_parse_escape  PARAMS ((cpp_reader *,
                                                  const unsigned char **,
                                                  const unsigned char *,
!                                                unsigned HOST_WIDE_INT, 
int, int *));

   /* In cpphash.c */

Index: gcc/flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.65
diff -c -3 -p -r1.65 flags.h
*** flags.h     2001/05/27 21:04:27     1.65
--- flags.h     2001/06/15 22:17:31
*************** extern int flag_detailed_statistics;
*** 625,628 ****
--- 625,633 ----
   /* Nonzero means enable synchronous exceptions for non-call 
instructions.  */
   extern int flag_non_call_exceptions;

+ /* Nonzero means initial "\p" in string becomes a length byte and
+    string type becomes _unsigned_ char* .  */
+
+ extern int flag_pascal_strings;
+
   #endif /* ! GCC_FLAGS_H */
Index: gcc/toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.470
diff -c -3 -p -r1.470 toplev.c
*** toplev.c    2001/06/13 03:21:48     1.470
--- toplev.c    2001/06/15 22:17:32
*************** lang_independent_options f_options[] =
*** 1169,1174 ****
--- 1169,1176 ----
      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/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.470
diff -c -3 -p -r1.470 decl2.c
*** decl2.c     2001/06/06 21:52:52     1.470
--- decl2.c     2001/06/15 22:17:32
*************** lang_f_options[] =
*** 444,449 ****
--- 444,450 ----
     {"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/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.102
diff -c -3 -p -r1.102 typeck2.c
*** typeck2.c   2001/06/10 13:48:04     1.102
--- typeck2.c   2001/06/15 22:17:32
*************** digest_init (type, init, tail)
*** 516,531 ****
               || (element && TREE_CODE (element) == STRING_CST)))
         {
           tree string = element ? element : init;

!         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");
--- 516,530 ----
               || (element && TREE_CODE (element) == STRING_CST)))
         {
           tree string = element ? element : init;
+         tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string)));

!         if (typ2 != char_type_node && typ2 != unsigned_char_type_node
               && TYPE_PRECISION (typ1) == BITS_PER_UNIT)
             {
               error ("char-array initialized from wide string");
               return error_mark_node;
             }
!         if ((typ2 == char_type_node || typ2 == unsigned_char_type_node)
               && TYPE_PRECISION (typ1) != BITS_PER_UNIT)
             {
               error ("int-array initialized from non-wide string");
*************** digest_init (type, init, tail)
*** 543,549 ****
                  because it's ok to ignore the terminating null char 
that is
                  counted in the length of the constant, but in C++ this 
would
                  be invalid.  */
!             if (size < TREE_STRING_LENGTH (string))
                 pedwarn ("initializer-string for array of chars is too 
long");
             }
           return string;
--- 542,555 ----
                  because it's ok to ignore the terminating null char 
that is
                  counted in the length of the constant, but in C++ this 
would
                  be invalid.  */
!             if (size < TREE_STRING_LENGTH (string)
!                 /* If it is a Pascal string, then it is ok even in C++
!                    to ignore the terminating null char, since it's 
kinda
!                    redundant anyway.  This works ok even for max-length
!                    (255-character long) pstrings because we still added
!                    a null char anyway. */
!                 && (typ2 != unsigned_char_type_node
!                     || size + 1 < TREE_STRING_LENGTH (string)))
                 pedwarn ("initializer-string for array of chars is too 
long");
             }
           return string;
Index: gcc/doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.13
diff -c -3 -p -r1.13 invoke.texi
*** invoke.texi 2001/06/14 22:51:17     1.13
--- invoke.texi 2001/06/15 22:17:37
*************** 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,1249 ----
   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.  These 
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.
+
+ 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 option is useful for calling external routines that expect Pascal
+ strings as arguments, as is true with some MacOS Toolbox calls.
   @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   Thu Jun 14 19:48:46 2001
--- pascal-strings-1.C  Thu Jun 14 19:56:43 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" "detect \\p 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   Thu Jun 14 19:48:46 2001
--- pascal-strings-2.C  Thu Jun 14 19:56:43 2001
***************
*** 0 ****
--- 1,23 ----
+ /* Test for handling of Pascal-style string literals */
+ /* Origin: Ziemowit Laski <zlaski@apple.com> */
+ /* { dg-do compile } */
+ /* { dg-options "-std=iso9899:1999 -fpascal-strings" } */
+
+ extern "C" void abort (void);
+
+ const wchar_t *pascalStr1 = L"\pHi!"; /* { dg-error "not allowed in 
wide" "detect \\p in wide string" } */
+ const wchar_t *pascalStr2 = L"Bye\p!"; /* { dg-error "not allowed in 
wide" "detect \\p in wide string" } */
+
+ const char *pascalStr3 = "Hello\p, World!"; /* { dg-error "must be at 
beginning" "detect \\p in middle of string" } */
+
+ const char *concat2 = "Hi" "\pthere"; /* { dg-warning "ignored in 
concatenation" "detect \\p in concatenation" } */
+ const char *concat3 = "Hi" "there\p"; /* { dg-error "must be at 
beginning" "detect \\p in middle of string" } */
+
+ int
+ main (void)
+ {
+   if (*pascalStr1 != L'p')
+     abort ();  /* do *not* treat as Pascal string */
+
+   return 0;
+ }
Index: gcc/testsuite/gcc.dg/pascal-strings-1.c
===================================================================
RCS file: pascal-strings-1.c
diff -N pascal-strings-1.c
*** /dev/null   Thu Jun 14 19:48:46 2001
--- pascal-strings-1.c  Thu Jun 14 19:56:55 2001
***************
*** 0 ****
--- 1,42 ----
+ /* 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" "detect \\p in middle of string" } */
+
+ const char *concat1 = "\pHi" "there";
+ const char *concat2 = "Hi" "\pthere"; /* { dg-warning "ignored in 
concatenation" "detect \\p in concatenation" } */
+ const char *concat3 = "Hi" "there\p"; /* { dg-warning "must be at 
beginning" "detect \\p in middle of string" } */
+
+ 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   Thu Jun 14 19:48:46 2001
--- pascal-strings-2.c  Thu Jun 14 19:56:55 2001
***************
*** 0 ****
--- 1,19 ----
+ /* 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" "detect \\p in wide string" } */
+ const wchar_t *pascalStr2 = L"Bye\p!"; /* { dg-warning "not allowed in 
wide" "detect \\p in wide string" } */
+
+ int
+ main (void)
+ {
+   if (*pascalStr1 != L'p')
+     abort ();  /* do *not* treat as Pascal string */
+
+   return 0;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]