This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: Support for Pascal strings
- To: gcc-patches at gcc dot gnu dot org
- Subject: PATCH: Support for Pascal strings
- From: Ziemowit Laski <zlaski at apple dot com>
- Date: Fri, 15 Jun 2001 16:39:32 -0700
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;
+ }