+2007-06-01 Borut Razem <borut.razem AT siol.net>
+
+ * SDCPP synchronized with GCC CPP release version 4.2.0,
+ currently the latest release:
+ * support/cpp2/c-incpath.c, support/cpp2/c-incpath.h,
+ support/cpp2/c-ppoutput.c, support/cpp2/cppdefault.c,
+ support/cpp2/cppdefault.h, support/cpp2/except.h,
+ support/cpp2/libcpp/directives.c, support/cpp2/libcpp/expr.c,
+ support/cpp2/libcpp/files.c, support/cpp2/libcpp/include/cpplib.h,
+ support/cpp2/libcpp/init.c, support/cpp2/libcpp/internal.h,
+ support/cpp2/libcpp/lex.c, support/cpp2/libcpp/macro.c,
+ support/cpp2/libcpp/mkdeps.c, support/cpp2/libiberty/getpwd.c,
+ support/cpp2/libiberty/hashtab.c, support/cpp2/optc-gen.awk,
+ support/cpp2/opth-gen.awk, support/cpp2/opts.c,
+ support/cpp2/opts.h, support/cpp2/output.h,
+ support/cpp2/prefix.c, support/cpp2/sdcpp-opts.c,
+ support/cpp2/sdcpp.dsp, support/cpp2/sdcpp.opt,
+ support/cpp2/system.h, support/cpp2/version.c: modified
+ * support/cpp2/opts-common.c: added
+
2007-06-01 Raphael Neider <rneider AT web.de>
* device/lib/pic/libdev/pic12f683.c,
/* Set up combined include path chain for the preprocessor.
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Broken out of cppinit.c and cppfiles.c and rewritten Mar 2003.
# define INO_T_COPY(DEST, SRC) (DEST) = (SRC)
#endif
+static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
+
static void add_env_var_paths (const char *, int);
-static void add_standard_paths (const char *, const char *, int);
+static void add_standard_paths (const char *, const char *, const char *, int);
static void free_path (struct cpp_dir *, int);
static void merge_include_chains (cpp_reader *, int);
static struct cpp_dir *remove_duplicates (cpp_reader *, struct cpp_dir *,
path = xstrdup (".");
else
{
- path = xmalloc (q - p + 1);
+ path = XNEWVEC (char, q - p + 1);
memcpy (path, p, q - p);
path[q - p] = '\0';
}
/* Append the standard include chain defined in cppdefault.c. */
static void
-add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
+add_standard_paths (const char *sysroot, const char *iprefix,
+ const char *imultilib, int cxx_stdinc)
{
const struct default_include *p;
size_t len;
if (!strncmp (p->fname, cpp_GCC_INCLUDE_DIR, len))
{
char *str = concat (iprefix, p->fname + len, NULL);
+ if (p->multilib && imultilib)
+ str = concat (str, dir_separator_str, imultilib, NULL);
add_path (str, SYSTEM, p->cxx_aware, false);
}
}
else
str = update_path (p->fname, p->component);
+ if (p->multilib && imultilib)
+ str = concat (str, dir_separator_str, imultilib, NULL);
+
add_path (str, SYSTEM, p->cxx_aware, false);
}
}
if (*c == '\\') *c = '/';
#endif
- p = xmalloc (sizeof (cpp_dir));
+ p = XNEW (cpp_dir);
p->next = NULL;
p->name = path;
if (chain == SYSTEM || chain == AFTER)
removal, and registration with cpplib. */
void
register_include_chains (cpp_reader *pfile, const char *sysroot,
- const char *iprefix, int stdinc, int cxx_stdinc,
- int verbose)
+ const char *iprefix, const char *imultilib,
+ int stdinc, int cxx_stdinc, int verbose)
{
static const char *const lang_env_vars[] =
{ "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH",
/* Finally chain on the standard directories. */
if (stdinc)
- add_standard_paths (sysroot, iprefix, cxx_stdinc);
+ add_standard_paths (sysroot, iprefix, imultilib, cxx_stdinc);
target_c_incpath.extra_includes (sysroot, iprefix, stdinc);
/* Set up combined include path for the preprocessor.
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
extern void split_quote_chain (void);
extern void add_path (char *, int, int, bool);
extern void register_include_chains (cpp_reader *, const char *,
- const char *, int, int, int);
+ const char *, const char *,
+ int, int, int);
extern void add_cpp_dir_path (struct cpp_dir *, int);
struct target_c_incpath_s {
const struct line_map *map = linemap_lookup (&line_table, src_loc);
size_t to_file_len = strlen (map->to_file);
- unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
+ unsigned char *to_file_quoted =
+ (unsigned char *) alloca (to_file_len * 4 + 1);
unsigned char *p;
print.src_line = SOURCE_LINE (map, src_loc);
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- print.src_line++;
+ if (linemap_lookup (&line_table, line)->to_line != 0)
+ print.src_line++;
}
static void
pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
{
size_t to_file_len = strlen (dir);
- unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
+ unsigned char *to_file_quoted =
+ (unsigned char *) alloca (to_file_len * 4 + 1);
unsigned char *p;
/* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */
/* CPP Library.
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
= {
#ifdef GPLUSPLUS_INCLUDE_DIR
/* Pick up GNU C++ generic include files. */
- { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0 },
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0, 0 },
#endif
#ifdef GPLUSPLUS_TOOL_INCLUDE_DIR
/* Pick up GNU C++ target-dependent include files. */
- { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, 0 },
+ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, 0, 1 },
#endif
#ifdef GPLUSPLUS_BACKWARD_INCLUDE_DIR
/* Pick up GNU C++ backward and deprecated include files. */
- { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, 0 },
+ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, 0, 0 },
#endif
#ifdef LOCAL_INCLUDE_DIR
/* /usr/local/include comes before the fixincluded header files. */
- { LOCAL_INCLUDE_DIR, 0, 0, 1, 1 },
+ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 0 },
#endif
#ifdef PREFIX_INCLUDE_DIR
- { PREFIX_INCLUDE_DIR, 0, 0, 1, 0 },
+ { PREFIX_INCLUDE_DIR, 0, 0, 1, 0, 0 },
#endif
#ifdef GCC_INCLUDE_DIR
/* This is the dir for fixincludes and for gcc's private headers. */
- { GCC_INCLUDE_DIR, "GCC", 0, 0, 0 },
+ { GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 },
#endif
#ifdef CROSS_INCLUDE_DIR
/* One place the target system's headers might be. */
- { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0 },
+ { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0, 0 },
#endif
#ifdef TOOL_INCLUDE_DIR
/* Another place the target system's headers might be. */
- { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0 },
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0, 0 },
#endif
#ifdef SYSTEM_INCLUDE_DIR
/* Some systems have an extra dir of include files. */
- { SYSTEM_INCLUDE_DIR, 0, 0, 0, 1 },
+ { SYSTEM_INCLUDE_DIR, 0, 0, 0, 1, 0 },
#endif
#ifdef STANDARD_INCLUDE_DIR
/* /usr/include comes dead last. */
- { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 1 },
+ { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 1, 0 },
#endif
- { 0, 0, 0, 0, 0 }
+ { 0, 0, 0, 0, 0, 0 }
};
#endif /* no INCLUDE_DEFAULTS */
/* CPP Library.
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
C++. */
const char add_sysroot; /* FNAME should be prefixed by
cpp_SYSROOT. */
+ const char multilib; /* FNAME should have the multilib path
+ specified with -imultilib
+ appended. */
};
extern const struct default_include cpp_include_defaults[];
extern bool can_throw_external (rtx);
/* Set TREE_NOTHROW and cfun->all_throwers_are_sibcalls. */
-extern void set_nothrow_function_flags (void);
+extern unsigned int set_nothrow_function_flags (void);
/* After initial rtl generation, call back to finish generating
exception support code. */
extern void maybe_remove_eh_handler (rtx);
extern void convert_from_eh_region_ranges (void);
-extern void convert_to_eh_region_ranges (void);
+extern unsigned int convert_to_eh_region_ranges (void);
extern void find_exception_handler_labels (void);
extern bool current_function_has_exception_handlers (void);
extern void output_function_exception_table (void);
extern rtx get_exception_pointer (struct function *);
extern rtx get_exception_filter (struct function *);
typedef tree (*duplicate_eh_regions_map) (tree, void *);
-extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map, void *, int);
+extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map,
+ void *, int, int);
extern void sjlj_emit_function_exit_after (rtx);
extern void default_init_unwind_resume_libfunc (void);
extern void expand_resx_expr (tree);
extern void verify_eh_tree (struct function *);
extern void dump_eh_tree (FILE *, struct function *);
+extern bool eh_region_outer_p (struct function *, int, int);
+extern int eh_region_outermost (struct function *, int, int);
/* tree-eh.c */
extern void add_stmt_to_eh_region_fn (struct function *, tree, int);
extern struct htab *get_eh_throw_stmt_table (struct function *);
extern void set_eh_throw_stmt_table (struct function *, struct htab *);
+
+#ifdef ENABLE_CHECKING
+extern void verify_eh_throw_table_statements (void);
+#endif
/* CPP Library. (Directive handling.)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
struct pragma_entry *next;
const cpp_hashnode *pragma; /* Name and length. */
bool is_nspace;
- bool allow_expansion;
bool is_internal;
+ bool is_deferred;
+ bool allow_expansion;
union {
pragma_cb handler;
struct pragma_entry *space;
+ unsigned int ident;
} u;
};
static void do_include_common (cpp_reader *, enum include_type);
static struct pragma_entry *lookup_pragma_entry (struct pragma_entry *,
const cpp_hashnode *);
-static struct pragma_entry *insert_pragma_entry (cpp_reader *,
- struct pragma_entry **,
- const cpp_hashnode *,
- pragma_cb,
- bool, bool);
-static void register_pragma (cpp_reader *, const char *, const char *,
- pragma_cb, bool, bool);
static int count_registered_pragmas (struct pragma_entry *);
static char ** save_registered_pragmas (struct pragma_entry *, char **);
static char ** restore_registered_pragmas (cpp_reader *, struct pragma_entry *,
static void
end_directive (cpp_reader *pfile, int skip_line)
{
- if (CPP_OPTION (pfile, traditional))
+ if (pfile->state.in_deferred_pragma)
+ ;
+ else if (CPP_OPTION (pfile, traditional))
{
/* Revert change of prepare_directive_trad. */
pfile->state.prevent_expansion--;
{
cpp_push_buffer (pfile, (const uchar *) buf, count,
/* from_stage3 */ true);
- /* Disgusting hack. */
- if (dir_no == T_PRAGMA && pfile->buffer->prev)
- pfile->buffer->file = pfile->buffer->prev->file;
start_directive (pfile);
/* This is a short-term fix to prevent a leading '#' being
prepare_directive_trad (pfile);
pfile->directive->handler (pfile);
end_directive (pfile, 1);
- if (dir_no == T_PRAGMA)
- pfile->buffer->file = NULL;
_cpp_pop_buffer (pfile);
}
return chain;
}
-/* Create and insert a pragma entry for NAME at the beginning of a
- singly-linked CHAIN. If handler is NULL, it is a namespace,
- otherwise it is a pragma and its handler. If INTERNAL is true
- this pragma is being inserted by libcpp itself. */
+/* Create and insert a blank pragma entry at the beginning of a
+ singly-linked CHAIN. */
static struct pragma_entry *
-insert_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain,
- const cpp_hashnode *pragma, pragma_cb handler,
- bool allow_expansion, bool internal)
+new_pragma_entry (cpp_reader *pfile, struct pragma_entry **chain)
{
struct pragma_entry *new_entry;
new_entry = (struct pragma_entry *)
_cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
- new_entry->pragma = pragma;
- if (handler)
- {
- new_entry->is_nspace = 0;
- new_entry->u.handler = handler;
- }
- else
- {
- new_entry->is_nspace = 1;
- new_entry->u.space = NULL;
- }
- new_entry->allow_expansion = allow_expansion;
- new_entry->is_internal = internal;
+ memset (new_entry, 0, sizeof (struct pragma_entry));
new_entry->next = *chain;
+
*chain = new_entry;
return new_entry;
}
/* Register a pragma NAME in namespace SPACE. If SPACE is null, it
- goes in the global namespace. HANDLER is the handler it will call,
- which must be non-NULL. If ALLOW_EXPANSION is set, allow macro
- expansion while parsing pragma NAME. INTERNAL is true if this is a
- pragma registered by cpplib itself, false if it is registered via
- cpp_register_pragma */
-static void
-register_pragma (cpp_reader *pfile, const char *space, const char *name,
- pragma_cb handler, bool allow_expansion, bool internal)
+ goes in the global namespace. */
+static struct pragma_entry *
+register_pragma_1 (cpp_reader *pfile, const char *space, const char *name,
+ bool allow_name_expansion)
{
struct pragma_entry **chain = &pfile->pragmas;
struct pragma_entry *entry;
const cpp_hashnode *node;
- if (!handler)
- abort ();
-
if (space)
{
node = cpp_lookup (pfile, U space, strlen (space));
entry = lookup_pragma_entry (*chain, node);
if (!entry)
- entry = insert_pragma_entry (pfile, chain, node, NULL,
- allow_expansion, internal);
+ {
+ entry = new_pragma_entry (pfile, chain);
+ entry->pragma = node;
+ entry->is_nspace = true;
+ entry->allow_expansion = allow_name_expansion;
+ }
else if (!entry->is_nspace)
goto clash;
+ else if (entry->allow_expansion != allow_name_expansion)
+ {
+ cpp_error (pfile, CPP_DL_ICE,
+ "registering pragmas in namespace \"%s\" with mismatched "
+ "name expansion", space);
+ return NULL;
+ }
chain = &entry->u.space;
}
+ else if (allow_name_expansion)
+ {
+ cpp_error (pfile, CPP_DL_ICE,
+ "registering pragma \"%s\" with name expansion "
+ "and no namespace", name);
+ return NULL;
+ }
/* Check for duplicates. */
node = cpp_lookup (pfile, U name, strlen (name));
entry = lookup_pragma_entry (*chain, node);
- if (entry)
+ if (entry == NULL)
{
- if (entry->is_nspace)
- clash:
- cpp_error (pfile, CPP_DL_ICE,
- "registering \"%s\" as both a pragma and a pragma namespace",
- NODE_NAME (node));
- else if (space)
- cpp_error (pfile, CPP_DL_ICE, "#pragma %s %s is already registered",
- space, name);
- else
- cpp_error (pfile, CPP_DL_ICE, "#pragma %s is already registered", name);
+ entry = new_pragma_entry (pfile, chain);
+ entry->pragma = node;
+ return entry;
}
+
+ if (entry->is_nspace)
+ clash:
+ cpp_error (pfile, CPP_DL_ICE,
+ "registering \"%s\" as both a pragma and a pragma namespace",
+ NODE_NAME (node));
+ else if (space)
+ cpp_error (pfile, CPP_DL_ICE, "#pragma %s %s is already registered",
+ space, name);
else
- insert_pragma_entry (pfile, chain, node, handler, allow_expansion,
- internal);
+ cpp_error (pfile, CPP_DL_ICE, "#pragma %s is already registered", name);
+
+ return NULL;
+}
+
+/* Register a cpplib internal pragma SPACE NAME with HANDLER. */
+static void
+register_pragma_internal (cpp_reader *pfile, const char *space,
+ const char *name, pragma_cb handler)
+{
+ struct pragma_entry *entry;
+
+ entry = register_pragma_1 (pfile, space, name, false);
+ entry->is_internal = true;
+ entry->u.handler = handler;
}
/* Register a pragma NAME in namespace SPACE. If SPACE is null, it
cpp_register_pragma (cpp_reader *pfile, const char *space, const char *name,
pragma_cb handler, bool allow_expansion)
{
- register_pragma (pfile, space, name, handler, allow_expansion, false);
+ struct pragma_entry *entry;
+
+ if (!handler)
+ {
+ cpp_error (pfile, CPP_DL_ICE, "registering pragma with NULL handler");
+ return;
+ }
+
+ entry = register_pragma_1 (pfile, space, name, false);
+ if (entry)
+ {
+ entry->allow_expansion = allow_expansion;
+ entry->u.handler = handler;
+ }
}
+/* Similarly, but create mark the pragma for deferred processing.
+ When found, a CPP_PRAGMA token will be insertted into the stream
+ with IDENT in the token->u.pragma slot. */
+void
+cpp_register_deferred_pragma (cpp_reader *pfile, const char *space,
+ const char *name, unsigned int ident,
+ bool allow_expansion, bool allow_name_expansion)
+{
+ struct pragma_entry *entry;
+
+ entry = register_pragma_1 (pfile, space, name, allow_name_expansion);
+ if (entry)
+ {
+ entry->is_deferred = true;
+ entry->allow_expansion = allow_expansion;
+ entry->u.ident = ident;
+ }
+}
+
/* Register the pragmas the preprocessor itself handles. */
void
_cpp_init_internal_pragmas (cpp_reader *pfile)
{
/* Pragmas in the global namespace. */
- register_pragma (pfile, 0, "once", do_pragma_once, false, true);
+ register_pragma_internal (pfile, 0, "once", do_pragma_once);
/* New GCC-specific pragmas should be put in the GCC namespace. */
- register_pragma (pfile, "GCC", "poison", do_pragma_poison, false, true);
- register_pragma (pfile, "GCC", "system_header", do_pragma_system_header,
- false, true);
- register_pragma (pfile, "GCC", "dependency", do_pragma_dependency,
- false, true);
+ register_pragma_internal (pfile, "GCC", "poison", do_pragma_poison);
+ register_pragma_internal (pfile, "GCC", "system_header",
+ do_pragma_system_header);
+ register_pragma_internal (pfile, "GCC", "dependency", do_pragma_dependency);
}
/* Return the number of registered pragmas in PE. */
front end. C99 defines three pragmas and says that no macro
expansion is to be performed on them; whether or not macro
expansion happens for other pragmas is implementation defined.
- This implementation never macro-expands the text after #pragma.
-
- The library user has the option of deferring execution of
- #pragmas not handled by cpplib, in which case they are converted
- to CPP_PRAGMA tokens and inserted into the output stream. */
+ This implementation allows for a mix of both, since GCC did not
+ traditionally macro expand its (few) pragmas, whereas OpenMP
+ specifies that macro expansion should happen. */
static void
do_pragma (cpp_reader *pfile)
{
const struct pragma_entry *p = NULL;
const cpp_token *token, *pragma_token = pfile->cur_token;
+ cpp_token ns_token;
unsigned int count = 1;
- /* Save the current position so that defer_pragmas mode can
- copy the entire current line to a string. It will not work
- to use _cpp_backup_tokens as that does not reverse buffer->cur. */
- const uchar *line_start = CPP_BUFFER (pfile)->cur;
-
pfile->state.prevent_expansion++;
token = cpp_get_token (pfile);
+ ns_token = *token;
if (token->type == CPP_NAME)
{
p = lookup_pragma_entry (pfile->pragmas, token->val.node);
if (p && p->is_nspace)
{
- count = 2;
+ bool allow_name_expansion = p->allow_expansion;
+ if (allow_name_expansion)
+ pfile->state.prevent_expansion--;
token = cpp_get_token (pfile);
if (token->type == CPP_NAME)
p = lookup_pragma_entry (p->u.space, token->val.node);
else
p = NULL;
+ if (allow_name_expansion)
+ pfile->state.prevent_expansion++;
+ count = 2;
}
}
if (p)
{
- if (p->is_internal || !CPP_OPTION (pfile, defer_pragmas))
+ if (p->is_deferred)
+ {
+ pfile->directive_result.src_loc = pragma_token->src_loc;
+ pfile->directive_result.type = CPP_PRAGMA;
+ pfile->directive_result.flags = pragma_token->flags;
+ pfile->directive_result.val.pragma = p->u.ident;
+ pfile->state.in_deferred_pragma = true;
+ pfile->state.pragma_allow_expansion = p->allow_expansion;
+ if (!p->allow_expansion)
+ pfile->state.prevent_expansion++;
+ }
+ else
{
- /* Since the handler below doesn't get the line number, that it
- might need for diagnostics, make sure it has the right
+ /* Since the handler below doesn't get the line number, that
+ it might need for diagnostics, make sure it has the right
numbers in place. */
if (pfile->cb.line_change)
(*pfile->cb.line_change) (pfile, pragma_token, false);
- /* Never expand macros if handling a deferred pragma, since
- the macro definitions now applicable may be different
- from those at the point the pragma appeared. */
- if (p->allow_expansion && !pfile->state.in_deferred_pragma)
+ if (p->allow_expansion)
pfile->state.prevent_expansion--;
(*p->u.handler) (pfile);
- if (p->allow_expansion && !pfile->state.in_deferred_pragma)
+ if (p->allow_expansion)
pfile->state.prevent_expansion++;
}
- else
- {
- /* Squirrel away the pragma text. Pragmas are
- newline-terminated. */
- const uchar *line_end;
- uchar *s, c, cc;
- cpp_string body;
- cpp_token *ptok;
-
- for (line_end = line_start; (c = *line_end) != '\n'; line_end++)
- if (c == '"' || c == '\'')
- {
- /* Skip over string literal. */
- do
- {
- cc = *++line_end;
- if (cc == '\\' && line_end[1] != '\n')
- line_end++;
- else if (cc == '\n')
- {
- line_end--;
- break;
- }
- }
- while (cc != c);
- }
- else if (c == '/')
- {
- if (line_end[1] == '*')
- {
- /* Skip over C block comment, unless it is multi-line.
- When encountering multi-line block comment, terminate
- the pragma token right before that block comment. */
- const uchar *le = line_end + 2;
- while (*le != '\n')
- if (*le++ == '*' && *le == '/')
- {
- line_end = le;
- break;
- }
- if (line_end < le)
- break;
- }
- else if (line_end[1] == '/'
- && (CPP_OPTION (pfile, cplusplus_comments)
- || cpp_in_system_header (pfile)))
- {
- line_end += 2;
- while (*line_end != '\n')
- line_end++;
- break;
- }
- }
-
- body.len = (line_end - line_start) + 1;
- s = _cpp_unaligned_alloc (pfile, body.len + 1);
- memcpy (s, line_start, body.len - 1);
- s[body.len - 1] = '\n';
- s[body.len] = '\0';
- body.text = s;
-
- /* Create a CPP_PRAGMA token. */
- ptok = &pfile->directive_result;
- ptok->src_loc = pragma_token->src_loc;
- ptok->type = CPP_PRAGMA;
- ptok->flags = pragma_token->flags | NO_EXPAND;
- ptok->val.str = body;
- }
}
else if (pfile->cb.def_pragma)
{
- _cpp_backup_tokens (pfile, count);
+ if (count == 1 || pfile->context->prev == NULL)
+ _cpp_backup_tokens (pfile, count);
+ else
+ {
+ /* Invalid name comes from macro expansion, _cpp_backup_tokens
+ won't allow backing 2 tokens. */
+ /* ??? The token buffer is leaked. Perhaps if def_pragma hook
+ reads both tokens, we could perhaps free it, but if it doesn't,
+ we don't know the exact lifespan. */
+ cpp_token *toks = XNEWVEC (cpp_token, 2);
+ toks[0] = ns_token;
+ toks[0].flags |= NO_EXPAND;
+ toks[1] = *token;
+ toks[1].flags |= NO_EXPAND;
+ _cpp_push_token_context (pfile, NULL, toks, 2);
+ }
pfile->cb.def_pragma (pfile, pfile->directive_line);
}
{
const unsigned char *src, *limit;
char *dest, *result;
+ cpp_context *saved_context;
+ cpp_token *saved_cur_token;
+ tokenrun *saved_cur_run;
+ cpp_token *toks;
+ int count;
dest = result = (char *) alloca (in->len - 1);
src = in->text + 1 + (in->text[0] == 'L');
Something like line-at-a-time lexing should remove the need for
this. */
- {
- cpp_context *saved_context = pfile->context;
- cpp_token *saved_cur_token = pfile->cur_token;
- tokenrun *saved_cur_run = pfile->cur_run;
-
- pfile->context = XNEW (cpp_context);
- pfile->context->macro = 0;
- pfile->context->prev = 0;
- run_directive (pfile, T_PRAGMA, result, dest - result);
- XDELETE (pfile->context);
- pfile->context = saved_context;
- pfile->cur_token = saved_cur_token;
- pfile->cur_run = saved_cur_run;
- }
+ saved_context = pfile->context;
+ saved_cur_token = pfile->cur_token;
+ saved_cur_run = pfile->cur_run;
- /* See above comment. For the moment, we'd like
+ pfile->context = XNEW (cpp_context);
+ pfile->context->macro = 0;
+ pfile->context->prev = 0;
+ pfile->context->next = 0;
+
+ /* Inline run_directive, since we need to delay the _cpp_pop_buffer
+ until we've read all of the tokens that we want. */
+ cpp_push_buffer (pfile, (const uchar *) result, dest - result,
+ /* from_stage3 */ true);
+ /* ??? Antique Disgusting Hack. What does this do? */
+ if (pfile->buffer->prev)
+ pfile->buffer->file = pfile->buffer->prev->file;
- token1 _Pragma ("foo") token2
+ start_directive (pfile);
+ _cpp_clean_line (pfile);
+ do_pragma (pfile);
+ end_directive (pfile, 1);
- to be output as
+ /* We always insert at least one token, the directive result. It'll
+ either be a CPP_PADDING or a CPP_PRAGMA. In the later case, we
+ need to insert *all* of the tokens, including the CPP_PRAGMA_EOL. */
+
+ /* If we're not handling the pragma internally, read all of the tokens from
+ the string buffer now, while the string buffer is still installed. */
+ /* ??? Note that the token buffer allocated here is leaked. It's not clear
+ to me what the true lifespan of the tokens are. It would appear that
+ the lifespan is the entire parse of the main input stream, in which case
+ this may not be wrong. */
+ if (pfile->directive_result.type == CPP_PRAGMA)
+ {
+ int maxcount;
- token1
- # 7 "file.c"
- #pragma foo
- # 7 "file.c"
- token2
+ count = 1;
+ maxcount = 50;
+ toks = XNEWVEC (cpp_token, maxcount);
+ toks[0] = pfile->directive_result;
- Getting the line markers is a little tricky. */
- if (pfile->cb.line_change)
- pfile->cb.line_change (pfile, pfile->cur_token, false);
+ do
+ {
+ if (count == maxcount)
+ {
+ maxcount = maxcount * 3 / 2;
+ toks = XRESIZEVEC (cpp_token, toks, maxcount);
+ }
+ toks[count] = *cpp_get_token (pfile);
+ /* Macros have been already expanded by cpp_get_token
+ if the pragma allowed expansion. */
+ toks[count++].flags |= NO_EXPAND;
+ }
+ while (toks[count-1].type != CPP_PRAGMA_EOL);
+ }
+ else
+ {
+ count = 1;
+ toks = XNEW (cpp_token);
+ toks[0] = pfile->directive_result;
+
+ /* If we handled the entire pragma internally, make sure we get the
+ line number correct for the next token. */
+ if (pfile->cb.line_change)
+ pfile->cb.line_change (pfile, pfile->cur_token, false);
+ }
+
+ /* Finish inlining run_directive. */
+ pfile->buffer->file = NULL;
+ _cpp_pop_buffer (pfile);
+
+ /* Reset the old macro state before ... */
+ XDELETE (pfile->context);
+ pfile->context = saved_context;
+ pfile->cur_token = saved_cur_token;
+ pfile->cur_run = saved_cur_run;
+
+ /* ... inserting the new tokens we collected. */
+ _cpp_push_token_context (pfile, NULL, toks, count);
}
/* Handle the _Pragma operator. */
"_Pragma takes a parenthesized string literal");
}
-/* Handle a pragma that the front end deferred until now. */
-void
-cpp_handle_deferred_pragma (cpp_reader *pfile, const cpp_string *s)
-{
- cpp_context *saved_context = pfile->context;
- cpp_token *saved_cur_token = pfile->cur_token;
- tokenrun *saved_cur_run = pfile->cur_run;
- bool saved_defer_pragmas = CPP_OPTION (pfile, defer_pragmas);
- void (*saved_line_change) (cpp_reader *, const cpp_token *, int)
- = pfile->cb.line_change;
-
- pfile->context = XNEW (cpp_context);
- pfile->context->macro = 0;
- pfile->context->prev = 0;
- pfile->cb.line_change = NULL;
- pfile->state.in_deferred_pragma = true;
- CPP_OPTION (pfile, defer_pragmas) = false;
-
- run_directive (pfile, T_PRAGMA, (const char *)s->text, s->len);
-
- XDELETE (pfile->context);
- pfile->context = saved_context;
- pfile->cur_token = saved_cur_token;
- pfile->cur_run = saved_cur_run;
- pfile->cb.line_change = saved_line_change;
- pfile->state.in_deferred_pragma = false;
- CPP_OPTION (pfile, defer_pragmas) = saved_defer_pragmas;
-}
-
/* Handle #ifdef. */
static void
do_ifdef (cpp_reader *pfile)
static unsigned int
interpret_float_suffix (const uchar *s, size_t len)
{
- size_t f = 0, l = 0, i = 0;
+ size_t f = 0, l = 0, i = 0, d = 0;
while (len--)
switch (s[len])
case 'l': case 'L': l++; break;
case 'i': case 'I':
case 'j': case 'J': i++; break;
+ case 'd': case 'D':
+ /* Disallow fd, ld suffixes. */
+ if (d && (f || l))
+ return 0;
+ d++;
+ break;
default:
return 0;
}
if (f + l > 1 || i > 1)
return 0;
+ /* Allow dd, df, dl suffixes for decimal float constants. */
+ if (d && ((d + f + l != 2) || i))
+ return 0;
+
return ((i ? CPP_N_IMAGINARY : 0)
| (f ? CPP_N_SMALL :
- l ? CPP_N_LARGE : CPP_N_MEDIUM));
+ l ? CPP_N_LARGE : CPP_N_MEDIUM)
+ | (d ? CPP_N_DFLOAT : 0));
}
/* Subroutine of cpp_classify_number. S points to an integer suffix
"traditional C rejects the \"%.*s\" suffix",
(int) (limit - str), str);
+ /* Radix must be 10 for decimal floats. */
+ if ((result & CPP_N_DFLOAT) && radix != 10)
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "invalid suffix \"%.*s\" with hexadecimal floating constant",
+ (int) (limit - str), str);
+ return CPP_N_INVALID;
+ }
+
result |= CPP_N_FLOATING;
}
else
/* RSHIFT */ {13, LEFT_ASSOC},
/* LSHIFT */ {13, LEFT_ASSOC},
- /* MIN */ {10, LEFT_ASSOC | CHECK_PROMOTION},
- /* MAX */ {10, LEFT_ASSOC | CHECK_PROMOTION},
-
/* COMPL */ {16, NO_L_OPERAND},
/* AND_AND */ {6, LEFT_ASSOC},
/* OR_OR */ {5, LEFT_ASSOC},
case CPP_MINUS:
case CPP_RSHIFT:
case CPP_LSHIFT:
- case CPP_MIN:
- case CPP_MAX:
case CPP_COMMA:
top[-1].value = num_binary_op (pfile, top[-1].value,
top->value, top->op);
{
cpp_num result;
size_t precision = CPP_OPTION (pfile, precision);
- bool gte;
size_t n;
switch (op)
lhs = num_rshift (lhs, precision, n);
break;
- /* Min / Max. */
- case CPP_MIN:
- case CPP_MAX:
- {
- bool unsignedp = lhs.unsignedp || rhs.unsignedp;
-
- gte = num_greater_eq (lhs, rhs, precision);
- if (op == CPP_MIN)
- gte = !gte;
- if (!gte)
- lhs = rhs;
- lhs.unsignedp = unsignedp;
- }
- break;
-
/* Arithmetic. */
case CPP_MINUS:
rhs = num_negate (rhs, precision);
}
}
+/* Inteface to file statistics record in _cpp_file structure. */
+struct stat *
+_cpp_get_file_stat (_cpp_file *file)
+{
+ return &file->st;
+}
+
/* Set the include chain for "" to QUOTE, for <> to BRACKET. If
QUOTE_IGNORES_SOURCE_DIR, then "" includes do not look in the
directory of the including file.
The first group, to CPP_LAST_EQ, can be immediately followed by an
'='. The lexer needs operators ending in '=', like ">>=", to be in
- the same order as their counterparts without the '=', like ">>". */
+ the same order as their counterparts without the '=', like ">>".
+
+ See the cpp_operator table optab in expr.c if you change the order or
+ add or remove anything in the first group. */
#define TTYPE_TABLE \
OP(EQ, "=") \
OP(XOR, "^") \
OP(RSHIFT, ">>") \
OP(LSHIFT, "<<") \
- OP(MIN, "<?") /* extension */ \
- OP(MAX, ">?") \
\
OP(COMPL, "~") \
OP(AND_AND, "&&") /* logical */ \
OP(XOR_EQ, "^=") \
OP(RSHIFT_EQ, ">>=") \
OP(LSHIFT_EQ, "<<=") \
- OP(MIN_EQ, "<?=") /* extension */ \
- OP(MAX_EQ, ">?=") \
/* Digraphs together, beginning with CPP_FIRST_DIGRAPH. */ \
OP(HASH, "#") /* digraphs */ \
OP(PASTE, "##") \
TK(COMMENT, LITERAL) /* Only if output comments. */ \
/* SPELL_LITERAL happens to DTRT. */ \
TK(MACRO_ARG, NONE) /* Macro argument. */ \
- TK(PRAGMA, NONE) /* Only if deferring pragmas */ \
+ TK(PRAGMA, NONE) /* Only for deferred pragmas. */ \
+ TK(PRAGMA_EOL, NONE) /* End-of-line for deferred pragmas. */ \
TK(PADDING, NONE) /* Whitespace for -E. */ \
\
/* SDCC _asm specific */ \
N_TTYPES,
/* Positions in the table. */
- CPP_LAST_EQ = CPP_MAX,
+ CPP_LAST_EQ = CPP_LSHIFT,
CPP_FIRST_DIGRAPH = CPP_HASH,
- CPP_LAST_PUNCTUATOR= CPP_DOT_STAR,
+ CPP_LAST_PUNCTUATOR= CPP_ATSIGN,
CPP_LAST_CPP_OP = CPP_LESS_EQ
};
#undef OP
#define NAMED_OP (1 << 4) /* C++ named operators. */
#define NO_EXPAND (1 << 5) /* Do not macro-expand this token. */
#define BOL (1 << 6) /* Token at beginning of line. */
+#define PURE_ZERO (1 << 7) /* Single 0 digit, used by the C++ frontend,
+ set in c-lex.c. */
/* Specify which field, if any, of the cpp_token union is used. */
CPP_TOKEN_FLD_SOURCE,
CPP_TOKEN_FLD_STR,
CPP_TOKEN_FLD_ARG_NO,
+ CPP_TOKEN_FLD_PRAGMA,
CPP_TOKEN_FLD_NONE
};
/* Argument no. for a CPP_MACRO_ARG. */
unsigned int GTY ((tag ("CPP_TOKEN_FLD_ARG_NO"))) arg_no;
+
+ /* Caller-supplied identifier for a CPP_PRAGMA. */
+ unsigned int GTY ((tag ("CPP_TOKEN_FLD_PRAGMA"))) pragma;
} GTY ((desc ("cpp_token_val_index (&%1)"))) val;
};
/* Nonzero means __STDC__ should have the value 0 in system headers. */
unsigned char stdc_0_in_system_headers;
- /* True means return pragmas as tokens rather than processing
- them directly. */
- bool defer_pragmas;
-
/* True means error callback should be used for diagnostics. */
bool client_diagnostic;
};
BT_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
BT_TIME, /* `__TIME__' */
BT_STDC, /* `__STDC__' */
- BT_PRAGMA /* `_Pragma' operator */
+ BT_PRAGMA, /* `_Pragma' operator */
+ BT_TIMESTAMP /* `__TIMESTAMP__' */
};
#define CPP_HASHNODE(HNODE) ((cpp_hashnode *) (HNODE))
unsigned char *, bool);
extern void cpp_register_pragma (cpp_reader *, const char *, const char *,
void (*) (cpp_reader *), bool);
-extern void cpp_handle_deferred_pragma (cpp_reader *, const cpp_string *);
+extern void cpp_register_deferred_pragma (cpp_reader *, const char *,
+ const char *, unsigned, bool, bool);
extern int cpp_avoid_paste (cpp_reader *, const cpp_token *,
const cpp_token *);
extern const cpp_token *cpp_get_token (cpp_reader *);
#define CPP_N_UNSIGNED 0x1000 /* Properties. */
#define CPP_N_IMAGINARY 0x2000
+#define CPP_N_DFLOAT 0x4000
/* Classify a CPP_NUMBER token. The return value is a combination of
the flags from the above sets. */
#define B(n, t) { DSC(n), t }
static const struct builtin builtin_array[] =
{
+ B("__TIMESTAMP__", BT_TIMESTAMP),
B("__TIME__", BT_TIME),
B("__DATE__", BT_DATE),
B("__FILE__", BT_FILE),
/* Nonzero to prevent macro expansion. */
unsigned char prevent_expansion;
- /* Nonzero when handling a deferred pragma. */
- unsigned char in_deferred_pragma;
-
/* Nonzero when parsing arguments to a function-like macro. */
unsigned char parsing_args;
/* Nonzero to skip evaluating part of an expression. */
unsigned int skip_eval;
+
+ /* Nonzero when handling a deferred pragma. */
+ unsigned char in_deferred_pragma;
+
+ /* Nonzero if the deferred pragma being handled allows macro expansion. */
+ unsigned char pragma_allow_expansion;
};
/* Special nodes - identifiers with predefined significance. */
Used for include_next and to record control macros. */
struct _cpp_file *file;
+ /* Saved value of __TIMESTAMP__ macro - date and time of last modification
+ of the assotiated file. */
+ const unsigned char *timestamp;
+
/* Value of if_stack at start of this file.
Used to prohibit unmatched #endif (etc) in an include file. */
struct if_stack *if_stack;
unsigned int);
extern const unsigned char *_cpp_builtin_macro_text (cpp_reader *,
cpp_hashnode *);
-int _cpp_warn_if_unused_macro (cpp_reader *, cpp_hashnode *, void *);
+extern int _cpp_warn_if_unused_macro (cpp_reader *, cpp_hashnode *, void *);
+extern void _cpp_push_token_context (cpp_reader *, cpp_hashnode *,
+ const cpp_token *, unsigned int);
+
/* In identifiers.c */
extern void _cpp_init_hashtable (cpp_reader *, hash_table *);
extern void _cpp_destroy_hashtable (cpp_reader *);
extern void _cpp_pop_file_buffer (cpp_reader *, struct _cpp_file *);
extern bool _cpp_save_file_entries (cpp_reader *pfile, FILE *f);
extern bool _cpp_read_file_entries (cpp_reader *, FILE *);
+extern struct stat *_cpp_get_file_stat (_cpp_file *);
/* In expr.c */
extern bool _cpp_parse_expr (cpp_reader *);
cpp_error (pfile, CPP_DL_WARNING,
"null character(s) preserved in literal");
+ if (type == CPP_OTHER && CPP_OPTION (pfile, lang) != CLK_ASM)
+ cpp_error (pfile, CPP_DL_PEDWARN, "missing terminating %c character",
+ (int) terminator);
+
pfile->buffer->cur = cur;
create_literal (pfile, token, base, cur - base, type);
}
/* 6.10.3 p 11: Directives in a list of macro arguments
gives undefined behavior. This implementation
handles the directive as normal. */
- && pfile->state.parsing_args != 1
- && _cpp_handle_directive (pfile, result->flags & PREV_WHITE))
+ && pfile->state.parsing_args != 1)
{
- if (pfile->directive_result.type == CPP_PADDING)
- continue;
- else
+ if (_cpp_handle_directive (pfile, result->flags & PREV_WHITE))
{
+ if (pfile->directive_result.type == CPP_PADDING)
+ continue;
result = &pfile->directive_result;
- break;
}
}
+ else if (pfile->state.in_deferred_pragma)
+ result = &pfile->directive_result;
if (pfile->cb.line_change && !pfile->state.skipping)
pfile->cb.line_change (pfile, result, pfile->state.parsing_args);
}
/* We don't skip tokens in directives. */
- if (pfile->state.in_directive)
+ if (pfile->state.in_directive || pfile->state.in_deferred_pragma)
break;
/* Outside a directive, invalidate controlling macros. At file
buffer = pfile->buffer;
if (buffer->need_line)
{
+ if (pfile->state.in_deferred_pragma)
+ {
+ result->type = CPP_PRAGMA_EOL;
+ pfile->state.in_deferred_pragma = false;
+ if (!pfile->state.pragma_allow_expansion)
+ pfile->state.prevent_expansion--;
+ return result;
+ }
if (!_cpp_get_fresh_line (pfile))
{
result->type = CPP_EOF;
buffer->cur++;
IF_NEXT_IS ('=', CPP_LSHIFT_EQ, CPP_LSHIFT);
}
- else if (*buffer->cur == '?' && CPP_OPTION (pfile, cplusplus))
- {
- buffer->cur++;
- IF_NEXT_IS ('=', CPP_MIN_EQ, CPP_MIN);
- }
else if (CPP_OPTION (pfile, digraphs))
{
if (*buffer->cur == ':')
buffer->cur++;
IF_NEXT_IS ('=', CPP_RSHIFT_EQ, CPP_RSHIFT);
}
- else if (*buffer->cur == '?' && CPP_OPTION (pfile, cplusplus))
- {
- buffer->cur++;
- IF_NEXT_IS ('=', CPP_MAX_EQ, CPP_MAX);
- }
break;
case '%':
switch (a)
{
- case CPP_GREATER: return c == '>' || c == '?';
- case CPP_LESS: return c == '<' || c == '?' || c == '%' || c == ':';
+ case CPP_GREATER: return c == '>';
+ case CPP_LESS: return c == '<' || c == '%' || c == ':';
case CPP_PLUS: return c == '+';
case CPP_MINUS: return c == '-' || c == '>';
case CPP_DIV: return c == '/' || c == '*'; /* Comments. */
else if (tok->type == CPP_PADDING)
return CPP_TOKEN_FLD_SOURCE;
else if (tok->type == CPP_PRAGMA)
- return CPP_TOKEN_FLD_STR;
+ return CPP_TOKEN_FLD_PRAGMA;
/* else fall through */
default:
return CPP_TOKEN_FLD_NONE;
static int enter_macro_context (cpp_reader *, cpp_hashnode *);
static int builtin_macro (cpp_reader *, cpp_hashnode *);
-static void push_token_context (cpp_reader *, cpp_hashnode *,
- const cpp_token *, unsigned int);
static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
const cpp_token **, unsigned int);
static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *);
NODE_NAME (node));
break;
+ case BT_TIMESTAMP:
+ {
+ cpp_buffer *pbuffer = cpp_get_buffer (pfile);
+ if (pbuffer->timestamp == NULL)
+ {
+ /* Initialize timestamp value of the assotiated file. */
+ struct _cpp_file *file = cpp_get_file (pbuffer);
+ if (file)
+ {
+ /* Generate __TIMESTAMP__ string, that represents
+ the date and time of the last modification
+ of the current source file. The string constant
+ looks like "Sun Sep 16 01:03:52 1973". */
+ struct tm *tb = NULL;
+ struct stat *st = _cpp_get_file_stat (file);
+ if (st)
+ tb = localtime (&st->st_mtime);
+ if (tb)
+ {
+ char *str = asctime (tb);
+ size_t len = strlen (str);
+ unsigned char *buf = _cpp_unaligned_alloc (pfile, len + 2);
+ buf[0] = '"';
+ strcpy ((char *) buf + 1, str);
+ buf[len] = '"';
+ pbuffer->timestamp = buf;
+ }
+ else
+ {
+ cpp_errno (pfile, CPP_DL_WARNING,
+ "could not determine file timestamp");
+ pbuffer->timestamp = U"\"??? ??? ?? ??:??:?? ????\"";
+ }
+ }
+ }
+ result = pbuffer->timestamp;
+ }
+ break;
case BT_FILE:
case BT_BASE_FILE:
{
return 0;
_cpp_do__Pragma (pfile);
- if (pfile->directive_result.type == CPP_PRAGMA)
- {
- cpp_token *tok = _cpp_temp_token (pfile);
- *tok = pfile->directive_result;
- push_token_context (pfile, NULL, tok, 1);
- }
-
return 1;
}
/* Set pfile->cur_token as required by _cpp_lex_direct. */
pfile->cur_token = _cpp_temp_token (pfile);
- push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
+ _cpp_push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
if (pfile->buffer->cur != pfile->buffer->rlimit)
cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro \"%s\"",
NODE_NAME (node));
static bool
paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
{
- unsigned char *buf, *end;
+ unsigned char *buf, *end, *lhsend;
const cpp_token *lhs;
unsigned int len;
- bool valid;
lhs = *plhs;
len = cpp_token_len (lhs) + cpp_token_len (rhs) + 1;
buf = (unsigned char *) alloca (len);
- end = cpp_spell_token (pfile, lhs, buf, false);
+ end = lhsend = cpp_spell_token (pfile, lhs, buf, false);
/* Avoid comment headers, since they are still processed in stage 3.
It is simpler to insert a space here, rather than modifying the
/* Set pfile->cur_token as required by _cpp_lex_direct. */
pfile->cur_token = _cpp_temp_token (pfile);
*plhs = _cpp_lex_direct (pfile);
- valid = pfile->buffer->cur == pfile->buffer->rlimit;
- _cpp_pop_buffer (pfile);
+ if (pfile->buffer->cur != pfile->buffer->rlimit)
+ {
+ _cpp_pop_buffer (pfile);
+ _cpp_backup_tokens (pfile, 1);
+ *lhsend = '\0';
- return valid;
+ /* Mandatory error for all apart from assembler. */
+ if (CPP_OPTION (pfile, lang) != CLK_ASM)
+ cpp_error (pfile, CPP_DL_ERROR,
+ "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
+ buf, cpp_token_as_text (pfile, rhs));
+ return false;
+ }
+
+ _cpp_pop_buffer (pfile);
+ return true;
}
/* Handles an arbitrarily long sequence of ## operators, with initial
abort ();
if (!paste_tokens (pfile, &lhs, rhs))
- {
- _cpp_backup_tokens (pfile, 1);
-
- /* Mandatory error for all apart from assembler. */
- if (CPP_OPTION (pfile, lang) != CLK_ASM)
- cpp_error (pfile, CPP_DL_ERROR,
- "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
- cpp_token_as_text (pfile, lhs),
- cpp_token_as_text (pfile, rhs));
- break;
- }
+ break;
}
while (rhs->flags & PASTE_LEFT);
/* Put the resulting token in its own context. */
- push_token_context (pfile, NULL, lhs, 1);
+ _cpp_push_token_context (pfile, NULL, lhs, 1);
}
/* Returns TRUE if the number of arguments ARGC supplied in an
too difficult. We re-insert it in its own context. */
_cpp_backup_tokens (pfile, 1);
if (padding)
- push_token_context (pfile, NULL, padding, 1);
+ _cpp_push_token_context (pfile, NULL, padding, 1);
}
return NULL;
macro->used = 1;
if (macro->paramc == 0)
- push_token_context (pfile, node, macro->exp.tokens, macro->count);
+ _cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count);
return 1;
}
}
/* Push a list of tokens. */
-static void
-push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
+void
+_cpp_push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
const cpp_token *first, unsigned int count)
{
cpp_context *context = next_context (pfile);
pfile->state.prevent_expansion--;
}
-/* Step back one (or more) tokens. Can only step mack more than 1 if
+/* Step back one (or more) tokens. Can only step back more than 1 if
they are from the lexer, and not from macro expansion. */
void
_cpp_backup_tokens (cpp_reader *pfile, unsigned int count)
/* Dependency generator for Makefile fragments.
- Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2003, 2007 Free Software Foundation, Inc.
Contributed by Zack Weinberg, Mar 2000
This program is free software; you can redistribute it and/or modify it
/* Remove leading ./ in any case. */
while (t[0] == '.' && IS_DIR_SEPARATOR (t[1]))
- t += 2;
+ {
+ t += 2;
+ /* If we removed a leading ./, then also remove any /s after the
+ first. */
+ while (IS_DIR_SEPARATOR (t[0]))
+ ++t;
+ }
return t;
}
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-
-/* Prototype these in case the system headers don't provide them. */
-extern char *getpwd ();
-extern char *getwd ();
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
#include "libiberty.h"
the few exceptions to the general rule here. */
#if !defined(HAVE_GETCWD) && defined(HAVE_GETWD)
+/* Prototype in case the system headers doesn't provide it. */
+extern char *getwd ();
#define getcwd(buf,len) getwd(buf)
#endif
yield 0 and set errno. */
char *
-getpwd ()
+getpwd (void)
{
static char *pwd;
static int failure_errno;
&& dotstat.st_dev == pwdstat.st_dev))
/* The shortcut didn't work. Try the slow, ``sure'' way. */
- for (s = GUESSPATHLEN; ! getcwd (p = xmalloc (s), s); s *= 2)
+ for (s = GUESSPATHLEN; !getcwd (p = XNEWVEC (char, s), s); s *= 2)
{
int e = errno;
free (p);
#endif
char *
-getpwd ()
+getpwd (void)
{
static char *pwd = 0;
if (!pwd)
- pwd = getcwd (xmalloc (MAXPATHLEN + 1), MAXPATHLEN + 1
+ pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1
#ifdef VMS
, 0
#endif
if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
(*htab->del_f) (entries[i]);
- memset (entries, 0, size * sizeof (PTR));
+ /* Instead of clearing megabyte, downsize the table. */
+ if (size > 1024*1024 / sizeof (PTR))
+ {
+ int nindex = higher_prime_index (1024 / sizeof (PTR));
+ int nsize = prime_tab[nindex].prime;
+
+ if (htab->free_f != NULL)
+ (*htab->free_f) (htab->entries);
+ else if (htab->free_with_arg_f != NULL)
+ (*htab->free_with_arg_f) (htab->alloc_arg, htab->entries);
+ if (htab->alloc_with_arg_f != NULL)
+ htab->entries = (PTR *) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
+ sizeof (PTR *));
+ else
+ htab->entries = (PTR *) (*htab->alloc_f) (nsize, sizeof (PTR *));
+ htab->size = nsize;
+ htab->size_prime_index = nindex;
+ }
+ else
+ memset (entries, 0, size * sizeof (PTR));
+ htab->n_deleted = 0;
+ htab->n_elements = 0;
}
/* Similar to htab_find_slot, but without several unwanted side effects:
print "#include " quote "opts.h" quote
print "#include " quote "intl.h" quote
print ""
+print "#ifdef GCC_DRIVER"
+print "int target_flags;"
+print "#endif /* GCC_DRIVER */"
+print ""
for (i = 0; i < n_opts; i++) {
name = var_name(flags[i]);
if (name == "")
continue;
- if (flag_set_p("VarExists", flags[i]))
- continue;
-
- init = opt_args("Init", flags[i])
- if (init != "")
- init = " = " init;
- else if (name in var_seen)
- continue;
+ if (flag_set_p("VarExists", flags[i])) {
+ # Need it for the gcc driver.
+ if (name in var_seen)
+ continue;
+ init = ""
+ gcc_driver = 1
+ }
+ else {
+ init = opt_args("Init", flags[i])
+ if (init != "")
+ init = " = " init;
+ else if (name in var_seen)
+ continue;
+ gcc_driver = 0
+ }
+ if (gcc_driver == 1)
+ print "#ifdef GCC_DRIVER"
print "/* Set by -" opts[i] "."
print " " help[i] " */"
print var_type(flags[i]) name init ";"
+ if (gcc_driver == 1)
+ print "#endif /* GCC_DRIVER */"
print ""
var_seen[name] = 1;
print "const struct cl_option cl_options[] =\n{"
-for (i = 0; i < n_opts; i++)
+j = 0
+for (i = 0; i < n_opts; i++) {
back_chain[i] = "N_OPTS";
+ indices[opts[i]] = j;
+ # Combine the flags of identical switches. Switches
+ # appear many times if they are handled by many front
+ # ends, for example.
+ while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+ flags[i + 1] = flags[i] " " flags[i + 1];
+ i++;
+ back_chain[i] = "N_OPTS";
+ indices[opts[i]] = j;
+ }
+ j++;
+}
for (i = 0; i < n_opts; i++) {
# Combine the flags of identical switches. Switches
else
hlp = quote help[i] quote;
- printf(" { %c-%s%c,\n %s,\n %s, %u,\n",
- quote, opts[i], quote, hlp, back_chain[i], len)
+ neg = opt_args("Negative", flags[i]);
+ if (neg != "")
+ idx = indices[neg]
+ else {
+ if (flag_set_p("RejectNegative", flags[i]))
+ idx = -1;
+ else {
+ if (opts[i] ~ "^[Wfm]")
+ idx = indices[opts[i]];
+ else
+ idx = -1;
+ }
+ }
+ printf(" { %c-%s%c,\n %s,\n %s, %u, %d,\n",
+ quote, opts[i], quote, hlp, back_chain[i], len, idx)
condition = opt_args("Condition", flags[i])
cl_flags = switch_flags(flags[i])
if (condition != "")
-# Copyright (C) 2003,2004 Free Software Foundation, Inc.
+# Copyright (C) 2003,2004,2005,2006 Free Software Foundation, Inc.
# Contributed by Kelley Cook, June 2004.
# Original code from Neil Booth, May 2003.
#
for (i = 0; i < n_opts; i++) {
opt = opt_args("InverseMask", flags[i])
- if (opt ~ ",")
- print "#define TARGET_" nth_arg(1, opt) \
- " ((target_flags & MASK_" nth_arg(0, opt) ") == 0)"
+ if (opt ~ ",") {
+ vname = var_name(flags[i])
+ macro = "OPTION_"
+ mask = "OPTION_MASK_"
+ if (vname == "") {
+ vname = "target_flags"
+ macro = "TARGET_"
+ mask = "MASK_"
+ }
+ print "#define " macro nth_arg(1, opt) \
+ " ((" vname " & " mask nth_arg(0, opt) ") == 0)"
+ }
}
print ""
--- /dev/null
+/* Command line option handling.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "intl.h"
+#include "opts.h"
+
+/* Perform a binary search to find which option the command-line INPUT
+ matches. Returns its index in the option array, and N_OPTS
+ (cl_options_count) on failure.
+
+ This routine is quite subtle. A normal binary search is not good
+ enough because some options can be suffixed with an argument, and
+ multiple sub-matches can occur, e.g. input of "-pedantic" matching
+ the initial substring of "-pedantic-errors".
+
+ A more complicated example is -gstabs. It should match "-g" with
+ an argument of "stabs". Suppose, however, that the number and list
+ of switches are such that the binary search tests "-gen-decls"
+ before having tested "-g". This doesn't match, and as "-gen-decls"
+ is less than "-gstabs", it will become the lower bound of the
+ binary search range, and "-g" will never be seen. To resolve this
+ issue, opts.sh makes "-gen-decls" point, via the back_chain member,
+ to "-g" so that failed searches that end between "-gen-decls" and
+ the lexicographically subsequent switch know to go back and see if
+ "-g" causes a match (which it does in this example).
+
+ This search is done in such a way that the longest match for the
+ front end in question wins. If there is no match for the current
+ front end, the longest match for a different front end is returned
+ (or N_OPTS if none) and the caller emits an error message. */
+size_t
+find_opt (const char *input, int lang_mask)
+{
+ size_t mn, mx, md, opt_len;
+ size_t match_wrong_lang;
+ int comp;
+
+ mn = 0;
+ mx = cl_options_count;
+
+ /* Find mn such this lexicographical inequality holds:
+ cl_options[mn] <= input < cl_options[mn + 1]. */
+ while (mx - mn > 1)
+ {
+ md = (mn + mx) / 2;
+ opt_len = cl_options[md].opt_len;
+ comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
+
+ if (comp < 0)
+ mx = md;
+ else
+ mn = md;
+ }
+
+ /* This is the switch that is the best match but for a different
+ front end, or cl_options_count if there is no match at all. */
+ match_wrong_lang = cl_options_count;
+
+ /* Backtrace the chain of possible matches, returning the longest
+ one, if any, that fits best. With current GCC switches, this
+ loop executes at most twice. */
+ do
+ {
+ const struct cl_option *opt = &cl_options[mn];
+
+ /* Is the input either an exact match or a prefix that takes a
+ joined argument? */
+ if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
+ && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
+ {
+ /* If language is OK, return it. */
+ if (opt->flags & lang_mask)
+ return mn;
+
+ /* If we haven't remembered a prior match, remember this
+ one. Any prior match is necessarily better. */
+ if (match_wrong_lang == cl_options_count)
+ match_wrong_lang = mn;
+ }
+
+ /* Try the next possibility. This is cl_options_count if there
+ are no more. */
+ mn = opt->back_chain;
+ }
+ while (mn != cl_options_count);
+
+ /* Return the best wrong match, or cl_options_count if none. */
+ return match_wrong_lang;
+}
+
+/* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the
+ next one is the same as ORIG_NEXT_OPT_IDX. */
+
+static bool
+cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx)
+{
+ /* An option can be canceled by the same option or an option with
+ Negative. */
+ if (cl_options [next_opt_idx].neg_index == opt_idx)
+ return true;
+
+ if (cl_options [next_opt_idx].neg_index != orig_next_opt_idx)
+ return cancel_option (opt_idx, cl_options [next_opt_idx].neg_index,
+ orig_next_opt_idx);
+
+ return false;
+}
+
+/* Filter out options canceled by the ones after them. */
+
+void
+prune_options (int *argcp, char ***argvp)
+{
+ int argc = *argcp;
+ int *options = xmalloc (argc * sizeof (*options));
+ char **argv = xmalloc (argc * sizeof (char *));
+ int i, arg_count, need_prune = 0;
+ const struct cl_option *option;
+ size_t opt_index;
+
+ /* Scan all arguments. */
+ for (i = 1; i < argc; i++)
+ {
+ int value = 1;
+ const char *opt = (*argvp) [i];
+
+ opt_index = find_opt (opt + 1, -1);
+ if (opt_index == cl_options_count
+ && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm')
+ && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-')
+ {
+ char *dup;
+
+ /* Drop the "no-" from negative switches. */
+ size_t len = strlen (opt) - 3;
+
+ dup = XNEWVEC (char, len + 1);
+ dup[0] = '-';
+ dup[1] = opt[1];
+ memcpy (dup + 2, opt + 5, len - 2 + 1);
+ opt = dup;
+ value = 0;
+ opt_index = find_opt (opt + 1, -1);
+ free (dup);
+ }
+
+ if (opt_index == cl_options_count)
+ {
+cont:
+ options [i] = 0;
+ continue;
+ }
+
+ option = &cl_options[opt_index];
+ if (option->neg_index < 0)
+ goto cont;
+
+ /* Skip joined switches. */
+ if ((option->flags & CL_JOINED))
+ goto cont;
+
+ /* Reject negative form of switches that don't take negatives as
+ unrecognized. */
+ if (!value && (option->flags & CL_REJECT_NEGATIVE))
+ goto cont;
+
+ options [i] = (int) opt_index;
+ need_prune |= options [i];
+ }
+
+ if (!need_prune)
+ goto done;
+
+ /* Remove arguments which are negated by others after them. */
+ argv [0] = (*argvp) [0];
+ arg_count = 1;
+ for (i = 1; i < argc; i++)
+ {
+ int j, opt_idx;
+
+ opt_idx = options [i];
+ if (opt_idx)
+ {
+ int next_opt_idx;
+ for (j = i + 1; j < argc; j++)
+ {
+ next_opt_idx = options [j];
+ if (next_opt_idx
+ && cancel_option (opt_idx, next_opt_idx,
+ next_opt_idx))
+ break;
+ }
+ }
+ else
+ goto keep;
+
+ if (j == argc)
+ {
+keep:
+ argv [arg_count] = (*argvp) [i];
+ arg_count++;
+ }
+ }
+
+ if (arg_count != argc)
+ {
+ *argcp = arg_count;
+ *argvp = argv;
+ }
+ else
+ {
+done:
+ free (argv);
+ }
+
+ free (options);
+}
/* Command line option handling.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Neil Booth.
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
const char **in_fnames;
unsigned num_in_fnames;
-static size_t find_opt (const char *, int);
static int common_handle_option (size_t scode, const char *arg, int value);
static unsigned int handle_option (const char **argv, unsigned int lang_mask);
static char *write_langs (unsigned int lang_mask);
static void handle_options (unsigned int, const char **, unsigned int);
static void wrap_help (const char *help, const char *item, unsigned int);
static void print_help (void);
-static void print_filtered_help (unsigned int flag);
+static void print_filtered_help (unsigned int);
static unsigned int print_switch (const char *text, unsigned int indent);
-/* Perform a binary search to find which option the command-line INPUT
- matches. Returns its index in the option array, and N_OPTS
- (cl_options_count) on failure.
-
- This routine is quite subtle. A normal binary search is not good
- enough because some options can be suffixed with an argument, and
- multiple sub-matches can occur, e.g. input of "-pedantic" matching
- the initial substring of "-pedantic-errors".
-
- A more complicated example is -gstabs. It should match "-g" with
- an argument of "stabs". Suppose, however, that the number and list
- of switches are such that the binary search tests "-gen-decls"
- before having tested "-g". This doesn't match, and as "-gen-decls"
- is less than "-gstabs", it will become the lower bound of the
- binary search range, and "-g" will never be seen. To resolve this
- issue, opts.sh makes "-gen-decls" point, via the back_chain member,
- to "-g" so that failed searches that end between "-gen-decls" and
- the lexicographically subsequent switch know to go back and see if
- "-g" causes a match (which it does in this example).
-
- This search is done in such a way that the longest match for the
- front end in question wins. If there is no match for the current
- front end, the longest match for a different front end is returned
- (or N_OPTS if none) and the caller emits an error message. */
-static size_t
-find_opt (const char *input, int lang_mask)
-{
- size_t mn, mx, md, opt_len;
- size_t match_wrong_lang;
- int comp;
-
- mn = 0;
- mx = cl_options_count;
-
- /* Find mn such this lexicographical inequality holds:
- cl_options[mn] <= input < cl_options[mn + 1]. */
- while (mx - mn > 1)
- {
- md = (mn + mx) / 2;
- opt_len = cl_options[md].opt_len;
- comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
-
- if (comp < 0)
- mx = md;
- else
- mn = md;
- }
-
- /* This is the switch that is the best match but for a different
- front end, or cl_options_count if there is no match at all. */
- match_wrong_lang = cl_options_count;
-
- /* Backtrace the chain of possible matches, returning the longest
- one, if any, that fits best. With current GCC switches, this
- loop executes at most twice. */
- do
- {
- const struct cl_option *opt = &cl_options[mn];
-
- /* Is the input either an exact match or a prefix that takes a
- joined argument? */
- if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
- && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
- {
- /* If language is OK, return it. */
- if (opt->flags & lang_mask)
-
-
- /* If we haven't remembered a prior match, remember this
- one. Any prior match is necessarily better. */
- if (match_wrong_lang == cl_options_count)
- match_wrong_lang = mn;
- }
-
- /* Try the next possibility. This is cl_options_count if there
- are no more. */
- mn = opt->back_chain;
- }
- while (mn != cl_options_count);
-
- /* Return the best wrong match, or cl_options_count if none. */
- return match_wrong_lang;
-}
-
/* If ARG is a non-negative integer made up solely of digits, return its
value, otherwise return -1. */
static int
if (mask & (1U << n))
len += strlen (lang_name) + 1;
- result = xmalloc (len);
+ result = XNEWVEC (char, len);
len = 0;
for (n = 0; (lang_name = lang_names[n]) != 0; n++)
if (mask & (1U << n))
/* Drop the "no-" from negative switches. */
size_t len = strlen (opt) - 3;
- dup = xmalloc (len + 1);
+ dup = XNEWVEC (char, len + 1);
dup[0] = '-';
dup[1] = opt[1];
memcpy (dup + 2, opt + 5, len - 2 + 1);
}
if (option->flags & lang_mask)
- if ((*lang_hooks.handle_option) (opt_index, arg, value) == 0)
+ if (lang_hooks.handle_option (opt_index, arg, value) == 0)
result = 0;
if (result && (option->flags & CL_COMMON))
}
/* Handle FILENAME from the command line. */
-void
+static void
add_input_filename (const char *filename)
{
num_in_fnames++;
const char *help;
unsigned short back_chain;
unsigned char opt_len;
+ int neg_index;
unsigned int flags;
void *flag_var;
enum cl_var_type var_type;
extern const struct cl_option cl_options[];
extern const unsigned int cl_options_count;
extern const char *const lang_names[];
+extern bool no_unit_at_a_time_default;
#define CL_DISABLED (1 << 21) /* Disabled in this configuration. */
#define CL_TARGET (1 << 22) /* Target-specific option. */
extern unsigned num_in_fnames;
+size_t find_opt (const char *input, int lang_mask);
+extern void prune_options (int *argcp, char ***argvp);
extern void decode_options (unsigned int argc, const char **argv);
extern int option_enabled (int opt_idx);
extern bool get_option_state (int, struct cl_option_state *);
#ifndef GCC_OUTPUT_H
#define GCC_OUTPUT_H
-/* Compute branch alignments based on frequency information in the CFG. */
-extern void compute_alignments (void);
-
/* Initialize data in final at the beginning of a compilation. */
extern void init_final (const char *);
/* Functions in varasm.c. */
-/* Tell assembler to switch to text section. */
-extern void text_section (void);
-
-/* Tell assembler to switch to unlikely-to-be-executed text section. */
-extern void unlikely_text_section (void);
-
-/* Tell assembler to switch to data section. */
-extern void data_section (void);
-
-/* Tell assembler to switch to read-only data section. This is normally
- the text section. */
-extern void readonly_data_section (void);
-
-/* Determine if we're in the text section. */
-extern int in_text_section (void);
-
-/* Determine if we're in the unlikely-to-be-executed text section. */
-extern int in_unlikely_text_section (void);
-
-#ifdef CTORS_SECTION_ASM_OP
-extern void ctors_section (void);
-#endif
-
-#ifdef DTORS_SECTION_ASM_OP
-extern void dtors_section (void);
-#endif
-
-#ifdef BSS_SECTION_ASM_OP
-extern void bss_section (void);
-#endif
-
-#ifdef INIT_SECTION_ASM_OP
-extern void init_section (void);
-#endif
-
-#ifdef FINI_SECTION_ASM_OP
-extern void fini_section (void);
-#endif
-
-#ifdef EXPORTS_SECTION_ASM_OP
-extern void exports_section (void);
-#endif
-
-#ifdef DRECTVE_SECTION_ASM_OP
-extern void drectve_section (void);
-#endif
-
-#ifdef SDATA_SECTION_ASM_OP
-extern void sdata_section (void);
-#endif
-
-/* Tell assembler to change to section NAME for DECL.
- If DECL is NULL, just switch to section NAME.
- If NAME is NULL, get the name from DECL.
- If RELOC is 1, the initializer for DECL contains relocs. */
-extern void named_section (tree, const char *, int);
-
-/* Tell assembler to switch to the section for function DECL. */
-extern void function_section (tree);
-
-/* Tell assembler to switch to the most recently used text section. */
-extern void current_function_section (tree);
-
-/* Tell assembler to switch to the section for string merging. */
-extern void mergeable_string_section (tree, unsigned HOST_WIDE_INT,
- unsigned int);
-
-/* Tell assembler to switch to the section for constant merging. */
-extern void mergeable_constant_section (enum machine_mode,
- unsigned HOST_WIDE_INT, unsigned int);
-
/* Declare DECL to be a weak symbol. */
extern void declare_weak (tree);
/* Merge weak status. */
Prefixes such as % are optional. */
extern int decode_reg_name (const char *);
-/* Make the rtl for variable VAR be volatile.
- Use this only for static variables. */
-extern void make_var_volatile (tree);
-
extern void assemble_alias (tree, tree);
extern void default_assemble_visibility (tree, int);
initial value (that will be done by the caller). */
extern void assemble_variable (tree, int, int, int);
+/* Compute the alignment of variable specified by DECL.
+ DONT_OUTPUT_DATA is from assemble_variable. */
+extern void align_variable (tree decl, bool dont_output_data);
+
/* Output something to declare an external symbol to the assembler.
(Most assemblers don't need this, so we normally output nothing.)
Do nothing if DECL is not external. */
extern rtx peephole (rtx);
#endif
-/* Write all the constants in the constant pool. */
-extern void output_constant_pool (const char *, tree);
+extern void output_shared_constant_pool (void);
+
+extern void output_object_blocks (void);
+
+/* Whether a constructor CTOR is a valid static constant initializer if all
+ its elements are. This used to be internal to initializer_constant_valid_p
+ and has been exposed to let other functions like categorize_ctor_elements
+ evaluate the property while walking a constructor for other purposes. */
+
+extern bool constructor_static_from_elts_p (tree);
/* Return nonzero if VALUE is a valid constant-valued expression
for use in initializing a static variable; one that can be an
extern int size_directive_output;
extern tree last_assemble_variable_decl;
-enum in_section { no_section, in_text, in_unlikely_executed_text, in_data,
- in_named
-#ifdef BSS_SECTION_ASM_OP
- , in_bss
-#endif
-#ifdef CTORS_SECTION_ASM_OP
- , in_ctors
-#endif
-#ifdef DTORS_SECTION_ASM_OP
- , in_dtors
-#endif
-#ifdef READONLY_DATA_SECTION_ASM_OP
- , in_readonly_data
-#endif
-#ifdef EXTRA_SECTIONS
- , EXTRA_SECTIONS
-#endif
-};
-
-extern const char *last_text_section_name;
-extern enum in_section last_text_section;
extern bool first_function_block_is_cold;
/* Decide whether DECL needs to be in a writable section.
RELOC is the same as for SELECT_SECTION. */
extern bool decl_readonly_section (tree, int);
-extern bool decl_readonly_section_1 (tree, int, int);
/* This can be used to compute RELOC for the function above, when
given a constant expression. */
/* Default target function prologue and epilogue assembler output. */
extern void default_function_pro_epilogue (FILE *, HOST_WIDE_INT);
-/* Tell assembler to switch to the section for the exception table. */
-extern void default_exception_section (void);
-
-/* Tell assembler to switch to the section for the EH frames. */
-extern void named_section_eh_frame_section (void);
-extern void collect2_eh_frame_section (void);
-extern void default_eh_frame_section (void);
-
/* Default target hook that outputs nothing to a stream. */
extern void no_asm_to_stream (FILE *);
#define SECTION_OVERRIDE 0x20000 /* allow override of default flags */
#define SECTION_TLS 0x40000 /* contains thread-local storage */
#define SECTION_NOTYPE 0x80000 /* don't output @progbits */
-#define SECTION_MACH_DEP 0x100000 /* subsequent bits reserved for target */
+#define SECTION_DECLARED 0x100000 /* section has been used */
+#define SECTION_STYLE_MASK 0x600000 /* bits used for SECTION_STYLE */
+#define SECTION_COMMON 0x800000 /* contains common data */
+#define SECTION_MACH_DEP 0x1000000 /* subsequent bits reserved for target */
+
+/* This SECTION_STYLE is used for unnamed sections that we can switch
+ to using a special assembler directive. */
+#define SECTION_UNNAMED 0x000000
+
+/* This SECTION_STYLE is used for named sections that we can switch
+ to using a general section directive. */
+#define SECTION_NAMED 0x200000
+
+/* This SECTION_STYLE is used for sections that we cannot switch to at
+ all. The choice of section is implied by the directive that we use
+ to declare the object. */
+#define SECTION_NOSWITCH 0x400000
/* A helper function for default_elf_select_section and
default_elf_unique_section. Categorizes the DECL. */
SECCAT_TBSS
};
+/* Information that is provided by all instances of the section type. */
+struct section_common GTY(()) {
+ /* The set of SECTION_* flags that apply to this section. */
+ unsigned int flags;
+};
+
+/* Information about a SECTION_NAMED section. */
+struct named_section GTY(()) {
+ struct section_common common;
+
+ /* The name of the section. */
+ const char *name;
+
+ /* If nonnull, the VAR_DECL or FUNCTION_DECL with which the
+ section is associated. */
+ tree decl;
+};
+
+/* A callback that writes the assembly code for switching to an unnamed
+ section. The argument provides callback-specific data. */
+typedef void (*unnamed_section_callback) (const void *);
+
+/* Information about a SECTION_UNNAMED section. */
+struct unnamed_section GTY(()) {
+ struct section_common common;
+
+ /* The callback used to switch to the section, and the data that
+ should be passed to the callback. */
+ unnamed_section_callback GTY ((skip)) callback;
+ const void *GTY ((skip)) data;
+
+ /* The next entry in the chain of unnamed sections. */
+ section *next;
+};
+
+/* A callback that writes the assembly code for a decl in a
+ SECTION_NOSWITCH section. DECL is the decl that should be assembled
+ and NAME is the name of its SYMBOL_REF. SIZE is the size of the decl
+ in bytes and ROUNDED is that size rounded up to the next
+ BIGGEST_ALIGNMENT / BITS_PER_UNIT boundary.
+
+ Return true if the callback used DECL_ALIGN to set the object's
+ alignment. A false return value implies that we are relying
+ on the rounded size to align the decl. */
+typedef bool (*noswitch_section_callback) (tree decl, const char *name,
+ unsigned HOST_WIDE_INT size,
+ unsigned HOST_WIDE_INT rounded);
+
+/* Information about a SECTION_NOSWITCH section. */
+struct noswitch_section GTY(()) {
+ struct section_common common;
+
+ /* The callback used to assemble decls in this section. */
+ noswitch_section_callback GTY ((skip)) callback;
+};
+
+/* Information about a section, which may be named or unnamed. */
+union section GTY ((desc ("SECTION_STYLE (&(%h))")))
+{
+ struct section_common GTY ((skip)) common;
+ struct named_section GTY ((tag ("SECTION_NAMED"))) named;
+ struct unnamed_section GTY ((tag ("SECTION_UNNAMED"))) unnamed;
+ struct noswitch_section GTY ((tag ("SECTION_NOSWITCH"))) noswitch;
+};
+
+/* Return the style of section SECT. */
+#define SECTION_STYLE(SECT) ((SECT)->common.flags & SECTION_STYLE_MASK)
+
+struct object_block;
+
+/* Special well-known sections. */
+extern GTY(()) section *text_section;
+extern GTY(()) section *data_section;
+extern GTY(()) section *readonly_data_section;
+extern GTY(()) section *sdata_section;
+extern GTY(()) section *ctors_section;
+extern GTY(()) section *dtors_section;
+extern GTY(()) section *bss_section;
+extern GTY(()) section *sbss_section;
+extern GTY(()) section *exception_section;
+extern GTY(()) section *eh_frame_section;
+extern GTY(()) section *tls_comm_section;
+extern GTY(()) section *comm_section;
+extern GTY(()) section *lcomm_section;
+extern GTY(()) section *bss_noswitch_section;
+
+extern GTY(()) section *in_section;
+extern GTY(()) bool in_cold_section_p;
+
+extern section *get_unnamed_section (unsigned int, void (*) (const void *),
+ const void *);
+extern section *get_section (const char *, unsigned int, tree);
+extern section *get_named_section (tree, const char *, int);
+extern void place_block_symbol (rtx);
+extern rtx get_section_anchor (struct object_block *, HOST_WIDE_INT,
+ enum tls_model);
+extern section *mergeable_constant_section (enum machine_mode,
+ unsigned HOST_WIDE_INT,
+ unsigned int);
+extern section *function_section (tree);
+extern section *unlikely_text_section (void);
+extern section *current_function_section (void);
+
+extern bool unlikely_text_section_p (section *);
+extern void switch_to_section (section *);
+extern void output_section_asm_op (const void *);
-extern bool set_named_section_flags (const char *, unsigned int);
-#define named_section_flags(NAME, FLAGS) \
- named_section_real((NAME), (FLAGS), /*decl=*/NULL_TREE)
-extern void named_section_real (const char *, unsigned int, tree);
-extern bool named_section_first_declaration (const char *);
extern unsigned int default_section_type_flags (tree, const char *, int);
-extern unsigned int default_section_type_flags_1 (tree, const char *, int, int);
+extern bool have_global_bss_p (void);
extern void default_no_named_section (const char *, unsigned int, tree);
extern void default_elf_asm_named_section (const char *, unsigned int, tree);
-extern enum section_category categorize_decl_for_section (tree, int, int);
+extern enum section_category categorize_decl_for_section (tree, int);
extern void default_coff_asm_named_section (const char *, unsigned int, tree);
extern void default_pe_asm_named_section (const char *, unsigned int, tree);
extern void default_named_section_asm_out_constructor (rtx, int);
extern void default_ctor_section_asm_out_constructor (rtx, int);
-extern void default_select_section (tree, int, unsigned HOST_WIDE_INT);
-extern void default_elf_select_section (tree, int, unsigned HOST_WIDE_INT);
-extern void default_elf_select_section_1 (tree, int,
- unsigned HOST_WIDE_INT, int);
+extern section *default_select_section (tree, int, unsigned HOST_WIDE_INT);
+extern section *default_elf_select_section (tree, int, unsigned HOST_WIDE_INT);
extern void default_unique_section (tree, int);
-extern void default_unique_section_1 (tree, int, int);
-extern void default_function_rodata_section (tree);
-extern void default_no_function_rodata_section (tree);
-extern void default_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT);
-extern void default_elf_select_rtx_section (enum machine_mode, rtx,
+extern section *default_function_rodata_section (tree);
+extern section *default_no_function_rodata_section (tree);
+extern section *default_select_rtx_section (enum machine_mode, rtx,
unsigned HOST_WIDE_INT);
+extern section *default_elf_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
extern void default_encode_section_info (tree, rtx, int);
extern const char *default_strip_name_encoding (const char *);
+extern void default_asm_output_anchor (rtx);
+extern bool default_use_anchors_for_symbol_p (rtx);
extern bool default_binds_local_p (tree);
extern bool default_binds_local_p_1 (tree, int);
extern void default_globalize_label (FILE *, const char *);
extern void default_emit_unwind_label (FILE *, tree, int, int);
+extern void default_emit_except_table_label (FILE *);
extern void default_internal_label (FILE *, const char *, unsigned long);
extern void default_file_start (void);
extern void file_end_indicate_exec_stack (void);
static char *
save_string (const char *s, int len)
{
- char *result = xmalloc (len + 1);
+ char *result = XNEWVEC (char, len + 1);
memcpy (result, s, len);
result[len] = 0;
keylen++)
;
- key = alloca (keylen + 1);
+ key = (char *) alloca (keylen + 1);
strncpy (key, &name[1], keylen);
key[keylen] = 0;
/* The prefix given by -iprefix, if any. */
static const char *iprefix;
+/* The multilib directory given by -imultilib, if any. */
+static const char *imultilib;
+
/* The system root, if any. Overridden by -isysroot. */
static const char *sysroot = TARGET_SYSTEM_ROOT;
iprefix = arg;
break;
+ case OPT_imultilib:
+ imultilib = arg;
+ break;
+
case OPT_iquote:
add_path (xstrdup (arg), QUOTE, 0, true);
break;
sanitize_cpp_opts ();
- register_include_chains (parse_in, sysroot, iprefix,
+ register_include_chains (parse_in, sysroot, iprefix, imultilib,
std_inc, 0, verbose);
/* Open the output now. We must do so even if flag_no_output is
# End Source File\r
# Begin Source File\r
\r
+SOURCE=".\opts-common.c"\r
+# End Source File\r
+# Begin Source File\r
+\r
SOURCE=.\opts.c\r
# End Source File\r
# Begin Source File\r
# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
# Begin Source File\r
\r
+SOURCE=.\libiberty\filenames.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\libiberty\hashtab.h\r
+# End Source File\r
+# Begin Source File\r
+\r
SOURCE=.\libiberty\obstack.h\r
# End Source File\r
# End Group\r
# End Source File\r
# Begin Source File\r
\r
+SOURCE=.\md5.h\r
+# End Source File\r
+# Begin Source File\r
+\r
SOURCE=.\options.h\r
# End Source File\r
# Begin Source File\r
SDCPP Joined Separate
-imacros <file> Accept definition of macros in <file>
+imultilib
+C ObjC C++ ObjC++ Joined Separate
+-imultilib <dir> Set <dir> to be the multilib include subdirectory
+
include
SDCPP Joined Separate
-include <file> Include the contents of <file> before other files
# endif
#endif
+#define ICE_EXIT_CODE 4
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
# define FALSE false
#endif /* !__cplusplus */
+/////* Get definition of double_int. */
+////#include "double-int.h"
/* Some compilers do not allow the use of unsigned char in bitfields. */
#define BOOL_BITFIELD unsigned int
TARGET_ESC TARGET_FF TARGET_NEWLINE TARGET_TAB TARGET_VT \
LINK_LIBGCC_SPECIAL DONT_ACCESS_GBLS_AFTER_EPILOGUE \
TARGET_OPTIONS TARGET_SWITCHES EXTRA_CC_MODES FINALIZE_PIC \
- PREDICATE_CODES SPECIAL_MODE_PREDICATES HOST_PTR_PRINTF
+ PREDICATE_CODES SPECIAL_MODE_PREDICATES HOST_PTR_PRINTF \
+ EXTRA_SECTIONS EXTRA_SECTION_FUNCTIONS READONLY_DATA_SECTION \
+ TARGET_ASM_EXCEPTION_SECTION TARGET_ASM_EH_FRAME_SECTION \
+ SMALL_ARG_MAX ASM_OUTPUT_SHARED_BSS ASM_OUTPUT_SHARED_COMMON \
+ ASM_OUTPUT_SHARED_LOCAL UNALIGNED_WORD_ASM_OP
/* Hooks that are no longer used. */
#pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \
#include "version.h"
-/* This is the string reported as the version number by all components
- of the compiler. If you distribute a modified version of GCC,
- please modify this string to indicate that, e.g. by putting your
- organization's name in parentheses at the end of the string. */
+/* This is the trailing component of the string reported as the
+ version number by all components of the compiler. For an official
+ FSF release, it is empty. If you distribute a modified version of
+ GCC, please change this string to indicate that. The suggested
+ format is a leading space, followed by your organization's name
+ in parentheses. You may also wish to include a number indicating
+ the revision of your modified compiler. */
-const char version_string[] = "4.1.2 + SDCC";
+#define BASEVER "4.2.0"
+#define DATESTAMP
+#define DEVPHASE
+#define VERSUFFIX " + SDCC"
/* This is the location of the online document giving instructions for
reporting bugs. If you distribute a modified version of GCC,
not bugs in your modifications.) */
const char bug_report_url[] = "<URL:http://sdcc.sourceforge.net>";
+
+/* The complete version string, assembled from several pieces.
+ BASEVER, DATESTAMP, and DEVPHASE are defined by the Makefile. */
+
+const char version_string[] = BASEVER DATESTAMP DEVPHASE VERSUFFIX;