/* Subroutines shared by all languages that are variants of C.
Copyright (C) 1992 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
char *name
, *printable_name
;
if (current_function_decl
== NULL
)
printable_name
= "top level";
if (TREE_CODE (TREE_TYPE (current_function_decl
)) == METHOD_TYPE
)
/* Allow functions to be nameless (such as artificial ones). */
if (DECL_NAME (current_function_decl
))
name
= IDENTIFIER_POINTER (DECL_NAME (current_function_decl
));
printable_name
= (*decl_printable_name
) (current_function_decl
, &kind
);
push_obstacks_nochange ();
decl
= build_decl (VAR_DECL
, get_identifier ("__FUNCTION__"),
TREE_READONLY (decl
) = 1;
DECL_SOURCE_LINE (decl
) = 0;
DECL_IN_SYSTEM_HEADER (decl
) = 1;
DECL_IGNORED_P (decl
) = 1;
init
= build_string (strlen (name
) + 1, name
);
TREE_TYPE (init
) = char_array_type_node
;
DECL_INITIAL (decl
) = init
;
finish_decl (pushdecl (decl
), init
, NULL_TREE
);
push_obstacks_nochange ();
decl
= build_decl (VAR_DECL
, get_identifier ("__PRETTY_FUNCTION__"),
TREE_READONLY (decl
) = 1;
DECL_SOURCE_LINE (decl
) = 0;
DECL_IN_SYSTEM_HEADER (decl
) = 1;
DECL_IGNORED_P (decl
) = 1;
init
= build_string (strlen (printable_name
) + 1, printable_name
);
TREE_TYPE (init
) = char_array_type_node
;
DECL_INITIAL (decl
) = init
;
finish_decl (pushdecl (decl
), init
, NULL_TREE
);
/* 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
)
int wchar_bytes
= TYPE_PRECISION (wchar_type_node
) / BITS_PER_UNIT
;
if (TREE_CHAIN (strings
))
/* More than one in the chain, so concatenate. */
/* Don't include the \0 at the end of each substring,
Count wide strings and ordinary strings separately. */
for (t
= strings
; t
; t
= TREE_CHAIN (t
))
if (TREE_TYPE (t
) == wchar_array_type_node
)
wide_length
+= (TREE_STRING_LENGTH (t
) - wchar_bytes
);
length
+= (TREE_STRING_LENGTH (t
) - 1);
/* If anything is wide, the non-wides will be converted,
which makes them take more space. */
length
= length
* wchar_bytes
+ wide_length
;
/* Copy the individual strings into the new combined string.
If the combined string is wide, convert the chars to ints
for any individual strings that are not wide. */
for (t
= strings
; t
; t
= TREE_CHAIN (t
))
int len
= (TREE_STRING_LENGTH (t
)
- ((TREE_TYPE (t
) == wchar_array_type_node
)
if ((TREE_TYPE (t
) == wchar_array_type_node
) == wide_flag
)
bcopy (TREE_STRING_POINTER (t
), q
, len
);
for (i
= 0; i
< len
; i
++)
((int *) q
)[i
] = TREE_STRING_POINTER (t
)[i
];
for (i
= 0; i
< wchar_bytes
; i
++)
value
= make_node (STRING_CST
);
TREE_STRING_POINTER (value
) = p
;
TREE_STRING_LENGTH (value
) = length
;
TREE_CONSTANT (value
) = 1;
length
= TREE_STRING_LENGTH (value
);
if (TREE_TYPE (value
) == wchar_array_type_node
)
/* Compute the number of elements, for the array type. */
nchars
= wide_flag
? length
/ wchar_bytes
: length
;
/* Create the array type for the string constant.
-Wwrite-strings says make the string constant an array of const char
so that copying it to a non-const pointer will get a warning. */
&& (! flag_traditional
&& ! flag_writable_strings
))
= build_type_variant (wide_flag
? wchar_type_node
: char_type_node
,
= build_array_type (elements
,
build_index_type (build_int_2 (nchars
- 1, 0)));
= build_array_type (wide_flag
? wchar_type_node
: char_type_node
,
build_index_type (build_int_2 (nchars
- 1, 0)));
TREE_CONSTANT (value
) = 1;
/* Process the attributes listed in ATTRIBUTES
and install them in DECL. */
decl_attributes (decl
, attributes
)
for (a
= attributes
; a
; a
= TREE_CHAIN (a
))
if (TREE_VALUE (a
) == get_identifier ("packed"))
if (TREE_CODE (decl
) == FIELD_DECL
)
/* We can't set DECL_PACKED for a VAR_DECL, because the bit is
used for DECL_REGISTER. It wouldn't mean anything anyway. */
else if (TREE_VALUE (a
) != 0
&& TREE_CODE (TREE_VALUE (a
)) == TREE_LIST
&& TREE_PURPOSE (TREE_VALUE (a
)) == get_identifier ("mode"))
= IDENTIFIER_POINTER (TREE_VALUE (TREE_VALUE (a
)));
/* Give this decl a type with the specified mode. */
for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
if (!strcmp (specified_name
, GET_MODE_NAME (i
)))
= type_for_mode (i
, TREE_UNSIGNED (TREE_TYPE (decl
)));
error ("no data type for mode `%s'", specified_name
);
if (i
== NUM_MACHINE_MODES
)
error ("unknown machine mode `%s'", specified_name
);
else if (TREE_VALUE (a
) != 0
&& TREE_CODE (TREE_VALUE (a
)) == TREE_LIST
&& TREE_PURPOSE (TREE_VALUE (a
)) == get_identifier ("aligned"))
int align
= TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (a
)))
if (exact_log2 (align
) == -1)
"requested alignment of `%s' is not a power of 2");
else if (TREE_CODE (decl
) != VAR_DECL
&& TREE_CODE (decl
) != FIELD_DECL
)
"alignment specified for `%s'");
DECL_ALIGN (decl
) = align
;
else if (TREE_VALUE (a
) != 0
&& TREE_CODE (TREE_VALUE (a
)) == TREE_LIST
&& TREE_PURPOSE (TREE_VALUE (a
)) == get_identifier ("format"))
tree list
= TREE_VALUE (TREE_VALUE (a
));
tree format_type
= TREE_PURPOSE (list
);
int format_num
= TREE_INT_CST_LOW (TREE_PURPOSE (TREE_VALUE (list
)));
int first_arg_num
= TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list
)));
if (TREE_CODE (decl
) != FUNCTION_DECL
)
"argument format specified for non-function `%s'");
if (format_type
== get_identifier ("printf"))
else if (format_type
== get_identifier ("scanf"))
error_with_decl (decl
, "unrecognized format specifier for `%s'");
if (first_arg_num
!= 0 && first_arg_num
<= format_num
)
"format string arg follows the args to be formatted, for `%s'");
record_format_info (DECL_NAME (decl
), is_scan
, format_num
,
/* Print a warning if a constant expression had overflow in folding. */
constant_expression_warning (value
)
if (TREE_CODE (value
) == INTEGER_CST
&& TREE_CONSTANT_OVERFLOW (value
))
pedwarn ("overflow in constant expression");
c_expand_expr_stmt (expr
)
/* Do default conversion if safe and possibly important,
in case within ({...}). */
if ((TREE_CODE (TREE_TYPE (expr
)) == ARRAY_TYPE
&& lvalue_p (expr
))
|| TREE_CODE (TREE_TYPE (expr
)) == FUNCTION_TYPE
)
expr
= default_conversion (expr
);
if (TREE_TYPE (expr
) != error_mark_node
&& TYPE_SIZE (TREE_TYPE (expr
)) == 0
&& TREE_CODE (TREE_TYPE (expr
)) != ARRAY_TYPE
)
error ("expression statement has incomplete type");
/* Validate the expression after `case' and apply default promotions. */
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
if (TREE_CODE (value
) != INTEGER_CST
&& value
!= error_mark_node
)
error ("case label does not reduce to an integer constant");
/* Promote char or short to int. */
value
= default_conversion (value
);
constant_expression_warning (value
);
/* Return an integer type with BITS bits of precision,
that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
type_for_size (bits
, unsignedp
)
if (bits
== TYPE_PRECISION (signed_char_type_node
))
return unsignedp
? unsigned_char_type_node
: signed_char_type_node
;
if (bits
== TYPE_PRECISION (short_integer_type_node
))
return unsignedp
? short_unsigned_type_node
: short_integer_type_node
;
if (bits
== TYPE_PRECISION (integer_type_node
))
return unsignedp
? unsigned_type_node
: integer_type_node
;
if (bits
== TYPE_PRECISION (long_integer_type_node
))
return unsignedp
? long_unsigned_type_node
: long_integer_type_node
;
if (bits
== TYPE_PRECISION (long_long_integer_type_node
))
return (unsignedp
? long_long_unsigned_type_node
: long_long_integer_type_node
);
if (bits
<= TYPE_PRECISION (intQI_type_node
))
return unsignedp
? unsigned_intQI_type_node
: intQI_type_node
;
if (bits
<= TYPE_PRECISION (intHI_type_node
))
return unsignedp
? unsigned_intHI_type_node
: intHI_type_node
;
if (bits
<= TYPE_PRECISION (intSI_type_node
))
return unsignedp
? unsigned_intSI_type_node
: intSI_type_node
;
if (bits
<= TYPE_PRECISION (intDI_type_node
))
return unsignedp
? unsigned_intDI_type_node
: intDI_type_node
;
/* Return a data type that has machine mode MODE.
If the mode is an integer,
then UNSIGNEDP selects between signed and unsigned types. */
type_for_mode (mode
, unsignedp
)
if (mode
== TYPE_MODE (signed_char_type_node
))
return unsignedp
? unsigned_char_type_node
: signed_char_type_node
;
if (mode
== TYPE_MODE (short_integer_type_node
))
return unsignedp
? short_unsigned_type_node
: short_integer_type_node
;
if (mode
== TYPE_MODE (integer_type_node
))
return unsignedp
? unsigned_type_node
: integer_type_node
;
if (mode
== TYPE_MODE (long_integer_type_node
))
return unsignedp
? long_unsigned_type_node
: long_integer_type_node
;
if (mode
== TYPE_MODE (long_long_integer_type_node
))
return unsignedp
? long_long_unsigned_type_node
: long_long_integer_type_node
;
if (mode
== TYPE_MODE (intQI_type_node
))
return unsignedp
? unsigned_intQI_type_node
: intQI_type_node
;
if (mode
== TYPE_MODE (intHI_type_node
))
return unsignedp
? unsigned_intHI_type_node
: intHI_type_node
;
if (mode
== TYPE_MODE (intSI_type_node
))
return unsignedp
? unsigned_intSI_type_node
: intSI_type_node
;
if (mode
== TYPE_MODE (intDI_type_node
))
return unsignedp
? unsigned_intDI_type_node
: intDI_type_node
;
if (mode
== TYPE_MODE (float_type_node
))
if (mode
== TYPE_MODE (double_type_node
))
if (mode
== TYPE_MODE (long_double_type_node
))
return long_double_type_node
;
if (mode
== TYPE_MODE (build_pointer_type (char_type_node
)))
return build_pointer_type (char_type_node
);
if (mode
== TYPE_MODE (build_pointer_type (integer_type_node
)))
return build_pointer_type (integer_type_node
);
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
error ("invalid truth-value expression");
opname
= "rotate"; break;
error ("invalid operands to binary %s", opname
);
/* Subroutine of build_binary_op, used for comparison operations.
See if the operands have both been converted from subword integer types
and, if so, perhaps change them both back to their original type.
The arguments of this function are all pointers to local variables
of build_binary_op: OP0_PTR is &OP0, OP1_PTR is &OP1,
RESTYPE_PTR is &RESULT_TYPE and RESCODE_PTR is &RESULTCODE.
If this function returns nonzero, it means that the comparison has
a constant value. What this function returns is an expression for
shorten_compare (op0_ptr
, op1_ptr
, restype_ptr
, rescode_ptr
)
enum tree_code
*rescode_ptr
;
int unsignedp0
, unsignedp1
;
enum tree_code code
= *rescode_ptr
;
/* Throw away any conversions to wider types
already present in the operands. */
primop0
= get_narrower (op0
, &unsignedp0
);
primop1
= get_narrower (op1
, &unsignedp1
);
/* Handle the case that OP0 does not *contain* a conversion
but it *requires* conversion to FINAL_TYPE. */
if (op0
== primop0
&& TREE_TYPE (op0
) != *restype_ptr
)
unsignedp0
= TREE_UNSIGNED (TREE_TYPE (op0
));
if (op1
== primop1
&& TREE_TYPE (op1
) != *restype_ptr
)
unsignedp1
= TREE_UNSIGNED (TREE_TYPE (op1
));
/* If one of the operands must be floated, we cannot optimize. */
real1
= TREE_CODE (TREE_TYPE (primop0
)) == REAL_TYPE
;
real2
= TREE_CODE (TREE_TYPE (primop1
)) == REAL_TYPE
;
/* If first arg is constant, swap the args (changing operation
so value is preserved), for canonicalization. */
if (TREE_CONSTANT (primop0
))
register tree tem
= primop0
;
register int temi
= unsignedp0
;
/* If comparing an integer against a constant more bits wide,
maybe we can deduce a value of 1 or 0 independent of the data.
Or else truncate the constant now
rather than extend the variable at run time.
This is only interesting if the constant is the wider arg.
Also, it is not safe if the constant is unsigned and the
variable arg is signed, since in this case the variable
would be sign-extended and then regarded as unsigned.
Our technique fails in this case because the lowest/highest
possible unsigned results don't follow naturally from the
lowest/highest possible values of the variable operand.
For just EQ_EXPR and NE_EXPR there is another technique that
could be used: see if the constant can be faithfully represented
in the other operand's type, by truncating it and reextending it
and see if that preserves the constant's value. */
&& TREE_CODE (primop1
) == INTEGER_CST
&& TYPE_PRECISION (TREE_TYPE (primop0
)) < TYPE_PRECISION (*restype_ptr
))
int min_gt
, max_gt
, min_lt
, max_lt
;
/* 1 if comparison is nominally unsigned. */
int unsignedp
= TREE_UNSIGNED (*restype_ptr
);
type
= signed_or_unsigned_type (unsignedp0
, TREE_TYPE (primop0
));
maxval
= TYPE_MAX_VALUE (type
);
minval
= TYPE_MIN_VALUE (type
);
if (unsignedp
&& !unsignedp0
)
*restype_ptr
= signed_type (*restype_ptr
);
if (TREE_TYPE (primop1
) != *restype_ptr
)
primop1
= convert (*restype_ptr
, primop1
);
if (type
!= *restype_ptr
)
minval
= convert (*restype_ptr
, minval
);
maxval
= convert (*restype_ptr
, maxval
);
if (unsignedp
&& unsignedp0
)
min_gt
= INT_CST_LT_UNSIGNED (primop1
, minval
);
max_gt
= INT_CST_LT_UNSIGNED (primop1
, maxval
);
min_lt
= INT_CST_LT_UNSIGNED (minval
, primop1
);
max_lt
= INT_CST_LT_UNSIGNED (maxval
, primop1
);
min_gt
= INT_CST_LT (primop1
, minval
);
max_gt
= INT_CST_LT (primop1
, maxval
);
min_lt
= INT_CST_LT (minval
, primop1
);
max_lt
= INT_CST_LT (maxval
, primop1
);
/* This used to be a switch, but Genix compiler can't handle that. */
else if (code
== EQ_EXPR
)
else if (code
== LT_EXPR
)
else if (code
== GT_EXPR
)
else if (code
== LE_EXPR
)
else if (code
== GE_EXPR
)
/* If primop0 was sign-extended and unsigned comparison specd,
we did a signed comparison above using the signed type bounds.
But the comparison we output must be unsigned.
Also, for inequalities, VAL is no good; but if the signed
comparison had *any* fixed result, it follows that the
unsigned comparison just tests the sign in reverse
(positive values are LE, negative ones GE).
So we can generate an unsigned comparison
against an extreme value of the signed type. */
if (unsignedp
&& !unsignedp0
)
primop1
= TYPE_MIN_VALUE (type
);
primop1
= TYPE_MAX_VALUE (type
);
type
= unsigned_type (type
);
if (!max_gt
&& !unsignedp0
)
/* This is the case of (char)x >?< 0x80, which people used to use
expecting old C compilers to change the 0x80 into -0x80. */
if (val
== integer_zero_node
)
warning ("comparison is always 0 due to limited range of data type");
if (val
== integer_one_node
)
warning ("comparison is always 1 due to limited range of data type");
if (!min_lt
&& unsignedp0
)
/* This is the case of (unsigned char)x >?< -1 or < 0. */
if (val
== integer_zero_node
)
warning ("comparison is always 0 due to limited range of data type");
if (val
== integer_one_node
)
warning ("comparison is always 1 due to limited range of data type");
/* Don't forget to evaluate PRIMOP0 if it has side effects. */
if (TREE_SIDE_EFFECTS (primop0
))
return build (COMPOUND_EXPR
, TREE_TYPE (val
), primop0
, val
);
/* Value is not predetermined, but do the comparison
in the type of the operand that is not constant.
TYPE is already properly set. */
&& TYPE_PRECISION (TREE_TYPE (primop0
)) == TYPE_PRECISION (TREE_TYPE (primop1
)))
type
= TREE_TYPE (primop0
);
/* If args' natural types are both narrower than nominal type
and both extend in the same manner, compare them
in the type of the wider arg.
Otherwise must actually extend both to the nominal
common type lest different ways of extending
(eg, (short)-1 == (unsigned short)-1 should be 0.) */
else if (unsignedp0
== unsignedp1
&& real1
== real2
&& TYPE_PRECISION (TREE_TYPE (primop0
)) < TYPE_PRECISION (*restype_ptr
)
&& TYPE_PRECISION (TREE_TYPE (primop1
)) < TYPE_PRECISION (*restype_ptr
))
type
= common_type (TREE_TYPE (primop0
), TREE_TYPE (primop1
));
type
= signed_or_unsigned_type (unsignedp0
|| TREE_UNSIGNED (*restype_ptr
),
/* Make sure shorter operand is extended the right way
to match the longer operand. */
primop0
= convert (signed_or_unsigned_type (unsignedp0
, TREE_TYPE (primop0
)),
primop1
= convert (signed_or_unsigned_type (unsignedp1
, TREE_TYPE (primop1
)),
/* Here we must do the comparison on the nominal type
using the args exactly as we received them. */
if (!real1
&& !real2
&& integer_zerop (primop1
)
&& TREE_UNSIGNED (TREE_TYPE (primop0
)))
warning ("unsigned value >= 0 is always 1");
value
= integer_one_node
;
warning ("unsigned value < 0 is always 0");
value
= integer_zero_node
;
/* Don't forget to evaluate PRIMOP0 if it has side effects. */
if (TREE_SIDE_EFFECTS (primop0
))
return build (COMPOUND_EXPR
, TREE_TYPE (value
),
*op0_ptr
= convert (type
, primop0
);
*op1_ptr
= convert (type
, primop1
);
*restype_ptr
= integer_type_node
;
/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
or validate its data type for an `if' or `while' statement or ?..: exp.
This preparation consists of taking the ordinary
representation of an expression expr and producing a valid tree
boolean expression describing whether expr is nonzero. We could
simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
but we optimize comparisons, &&, ||, and !.
The resulting type should always be `integer_type_node'. */
truthvalue_conversion (expr
)
register enum tree_code code
;
switch (TREE_CODE (expr
))
/* It is simpler and generates better code to have only TRUTH_*_EXPR
or comparison expressions as truth values at this level. */
/* A one-bit unsigned bit-field is already acceptable. */
if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr
, 1)))
&& TREE_UNSIGNED (TREE_OPERAND (expr
, 1)))
/* It is simpler and generates better code to have only TRUTH_*_EXPR
or comparison expressions as truth values at this level. */
if (integer_zerop (TREE_OPERAND (expr
, 1)))
return build_unary_op (TRUTH_NOT_EXPR
, TREE_OPERAND (expr
, 0), 0);
case NE_EXPR
: case LE_EXPR
: case GE_EXPR
: case LT_EXPR
: case GT_EXPR
:
return integer_zerop (expr
) ? integer_zero_node
: integer_one_node
;
return real_zerop (expr
) ? integer_zero_node
: integer_one_node
;
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr
, 0)))
return build (COMPOUND_EXPR
, integer_type_node
,
TREE_OPERAND (expr
, 0), integer_one_node
);
/* These don't change whether an object is non-zero or zero. */
return truthvalue_conversion (TREE_OPERAND (expr
, 0));
/* These don't change whether an object is zero or non-zero, but
we can't ignore them if their second arg has side-effects. */
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr
, 1)))
return build (COMPOUND_EXPR
, integer_type_node
, TREE_OPERAND (expr
, 1),
truthvalue_conversion (TREE_OPERAND (expr
, 0)));
return truthvalue_conversion (TREE_OPERAND (expr
, 0));
/* Distribute the conversion into the arms of a COND_EXPR. */
return fold (build (COND_EXPR
, integer_type_node
, TREE_OPERAND (expr
, 0),
truthvalue_conversion (TREE_OPERAND (expr
, 1)),
truthvalue_conversion (TREE_OPERAND (expr
, 2))));
/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
since that affects how `default_conversion' will behave. */
if (TREE_CODE (TREE_TYPE (expr
)) == REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (TREE_OPERAND (expr
, 0))) == REFERENCE_TYPE
)
/* If this is widening the argument, we can ignore it. */
if (TYPE_PRECISION (TREE_TYPE (expr
))
>= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr
, 0))))
return truthvalue_conversion (TREE_OPERAND (expr
, 0));
/* These can be changed into a comparison of the two objects. */
if (TREE_TYPE (TREE_OPERAND (expr
, 0))
== TREE_TYPE (TREE_OPERAND (expr
, 1)))
return build_binary_op (NE_EXPR
, TREE_OPERAND (expr
, 0),
TREE_OPERAND (expr
, 1), 1);
return build_binary_op (NE_EXPR
, TREE_OPERAND (expr
, 0),
TREE_TYPE (TREE_OPERAND (expr
, 0)),
TREE_OPERAND (expr
, 1))), 1);
if (warn_parentheses
&& C_EXP_ORIGINAL_CODE (expr
) == MODIFY_EXPR
)
warning ("suggest parentheses around assignment used as truth value");
return build_binary_op (NE_EXPR
, expr
, integer_zero_node
, 1);
/* Read the rest of a #-directive from input stream FINPUT.
In normal use, the directive name and the white space after it
have already been read, so they won't be included in the result.
We allow for the fact that the directive line may contain
a newline embedded within a character or string literal which forms
The value is a string in a reusable buffer. It remains valid
only until the next time this function is called. */
get_directive_line (finput
)
static char *directive_buffer
= NULL
;
static unsigned buffer_length
= 0;
register char *buffer_limit
;
register int looking_for
= 0;
register int char_escaped
= 0;
directive_buffer
= (char *)xmalloc (128);
buffer_limit
= &directive_buffer
[buffer_length
];
for (p
= directive_buffer
; ; )
/* Make buffer bigger if it is full. */
register unsigned bytes_used
= (p
- directive_buffer
);
= (char *)xrealloc (directive_buffer
, buffer_length
);
p
= &directive_buffer
[bytes_used
];
buffer_limit
= &directive_buffer
[buffer_length
];
/* Discard initial whitespace. */
if ((c
== ' ' || c
== '\t') && p
== directive_buffer
)
/* Detect the end of the directive. */
if (c
== '\n' && looking_for
== 0)
/* Handle string and character constant syntax. */
if (looking_for
== c
&& !char_escaped
)
looking_for
= 0; /* Found terminator... stop looking. */
if (c
== '\'' || c
== '"')
looking_for
= c
; /* Don't stop buffering until we see another
another one of these (or an EOF). */
char_escaped
= (c
== '\\' && ! char_escaped
);