* Makefile.in: Update cppmain.o.
* cpphash.h (struct cpp_reader): Move some members to a
nested structure.
(trad_line): Rename saved_line.
(_cpp_read_logical_line_trad): Update.
(_cpp_remove_overlay): New.
* cppinit.c (cpp_create_reader): No need to set saved_line.
(cpp_destroy): Update.
(cpp_read_main_file): Only overlay if compiling.
* cpplex.c (continue_after_nul): Return false if in directive.
* cpplib.c (EXPAND): New.
(directive_table, SEEN_EOL): Update.
(end_directive): Remove overlay if traditional; don't skip
line in traditional #define.
(prepare_directive_trad): New.
(_cpp_handle_directive, run_directive): Update for traditional
directives.
(lex_macro_node): Simplify, don't use lex_identifier_trad.
* cpplib.h (struct options): Add preprocess_only.
* cppmain.c: Don't include intl.h.
(cpp_preprocess_file): Set options->preprocess_only.
(scan_translation_unit_trad): Fix, and print line numbers.
* cpptrad.c (check_output_buffer, lex_identifier, scan_parameters,
maybe_start_funlike, scan_out_logical_line, replace_args_and_push,
save_replacement_text, _cpp_create_trad_definition): Update for
variable renaming.
(_cpp_overlay_buffer): Save line number.
(_cpp_remove_overlay): Rename from restore_buff, restore line.
(_cpp_read_logical_line_trad): Don't handle overlays here.
(scan_out_logical_line): Process directives.
From-SVN: r54485
$(AR) $(AR_FLAGS) libcpp.a $(LIBCPP_OBJS)
-$(RANLIB) libcpp.a
-cppmain.o: cppmain.c $(CONFIG_H) $(CPPLIB_H) intl.h $(SYSTEM_H)
+cppmain.o: cppmain.c $(CONFIG_H) $(LIBCPP_DEPS)
cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS)
/* Whether cpplib owns the hashtable. */
unsigned char our_hashtable;
- /* Traditional preprocessing output buffer. */
- uchar *trad_out_base, *trad_out_limit;
- uchar *trad_out_cur;
- unsigned int trad_line;
+ /* Traditional preprocessing output buffer (a logical line). */
+ struct
+ {
+ uchar *base;
+ uchar *limit;
+ uchar *cur;
+ unsigned int first_line;
+ } out;
+
+ /* Used to save the original line number during traditional
+ preprocessing. */
+ unsigned int saved_line;
};
/* Character classes. Based on the more primitive macros in safe-ctype.h.
extern void _cpp_pop_buffer PARAMS ((cpp_reader *));
/* In cpptrad.c. */
-extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *, int));
+extern bool _cpp_read_logical_line_trad PARAMS ((cpp_reader *));
extern void _cpp_overlay_buffer PARAMS ((cpp_reader *pfile, const uchar *,
size_t));
+extern void _cpp_remove_overlay PARAMS ((cpp_reader *));
extern cpp_hashnode *_cpp_lex_identifier_trad PARAMS ((cpp_reader *));
extern void _cpp_set_trad_context PARAMS ((cpp_reader *));
extern bool _cpp_create_trad_definition PARAMS ((cpp_reader *, cpp_macro *));
/* Initialise the line map. Start at logical line 1, so we can use
a line number of zero for special states. */
init_line_maps (&pfile->line_maps);
- pfile->trad_line = pfile->line = 1;
+ pfile->line = 1;
/* Initialize lexer state. */
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
while (CPP_BUFFER (pfile) != NULL)
_cpp_pop_buffer (pfile);
- if (pfile->trad_out_base)
- free (pfile->trad_out_base);
+ if (pfile->out.base)
+ free (pfile->out.base);
if (pfile->macro_buffer)
{
if (CPP_OPTION (pfile, preprocessed))
read_original_filename (pfile);
/* Overlay an empty buffer to seed traditional preprocessing. */
- else if (CPP_OPTION (pfile, traditional))
+ else if (CPP_OPTION (pfile, traditional)
+ && !CPP_OPTION (pfile, preprocess_only))
_cpp_overlay_buffer (pfile, U"", 0);
return pfile->map->to_file;
buffer->saved_flags = BOL;
if (CPP_OPTION (pfile, traditional))
- more = _cpp_read_logical_line_trad (pfile, true);
+ {
+ if (pfile->state.in_directive)
+ return false;
+
+ _cpp_remove_overlay (pfile);
+ more = _cpp_read_logical_line_trad (pfile);
+ _cpp_overlay_buffer (pfile, pfile->out.base,
+ pfile->out.cur - pfile->out.base);
+ pfile->line = pfile->out.first_line;
+ }
else
{
/* Stop parsing arguments with a CPP_EOF. When we finally come
conditional; IF_COND an opening conditional. INCL means to treat
"..." and <...> as q-char and h-char sequences respectively. IN_I
means this directive should be handled even if -fpreprocessed is in
- effect (these are the directives with callback hooks). */
+ effect (these are the directives with callback hooks).
+
+ EXPAND is set on directives that are always macro-expanded. If
+ INCL is set, macro expansion is special-cased and EXPAND should not
+ be set. */
#define COND (1 << 0)
#define IF_COND (1 << 1)
#define INCL (1 << 2)
#define IN_I (1 << 3)
+#define EXPAND (1 << 4)
/* Defines one #-directive, including how to handle it. */
typedef void (*directive_handler) PARAMS ((cpp_reader *));
static void skip_rest_of_line PARAMS ((cpp_reader *));
static void check_eol PARAMS ((cpp_reader *));
static void start_directive PARAMS ((cpp_reader *));
+static void prepare_directive_trad PARAMS ((cpp_reader *));
static void end_directive PARAMS ((cpp_reader *, int));
static void directive_diagnostics
PARAMS ((cpp_reader *, const directive *, int));
D(include, T_INCLUDE, KANDR, INCL) /* 52262 */ \
D(endif, T_ENDIF, KANDR, COND) /* 45855 */ \
D(ifdef, T_IFDEF, KANDR, COND | IF_COND) /* 22000 */ \
-D(if, T_IF, KANDR, COND | IF_COND) /* 18162 */ \
+D(if, T_IF, KANDR, COND | IF_COND | EXPAND) /* 18162 */ \
D(else, T_ELSE, KANDR, COND) /* 9863 */ \
D(ifndef, T_IFNDEF, KANDR, COND | IF_COND) /* 9675 */ \
D(undef, T_UNDEF, KANDR, IN_I) /* 4837 */ \
-D(line, T_LINE, KANDR, 0) /* 2465 */ \
-D(elif, T_ELIF, STDC89, COND) /* 610 */ \
+D(line, T_LINE, KANDR, EXPAND) /* 2465 */ \
+D(elif, T_ELIF, STDC89, COND | EXPAND) /* 610 */ \
D(error, T_ERROR, STDC89, 0) /* 475 */ \
D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \
D(warning, T_WARNING, EXTENSION, 0) /* 22 */ \
do_linemarker, U"#", 1, KANDR, IN_I
};
-#define SEEN_EOL() (CPP_OPTION (pfile, traditional) \
- || pfile->cur_token[-1].type == CPP_EOF)
+#define SEEN_EOL() (pfile->cur_token[-1].type == CPP_EOF)
/* Skip any remaining tokens in a directive. */
static void
cpp_reader *pfile;
int skip_line;
{
+ if (CPP_OPTION (pfile, traditional))
+ {
+ if (pfile->directive == &dtable[T_DEFINE])
+ skip_line = false;
+ else
+ _cpp_remove_overlay (pfile);
+ }
+
/* We don't skip for an assembler #. */
if (skip_line)
{
pfile->directive = 0;
}
+/* Prepare to handle the directive in pfile->directive. */
+static void
+prepare_directive_trad (pfile)
+ cpp_reader *pfile;
+{
+ if (pfile->directive == &dtable[T_DEFINE])
+ CUR (pfile->context) = pfile->buffer->cur;
+ else
+ {
+ bool no_expand = ! (pfile->directive->flags & EXPAND);
+
+ if (no_expand)
+ pfile->state.prevent_expansion++;
+ _cpp_read_logical_line_trad (pfile);
+ if (no_expand)
+ pfile->state.prevent_expansion--;
+ _cpp_overlay_buffer (pfile, pfile->out.base,
+ pfile->out.cur - pfile->out.base);
+ }
+}
+
/* Output diagnostics for a directive DIR. INDENTED is non-zero if
the '#' was indented. */
static void
! CPP_OPTION (pfile, discard_comments_in_macro_exp);
pfile->directive = dir;
+ if (CPP_OPTION (pfile, traditional))
+ prepare_directive_trad (pfile);
(*pfile->directive->handler) (pfile);
}
else if (skip == 0)
/* We don't want a leading # to be interpreted as a directive. */
pfile->buffer->saved_flags = 0;
pfile->directive = &dtable[dir_no];
+ if (CPP_OPTION (pfile, traditional))
+ prepare_directive_trad (pfile);
(void) (*pfile->directive->handler) (pfile);
end_directive (pfile, 1);
_cpp_pop_buffer (pfile);
lex_macro_node (pfile)
cpp_reader *pfile;
{
- cpp_hashnode *node;
+ const cpp_token *token = _cpp_lex_token (pfile);
/* The token immediately after #define must be an identifier. That
identifier may not be "defined", per C99 6.10.8p4.
Note that if we're copying comments into macro expansions, we
could encounter comment tokens here, so eat them all up first. */
- if (CPP_OPTION (pfile, traditional))
- node = _cpp_lex_identifier_trad (pfile);
- else
+ if (! CPP_OPTION (pfile, discard_comments_in_macro_exp))
{
- const cpp_token *token = _cpp_lex_token (pfile);
+ while (token->type == CPP_COMMENT)
+ token = _cpp_lex_token (pfile);
+ }
- if (! CPP_OPTION (pfile, discard_comments_in_macro_exp))
- {
- while (token->type == CPP_COMMENT)
- token = _cpp_lex_token (pfile);
- }
+ if (token->type == CPP_NAME)
+ {
+ cpp_hashnode *node = token->val.node;
- if (token->type == CPP_EOF)
- {
- cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive",
- pfile->directive->name);
- return NULL;
- }
-
- if (token->type == CPP_NAME || (token->flags & NAMED_OP))
- node = token->val.node;
- else
- node = NULL;
+ if (node == pfile->spec_nodes.n_defined)
+ cpp_error (pfile, DL_ERROR,
+ "\"defined\" cannot be used as a macro name");
+ else if (! (node->flags & NODE_POISONED))
+ return node;
}
-
- if (!node)
- cpp_error (pfile, DL_ERROR, "macro names must be identifiers");
- else if (node->flags & NODE_OPERATOR)
+ else if (token->flags & NAMED_OP)
cpp_error (pfile, DL_ERROR,
"\"%s\" cannot be used as a macro name as it is an operator in C++",
- NODE_NAME (node));
- else if (node == pfile->spec_nodes.n_defined)
- cpp_error (pfile, DL_ERROR, "\"defined\" cannot be used as a macro name");
- else if (! (node->flags & NODE_POISONED))
- return node;
+ NODE_NAME (token->val.node));
+ else if (token->type == CPP_EOF)
+ cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive",
+ pfile->directive->name);
+ else
+ cpp_error (pfile, DL_ERROR, "macro names must be identifiers");
return NULL;
}
/* True for traditional preprocessing. */
unsigned char traditional;
+ /* True if only preprocessing and not compiling. */
+ unsigned char preprocess_only;
+
/* Target-specific features set by the front end or client. */
/* Precision for target CPP arithmetic, target characters, target
#include "system.h"
#include "cpplib.h"
#include "cpphash.h"
-#include "intl.h"
/* Encapsulates state used to convert the stream of tokens coming from
cpp_get_token back into a text file. */
{
options = cpp_get_options (pfile);
+ /* Let preprocessor know if it's only preprocessing. It would be
+ nice to lose this somehow. */
+ options->preprocess_only = 1;
+
/* Initialize the printer structure. Setting print.line to -1 here
is a trick to guarantee that the first token of the file will
cause a linemarker to be output by maybe_print_line. */
print.line++;
}
+/* Writes out a traditionally preprocessed file. */
static void
scan_translation_unit_trad (pfile)
cpp_reader *pfile;
{
- bool more;
- size_t len;
-
- do
+ for (;;)
{
- more = _cpp_read_logical_line_trad (pfile, false);
- len = pfile->trad_out_cur - pfile->trad_out_base;
- fwrite (pfile->trad_out_base, 1, len, print.outf);
+ size_t len;
+
+ if (!_cpp_read_logical_line_trad (pfile))
+ break;
+ len = pfile->out.cur - pfile->out.base;
+ maybe_print_line (print.map, pfile->out.first_line);
+ fwrite (pfile->out.base, 1, len, print.outf);
+ print.printed = 1;
}
- while (more);
}
/* If the token read on logical line LINE needs to be output on a
static const uchar *skip_comment PARAMS ((cpp_reader *, const uchar *));
static void scan_out_logical_line PARAMS ((cpp_reader *pfile, cpp_macro *));
static void check_output_buffer PARAMS ((cpp_reader *, size_t));
-static void restore_buff PARAMS ((cpp_reader *));
static void push_replacement_text PARAMS ((cpp_reader *, cpp_hashnode *));
static bool scan_parameters PARAMS ((cpp_reader *, cpp_macro *));
static void save_replacement_text PARAMS ((cpp_reader *, cpp_macro *,
cpp_reader *pfile;
size_t n;
{
- if (n > (size_t) (pfile->trad_out_limit - pfile->trad_out_cur))
+ if (n > (size_t) (pfile->out.limit - pfile->out.cur))
{
- size_t size = pfile->trad_out_cur - pfile->trad_out_base;
+ size_t size = pfile->out.cur - pfile->out.base;
size_t new_size = (size + n) * 3 / 2;
- pfile->trad_out_base
- = (uchar *) xrealloc (pfile->trad_out_base, new_size);
- pfile->trad_out_limit = pfile->trad_out_base + new_size;
- pfile->trad_out_cur = pfile->trad_out_base + size;
+ pfile->out.base
+ = (uchar *) xrealloc (pfile->out.base, new_size);
+ pfile->out.limit = pfile->out.base + new_size;
+ pfile->out.cur = pfile->out.base + size;
}
}
/* Lexes and outputs an identifier starting at CUR, which is assumed
to point to a valid first character of an identifier. Returns
- the hashnode, and updates trad_out_cur. */
+ the hashnode, and updates out.cur. */
static cpp_hashnode *
lex_identifier (pfile, cur)
cpp_reader *pfile;
const uchar *cur;
{
size_t len;
- uchar *out = pfile->trad_out_cur;
+ uchar *out = pfile->out.cur;
cpp_hashnode *result;
do
while (is_numchar (*cur));
CUR (pfile->context) = cur;
- len = out - pfile->trad_out_cur;
- result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->trad_out_cur,
+ len = out - pfile->out.cur;
+ result = (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->out.cur,
len, HT_ALLOC);
- pfile->trad_out_cur = out;
+ pfile->out.cur = out;
return result;
}
buffer->cur = start;
buffer->line_base = start;
buffer->rlimit = start + len;
+
+ pfile->saved_line = pfile->line;
}
/* Restores a buffer overlaid by _cpp_overlay_buffer(). */
-static void
-restore_buff (pfile)
+void
+_cpp_remove_overlay (pfile)
cpp_reader *pfile;
{
cpp_buffer *buffer = pfile->buffer;
buffer->cur = buffer->saved_cur;
buffer->rlimit = buffer->saved_rlimit;
buffer->line_base = buffer->saved_line_base;
+
+ pfile->line = pfile->saved_line;
}
/* Reads a logical line into the output buffer. Returns TRUE if there
is more text left in the buffer. */
bool
-_cpp_read_logical_line_trad (pfile, overlay)
+_cpp_read_logical_line_trad (pfile)
cpp_reader *pfile;
- int overlay;
{
cpp_buffer *buffer;
- unsigned int first_line = 0;
-
- if (overlay)
- {
- restore_buff (pfile);
- first_line = pfile->line = pfile->trad_line;
- }
buffer = pfile->buffer;
if (buffer->cur == buffer->rlimit)
CUR (pfile->context) = buffer->cur;
RLIMIT (pfile->context) = buffer->rlimit;
- pfile->trad_out_cur = pfile->trad_out_base;
+ pfile->out.cur = pfile->out.base;
+ pfile->out.first_line = pfile->line;
scan_out_logical_line (pfile, NULL);
buffer->cur = CUR (pfile->context);
- if (overlay)
- {
- pfile->trad_line = pfile->line;
- pfile->line = first_line;
- _cpp_overlay_buffer (pfile, pfile->trad_out_base,
- pfile->trad_out_cur - pfile->trad_out_base);
- }
-
return true;
}
macro->buff = _cpp_get_buff (pfile, n * sizeof (size_t));
macro->args = (size_t *) BUFF_FRONT (macro->buff);
macro->node = node;
- macro->offset = start - pfile->trad_out_base;
+ macro->offset = start - pfile->out.base;
macro->argc = 0;
pfile->state.parsing_args = 1;
context = pfile->context;
cur = CUR (context);
check_output_buffer (pfile, RLIMIT (context) - cur);
- out = pfile->trad_out_cur;
+ out = pfile->out.cur;
for (;;)
{
/* If this is a macro's expansion, pop it. */
if (context->prev)
{
- pfile->trad_out_cur = out - 1;
+ pfile->out.cur = out - 1;
_cpp_pop_context (pfile);
goto new_context;
}
{
cpp_hashnode *node;
- pfile->trad_out_cur = --out;
+ pfile->out.cur = --out;
node = lex_identifier (pfile, cur - 1);
if (node->type == NT_MACRO
{
/* Remove the object-like macro's name from the
output, and push its replacement text. */
- pfile->trad_out_cur = out;
+ pfile->out.cur = out;
push_replacement_text (pfile, node);
goto new_context;
}
{
/* Found a parameter in the replacement text of a
#define. Remove its name from the output. */
- pfile->trad_out_cur = out;
+ pfile->out.cur = out;
save_replacement_text (pfile, macro, node->arg_index);
}
- out = pfile->trad_out_cur;
+ out = pfile->out.cur;
cur = CUR (context);
}
break;
paren_depth++;
if (pfile->state.parsing_args == 1)
{
- const uchar *p = pfile->trad_out_base + fmacro.offset;
+ const uchar *p = pfile->out.base + fmacro.offset;
/* Invoke a prior function-like macro if there is only
white space in-between. */
{
pfile->state.parsing_args = 2;
paren_depth = 1;
- out = pfile->trad_out_base + fmacro.offset;
+ out = pfile->out.base + fmacro.offset;
fmacro.args[0] = fmacro.offset;
}
else
case ',':
if (quote == 0 && pfile->state.parsing_args == 2 && paren_depth == 1)
- save_argument (&fmacro, out - pfile->trad_out_base);
+ save_argument (&fmacro, out - pfile->out.base);
break;
case ')':
cpp_macro *m = fmacro.node->value.macro;
pfile->state.parsing_args = 0;
- save_argument (&fmacro, out - pfile->trad_out_base);
+ save_argument (&fmacro, out - pfile->out.base);
/* A single zero-length argument is no argument. */
if (fmacro.argc == 1
&& m->paramc == 0
- && out == pfile->trad_out_base + 1)
+ && out == pfile->out.base + 1)
fmacro.argc = 0;
if (_cpp_arguments_ok (pfile, m, fmacro.node, fmacro.argc))
{
/* Remove the macro's invocation from the
output, and push its replacement text. */
- pfile->trad_out_cur = (pfile->trad_out_base
+ pfile->out.cur = (pfile->out.base
+ fmacro.offset);
CUR (context) = cur;
replace_args_and_push (pfile, &fmacro);
}
break;
+ case '#':
+ /* At start of a line it's a directive. */
+ if (out - 1 == pfile->out.base && !pfile->state.in_directive)
+ {
+ /* This is a kludge. We want to have the ISO
+ preprocessor lex the next token. */
+ pfile->buffer->cur = cur;
+ if (_cpp_handle_directive (pfile, false /* indented */))
+ {
+ cur = CUR (context);
+ goto done;
+ }
+ }
+ break;
+
default:
break;
}
done:
out[-1] = '\0';
CUR (context) = cur;
- pfile->trad_out_cur = out - 1;
+ pfile->out.cur = out - 1;
if (fmacro.buff)
_cpp_release_buff (pfile, fmacro.buff);
}
break;
arglen = (fmacro->args[b->arg_index]
- fmacro->args[b->arg_index - 1] - 1);
- memcpy (p, pfile->trad_out_base + fmacro->args[b->arg_index - 1],
+ memcpy (p, pfile->out.base + fmacro->args[b->arg_index - 1],
arglen);
p += arglen;
exp += BLOCK_LEN (b->text_len);
}
/* Read and record the parameters, if any, of a function-like macro
- definition. Destroys pfile->trad_out_cur.
+ definition. Destroys pfile->out.cur.
Returns true on success, false on failure (syntax error or a
duplicate parameter). On success, CUR (pfile->context) is just
return ok;
}
-/* Save the text from pfile->trad_out_base to pfile->trad_out_cur as
+/* Save the text from pfile->out.base to pfile->out.cur as
the replacement text for the current macro, followed by argument
ARG_INDEX, with zero indicating the end of the replacement
text. */
cpp_macro *macro;
unsigned int arg_index;
{
- size_t len = pfile->trad_out_cur - pfile->trad_out_base;
+ size_t len = pfile->out.cur - pfile->out.base;
uchar *exp;
if (macro->paramc == 0)
/* Object-like and function-like macros without parameters
simply store their NUL-terminated replacement text. */
exp = _cpp_unaligned_alloc (pfile, len + 1);
- memcpy (exp, pfile->trad_out_base, len);
+ memcpy (exp, pfile->out.base, len);
exp[len] = '\0';
macro->exp.text = exp;
macro->count = len;
/* Write out the block information. */
block->text_len = len;
block->arg_index = arg_index;
- memcpy (block->text, pfile->trad_out_base, len);
+ memcpy (block->text, pfile->out.base, len);
/* Lex the rest into the start of the output buffer. */
- pfile->trad_out_cur = pfile->trad_out_base;
+ pfile->out.cur = pfile->out.base;
macro->count += blen;
const uchar *cur;
uchar *limit;
+ CUR (pfile->context) = pfile->buffer->cur;
+
/* Is this a function-like macro? */
if (* CUR (pfile->context) == '(')
{
/* Skip leading whitespace in the replacement text. */
CUR (pfile->context) = skip_whitespace (pfile, CUR (pfile->context));
- pfile->trad_out_cur = pfile->trad_out_base;
+ pfile->out.cur = pfile->out.base;
pfile->state.prevent_expansion++;
scan_out_logical_line (pfile, macro);
pfile->state.prevent_expansion--;
return false;
/* Skip trailing white space. */
- cur = pfile->trad_out_base;
- limit = pfile->trad_out_cur;
+ cur = pfile->out.base;
+ limit = pfile->out.cur;
while (limit > cur && is_space (limit[-1]))
limit--;
- pfile->trad_out_cur = limit;
+ pfile->out.cur = limit;
save_replacement_text (pfile, macro, 0);
return true;
if (pfile->context->prev)
abort ();
- pfile->trad_out_cur = pfile->trad_out_base;
+ pfile->out.cur = pfile->out.base;
CUR (context) = buffer->cur;
RLIMIT (context) = buffer->rlimit;
check_output_buffer (pfile, RLIMIT (context) - CUR (context));