static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *);
static unsigned int read_flag (cpp_reader *, unsigned int);
static bool strtolinenum (const uchar *, size_t, linenum_type *, bool *);
-static void do_diagnostic (cpp_reader *, int, int);
+static void do_diagnostic (cpp_reader *, int, int, int);
static cpp_hashnode *lex_macro_node (cpp_reader *, bool);
static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
static void do_include_common (cpp_reader *, enum include_type);
static cpp_hashnode *parse_assertion (cpp_reader *, struct answer **, int);
static struct answer ** find_answer (cpp_hashnode *, const struct answer *);
static void handle_assertion (cpp_reader *, const char *, int);
+static void do_pragma_push_macro (cpp_reader *);
+static void do_pragma_pop_macro (cpp_reader *);
/* This is the table of directive handlers. It is ordered by
frequency of occurrence; the numbers at the end are directive
D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \
D(warning, T_WARNING, EXTENSION, 0) /* 22 */ \
D(include_next, T_INCLUDE_NEXT, EXTENSION, INCL | EXPAND) /* 19 */ \
-D(ident, T_IDENT, EXTENSION, IN_I | DEPRECATED) /* 11 */ \
+D(ident, T_IDENT, EXTENSION, IN_I) /* 11 */ \
D(import, T_IMPORT, EXTENSION, INCL | EXPAND) /* 0 ObjC */ \
D(assert, T_ASSERT, EXTENSION, DEPRECATED) /* 0 SVR4 */ \
D(unassert, T_UNASSERT, EXTENSION, DEPRECATED) /* 0 SVR4 */ \
-D(sccs, T_SCCS, EXTENSION, IN_I | DEPRECATED) /* 0 SVR4? */
+D(sccs, T_SCCS, EXTENSION, IN_I) /* 0 SVR4? */
/* #sccs is synonymous with #ident. */
#define do_sccs do_ident
else if (((dir->flags & DEPRECATED) != 0
|| (dir == &dtable[T_IMPORT] && !CPP_OPTION (pfile, objc)))
&& CPP_OPTION (pfile, warn_deprecated))
- cpp_error (pfile, CPP_DL_WARNING, "#%s is a deprecated GCC extension",
- dir->name);
+ cpp_warning (pfile, CPP_W_DEPRECATED,
+ "#%s is a deprecated GCC extension", dir->name);
}
/* Traditionally, a directive is ignored unless its # is in
if (CPP_WTRADITIONAL (pfile))
{
if (dir == &dtable[T_ELIF])
- cpp_error (pfile, CPP_DL_WARNING,
- "suggest not using #elif in traditional C");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+ "suggest not using #elif in traditional C");
else if (indented && dir->origin == KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
- "traditional C ignores #%s with the # indented",
- dir->name);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+ "traditional C ignores #%s with the # indented",
+ dir->name);
else if (!indented && dir->origin != KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
- "suggest hiding #%s from traditional C with an indented #",
- dir->name);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+ "suggest hiding #%s from traditional C with an indented #",
+ dir->name);
}
}
/* Allow macro expansion. */
header = get_token_no_padding (pfile);
*location = header->src_loc;
- if (header->type == CPP_STRING || header->type == CPP_HEADER_NAME)
+ if ((header->type == CPP_STRING && header->val.str.text[0] != 'R')
+ || header->type == CPP_HEADER_NAME)
{
fname = XNEWVEC (char, header->val.str.len - 1);
memcpy (fname, header->val.str.text + 1, header->val.str.len - 2);
/* Report a warning or error detected by the program we are
processing. Use the directive's tokens in the error message. */
static void
-do_diagnostic (cpp_reader *pfile, int code, int print_dir)
+do_diagnostic (cpp_reader *pfile, int code, int reason, int print_dir)
{
const unsigned char *dir_name;
unsigned char *line;
line = cpp_output_line_to_string (pfile, dir_name);
pfile->state.prevent_expansion--;
- cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
+ if (code == CPP_DL_WARNING_SYSHDR && reason)
+ cpp_warning_with_line_syshdr (pfile, reason, src_loc, 0, "%s", line);
+ else if (code == CPP_DL_WARNING && reason)
+ cpp_warning_with_line (pfile, reason, src_loc, 0, "%s", line);
+ else
+ cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
free (line);
}
static void
do_error (cpp_reader *pfile)
{
- do_diagnostic (pfile, CPP_DL_ERROR, 1);
+ do_diagnostic (pfile, CPP_DL_ERROR, 0, 1);
}
static void
do_warning (cpp_reader *pfile)
{
/* We want #warning diagnostics to be emitted in system headers too. */
- do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, 1);
+ do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, CPP_W_WARNING_DIRECTIVE, 1);
}
/* Report program identification. */
{
/* Pragmas in the global namespace. */
register_pragma_internal (pfile, 0, "once", do_pragma_once);
+ register_pragma_internal (pfile, 0, "push_macro", do_pragma_push_macro);
+ register_pragma_internal (pfile, 0, "pop_macro", do_pragma_pop_macro);
/* New GCC-specific pragmas should be put in the GCC namespace. */
register_pragma_internal (pfile, "GCC", "poison", do_pragma_poison);
_cpp_mark_file_once_only (pfile, pfile->buffer->file);
}
+/* Handle #pragma push_macro(STRING). */
+static void
+do_pragma_push_macro (cpp_reader *pfile)
+{
+ char *macroname, *dest;
+ const char *limit, *src;
+ const cpp_token *txt;
+ struct def_pragma_macro *c;
+
+ txt = get__Pragma_string (pfile);
+ if (!txt)
+ {
+ source_location src_loc = pfile->cur_token[-1].src_loc;
+ cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
+ "invalid #pragma push_macro directive");
+ check_eol (pfile, false);
+ skip_rest_of_line (pfile);
+ return;
+ }
+ dest = macroname = (char *) alloca (txt->val.str.len + 2);
+ src = (const char *) (txt->val.str.text + 1 + (txt->val.str.text[0] == 'L'));
+ limit = (const char *) (txt->val.str.text + txt->val.str.len - 1);
+ while (src < limit)
+ {
+ /* We know there is a character following the backslash. */
+ if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
+ src++;
+ *dest++ = *src++;
+ }
+ *dest = 0;
+ check_eol (pfile, false);
+ skip_rest_of_line (pfile);
+ c = XNEW (struct def_pragma_macro);
+ c->name = XNEWVAR (char, strlen (macroname) + 1);
+ strcpy (c->name, macroname);
+ c->next = pfile->pushed_macros;
+ c->value = cpp_push_definition (pfile, c->name);
+ pfile->pushed_macros = c;
+}
+
+/* Handle #pragma pop_macro(STRING). */
+static void
+do_pragma_pop_macro (cpp_reader *pfile)
+{
+ char *macroname, *dest;
+ const char *limit, *src;
+ const cpp_token *txt;
+ struct def_pragma_macro *l = NULL, *c = pfile->pushed_macros;
+ txt = get__Pragma_string (pfile);
+ if (!txt)
+ {
+ source_location src_loc = pfile->cur_token[-1].src_loc;
+ cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0,
+ "invalid #pragma pop_macro directive");
+ check_eol (pfile, false);
+ skip_rest_of_line (pfile);
+ return;
+ }
+ dest = macroname = (char *) alloca (txt->val.str.len + 2);
+ src = (const char *) (txt->val.str.text + 1 + (txt->val.str.text[0] == 'L'));
+ limit = (const char *) (txt->val.str.text + txt->val.str.len - 1);
+ while (src < limit)
+ {
+ /* We know there is a character following the backslash. */
+ if (*src == '\\' && (src[1] == '\\' || src[1] == '"'))
+ src++;
+ *dest++ = *src++;
+ }
+ *dest = 0;
+ check_eol (pfile, false);
+ skip_rest_of_line (pfile);
+
+ while (c != NULL)
+ {
+ if (!strcmp (c->name, macroname))
+ {
+ if (!l)
+ pfile->pushed_macros = c->next;
+ else
+ l->next = c->next;
+ cpp_pop_definition (pfile, c->name, c->value);
+ free (c->name);
+ free (c);
+ break;
+ }
+ l = c;
+ c = c->next;
+ }
+}
+
/* Handle #pragma GCC poison, to poison one or more identifiers so
that the lexer produces a hard error for each subsequent usage. */
static void
if (cpp_get_token (pfile)->type != CPP_EOF)
{
_cpp_backup_tokens (pfile, 1);
- do_diagnostic (pfile, CPP_DL_WARNING, 0);
+ do_diagnostic (pfile, CPP_DL_WARNING, 0, 0);
}
}
if (string->type == CPP_EOF)
_cpp_backup_tokens (pfile, 1);
if (string->type != CPP_STRING && string->type != CPP_WSTRING
- && string->type != CPP_STRING32 && string->type != CPP_STRING16)
+ && string->type != CPP_STRING32 && string->type != CPP_STRING16
+ && string->type != CPP_UTF8STRING)
return NULL;
paren = get_token_no_padding (pfile);
pfile->cb.used_undef (pfile, pfile->directive_line, node);
}
}
+ if (pfile->cb.used)
+ pfile->cb.used (pfile, pfile->directive_line, node);
check_eol (pfile, false);
}
}
pfile->cb.used_undef (pfile, pfile->directive_line, node);
}
}
+ if (pfile->cb.used)
+ pfile->cb.used (pfile, pfile->directive_line, node);
check_eol (pfile, false);
}
}
run_directive (pfile, T_UNDEF, buf, len);
}
-/* Like lex_macro_node, but read the input from STR. */
-static cpp_hashnode *
-lex_macro_node_from_str (cpp_reader *pfile, const char *str)
-{
- size_t len = strlen (str);
- uchar *buf = (uchar *) alloca (len + 1);
- cpp_hashnode *node;
-
- memcpy (buf, str, len);
- buf[len] = '\n';
- cpp_push_buffer (pfile, buf, len, true);
- node = lex_macro_node (pfile, true);
- _cpp_pop_buffer (pfile);
-
- return node;
-}
-
/* If STR is a defined macro, return its definition node, else return NULL. */
cpp_macro *
cpp_push_definition (cpp_reader *pfile, const char *str)
{
- cpp_hashnode *node = lex_macro_node_from_str (pfile, str);
+ cpp_hashnode *node = _cpp_lex_identifier (pfile, str);
if (node && node->type == NT_MACRO)
return node->value.macro;
else
void
cpp_pop_definition (cpp_reader *pfile, const char *str, cpp_macro *dfn)
{
- cpp_hashnode *node = lex_macro_node_from_str (pfile, str);
+ cpp_hashnode *node = _cpp_lex_identifier (pfile, str);
if (node == NULL)
return;