-/* This is a dummy structure whose only purpose is getting alignment
- correct. */
-struct toklist_dummy
-{
- cpp_toklist list;
- cpp_token first_token;
-};
-
-
-/* Allocate space to hold the token list, its tokens, their text, and
- the parameter names if needed. Empty expansions are stored as a
- single placemarker token.
-
- These are all allocated in a block together for performance
- reasons. Therefore, this token list cannot be expanded like a
- normal token list. Try to do so, and you lose. */
-static cpp_toklist *
-alloc_macro (pfile, info, ntokens, len)
- cpp_reader *pfile;
- struct macro_info *info;
- unsigned int ntokens, len;
-{
- unsigned int size;
- struct toklist_dummy *dummy;
- cpp_toklist *list;
-
- size = sizeof (struct toklist_dummy);
- size += (ntokens - 1) * sizeof(cpp_token);
- size += len + info->paramlen;
-
- dummy = (struct toklist_dummy *) xmalloc (size);
- list = (cpp_toklist *) dummy;
-
- /* Initialize the monster. */
- list->tokens = &dummy->first_token;
- list->tokens_used = list->tokens_cap = ntokens;
-
- list->namebuf = (unsigned char *) &list->tokens[ntokens];
- list->name_used = list->name_cap = len + info->paramlen;
-
- list->directive = 0;
- list->line = pfile->token_list.line;
- list->file = pfile->token_list.file;
- list->params_len = info->paramlen;
- list->paramc = info->paramc;
- list->flags = info->flags;
-
- return list;
-}
-
-/* Free a macro allocated by allocate_macro. */
-static void
-free_macro (list)
- const cpp_toklist *list;
-{
- free ((PTR) list);
-}
-
-/* Copy the tokens of the expansion, beginning with FIRST until
- CPP_EOF. For a function-like macro, FIRST_PARAM points to the
- first parameter. INFO contains information about the macro.
-
- Change the type of macro arguments in the expansion from CPP_NAME
- to CPP_MACRO_ARG. Remove #'s that represent stringification,
- flagging the CPP_MACRO_ARG it operates on STRINGIFY. Remove ##'s,
- flagging the token on its immediate left PASTE_LEFT. Returns the
- token list for the macro expansion, or 0 on error. */
-static const cpp_toklist *
-save_expansion (pfile, first, first_param, info)
- cpp_reader *pfile;
- const cpp_token *first;
- const cpp_token *first_param;
- struct macro_info *info;
-{
- const cpp_token *token;
- cpp_toklist *list;
- cpp_token *dest;
- unsigned int len, ntokens;
- unsigned char *buf;
-
- /* Count tokens in expansion. We drop paste tokens, and stringize
- tokens, so don't count them. */
- ntokens = len = 0;
- for (token = first; token->type != CPP_EOF; token++)
- {
- if (token->type == CPP_PASTE)
- {
- /* Token-paste ##, can appear in both object-like and
- function-like macros, but not at the ends. Constraint
- 6.10.3.3.1 */
- if (token == first || token[1].type == CPP_EOF)
- {
- cpp_error_with_line (pfile, token->line, token->col,
- "'##' cannot appear at either end of a macro expansion");
- return 0;
- }
- continue;
- }
- else if (token->type == CPP_HASH)
- {
- /* Stringifying #, but a normal character in object-like
- macros. Must come before a parameter name. Constraint
- 6.10.3.2.1. */
- if (info->paramc >= 0)
- {
- if (token[1].type == CPP_NAME
- && find_param (first_param, token + 1))
- continue;
- if (! CPP_OPTION (pfile, lang_asm))
- {
- cpp_error_with_line (pfile, token->line, token->col,
- "'#' is not followed by a macro parameter");
- return 0;
- }
- }
- }
- else if (token->type == CPP_NAME)
- {
- /* Constraint 6.10.3.5 */
- if (!(info->flags & VAR_ARGS) && is__va_args__ (pfile, token))
- return 0;
- /* It might be worth doing a check here that we aren't a
- macro argument, since we don't store the text of macro
- arguments. This would reduce "len" and save space. */
- }
- ntokens++;
- if (TOKEN_SPELL (token) == SPELL_STRING)
- len += token->val.str.len;
- }
-
- if (ntokens == 0)
- ntokens++;
- list = alloc_macro (pfile, info, ntokens, len);
- buf = list->namebuf;
-
- /* Store the null-terminated parameter spellings of a macro, to
- provide pedantic warnings to satisfy 6.10.3.2, or for use when
- dumping macro definitions. They must go first. */
- if (list->params_len)
- for (token = first_param; token < first; token++)
- if (token->type == CPP_NAME)
- {
- /* Copy null too. */
- memcpy (buf, token->val.node->name, token->val.node->length + 1);
- buf += token->val.node->length + 1;
- }
-
- dest = list->tokens;
- for (token = first; token->type != CPP_EOF; token++)
- {
- unsigned int param_no;
-
- switch (token->type)
- {
- case CPP_NAME:
- if (list->paramc == -1)
- break;
-
- /* Check if the name is a macro parameter. */
- param_no = find_param (first_param, token);
- if (param_no == 0)
- break;
- dest->val.aux = param_no - 1;
-
- dest->type = CPP_MACRO_ARG;
- if (token[-1].type == CPP_HASH)
- dest->flags = token[-1].flags | STRINGIFY_ARG;
- else
- dest->flags = token->flags; /* Particularly PREV_WHITE. */
- dest++;
- continue;
-
- case CPP_PASTE:
- dest[-1].flags |= PASTE_LEFT;
- continue;
-
- case CPP_HASH:
- /* Stringifying #. Constraint 6.10.3.2.1 */
- if (list->paramc >= 0 && token[1].type == CPP_NAME
- && find_param (first_param, token + 1))
- continue;
- break;
-
- default:
- break;
- }
-
- /* Copy the token. */
- *dest = *token;
- if (TOKEN_SPELL (token) == SPELL_STRING)
- {
- memcpy (buf, token->val.str.text, token->val.str.len);
- dest->val.str.text = buf;
- buf += dest->val.str.len;
- }
- dest++;
- }
-
- if (dest == list->tokens)
- {
- dest->type = CPP_PLACEMARKER;
- dest->flags = 0;
- }
-
- return list;
-}
-
-int
-_cpp_create_definition (pfile, hp)