home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 7
/
FreshFishVol7.bin
/
bbs
/
gnu
/
gcc-2.3.3-src.lha
/
GNU
/
src
/
amiga
/
gcc-2.3.3
/
c-common.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-06
|
30KB
|
1,010 lines
/* 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)
any later version.
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. */
#include "config.h"
#include "tree.h"
#include "c-lex.h"
#include "c-tree.h"
#include "flags.h"
#include <stdio.h>
/* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
void
declare_function_name ()
{
tree decl, init;
char *name, *printable_name;
if (current_function_decl == NULL)
{
name = "";
printable_name = "top level";
}
else
{
char *kind = "function";
if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)
kind = "method";
/* Allow functions to be nameless (such as artificial ones). */
if (DECL_NAME (current_function_decl))
name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
else
name = "";
printable_name = (*decl_printable_name) (current_function_decl, &kind);
}
push_obstacks_nochange ();
decl = build_decl (VAR_DECL, get_identifier ("__FUNCTION__"),
char_array_type_node);
TREE_STATIC (decl) = 1;
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__"),
char_array_type_node);
TREE_STATIC (decl) = 1;
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. */
tree
combine_strings (strings)
tree strings;
{
register tree value, t;
register int length = 1;
int wide_length = 0;
int wide_flag = 0;
int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
int nchars;
if (TREE_CHAIN (strings))
{
/* More than one in the chain, so concatenate. */
register char *p, *q;
/* Don't include the \0 at the end of each substring,
except for the last one.
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);
wide_flag = 1;
}
else
length += (TREE_STRING_LENGTH (t) - 1);
}
/* If anything is wide, the non-wides will be converted,
which makes them take more space. */
if (wide_flag)
length = length * wchar_bytes + wide_length;
p = savealloc (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. */
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)
{
bcopy (TREE_STRING_POINTER (t), q, len);
q += len;
}
else
{
int i;
for (i = 0; i < len; i++)
((int *) q)[i] = TREE_STRING_POINTER (t)[i];
q += len * wchar_bytes;
}
}
if (wide_flag)
{
int i;
for (i = 0; i < wchar_bytes; i++)
*q++ = 0;
}
else
*q = 0;
value = make_node (STRING_CST);
TREE_STRING_POINTER (value) = p;
TREE_STRING_LENGTH (value) = length;
TREE_CONSTANT (value) = 1;
}
else
{
value = strings;
length = TREE_STRING_LENGTH (value);
if (TREE_TYPE (value) == wchar_array_type_node)
wide_flag = 1;
}
/* 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. */
if (warn_write_strings
&& (! 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,
build_index_type (build_int_2 (nchars - 1, 0)));
}
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;
TREE_STATIC (value) = 1;
return value;
}
/* Process the attributes listed in ATTRIBUTES
and install them in DECL. */
void
decl_attributes (decl, attributes)
tree decl, attributes;
{
tree a;
for (a = attributes; a; a = TREE_CHAIN (a))
if (TREE_VALUE (a) == get_identifier ("packed"))
{
if (TREE_CODE (decl) == FIELD_DECL)
DECL_PACKED (decl) = 1;
/* 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"))
{
int i;
char *specified_name
= 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)))
{
tree type
= type_for_mode (i, TREE_UNSIGNED (TREE_TYPE (decl)));
if (type != 0)
{
TREE_TYPE (decl) = type;
DECL_SIZE (decl) = 0;
layout_decl (decl, 0);
}
else
error ("no data type for mode `%s'", specified_name);
break;
}
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)))
* BITS_PER_UNIT;
if (exact_log2 (align) == -1)
error_with_decl (decl,
"requested alignment of `%s' is not a power of 2");
else if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FIELD_DECL)
error_with_decl (decl,
"alignment specified for `%s'");
else
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)));
int is_scan;
if (TREE_CODE (decl) != FUNCTION_DECL)
{
error_with_decl (decl,
"argument format specified for non-function `%s'");
return;
}
if (format_type == get_identifier ("printf"))
is_scan = 0;
else if (format_type == get_identifier ("scanf"))
is_scan = 1;
else
{
error_with_decl (decl, "unrecognized format specifier for `%s'");
return;
}
if (first_arg_num != 0 && first_arg_num <= format_num)
{
error_with_decl