/* Push a context holding the replacement text of the macro NODE on the context stack. NODE is either object-like, or a function-like macro with no arguments. */ static void replace_args_and_push (cpp_reader *pfile, struct fun_macro *fmacro) { cpp_macro *macro = fmacro->node->value.macro; if (macro->paramc == 0) push_replacement_text (pfile, fmacro->node); else { const uchar *exp; uchar *p; _cpp_buff *buff; size_t len = 0; /* Calculate the length of the argument-replaced text. */ for (exp = macro->exp.text;;) { struct block *b = (struct block *) exp; len += b->text_len; if (b->arg_index == 0) break; len += (fmacro->args[b->arg_index] - fmacro->args[b->arg_index - 1] - 1); exp += BLOCK_LEN (b->text_len); } /* Allocate room for the expansion plus \n. */ buff = _cpp_get_buff (pfile, len + 1); /* Copy the expansion and replace arguments. */ p = BUFF_FRONT (buff); for (exp = macro->exp.text;;) { struct block *b = (struct block *) exp; size_t arglen; memcpy (p, b->text, b->text_len); p += b->text_len; if (b->arg_index == 0) break; arglen = (fmacro->args[b->arg_index] - fmacro->args[b->arg_index - 1] - 1); memcpy (p, pfile->out.base + fmacro->args[b->arg_index - 1], arglen); p += arglen; exp += BLOCK_LEN (b->text_len); } /* \n-terminate. */ *p = '\n'; _cpp_push_text_context (pfile, fmacro->node, BUFF_FRONT (buff), len); /* So we free buffer allocation when macro is left. */ pfile->context->buff = buff; } }
/* Creates a new buffer with enough space to hold the uncommitted remaining bytes of BUFF, and at least MIN_EXTRA more bytes. Copies the excess bytes to the new buffer. Chains the new buffer after BUFF, and returns the new buffer. */ _cpp_buff * _cpp_append_extend_buff (cpp_reader *pfile, _cpp_buff *buff, size_t min_extra) { size_t size = EXTENDED_BUFF_SIZE (buff, min_extra); _cpp_buff *new_buff = _cpp_get_buff (pfile, size); buff->next = new_buff; memcpy (new_buff->base, buff->cur, BUFF_ROOM (buff)); return new_buff; }
/* Creates a new buffer with enough space to hold the uncommitted remaining bytes of the buffer pointed to by BUFF, and at least MIN_EXTRA more bytes. Copies the excess bytes to the new buffer. Chains the new buffer before the buffer pointed to by BUFF, and updates the pointer to point to the new buffer. */ void _cpp_extend_buff (cpp_reader *pfile, _cpp_buff **pbuff, size_t min_extra) { _cpp_buff *new_buff, *old_buff = *pbuff; size_t size = EXTENDED_BUFF_SIZE (old_buff, min_extra); new_buff = _cpp_get_buff (pfile, size); memcpy (new_buff->base, old_buff->cur, BUFF_ROOM (old_buff)); new_buff->next = old_buff; *pbuff = new_buff; }
/* Set up state for finding the opening '(' of a function-like macro. */ static void maybe_start_funlike (cpp_reader *pfile, cpp_hashnode *node, const uchar *start, struct fun_macro *macro) { unsigned int n = node->value.macro->paramc + 1; if (macro->buff) _cpp_release_buff (pfile, macro->buff); 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->out.base; macro->argc = 0; }
/* Allocate permanent, unaligned storage of length LEN from a_buff. That buffer is used for growing allocations when saving macro replacement lists in a #define, and when parsing an answer to an assertion in #assert, #unassert or #if (and therefore possibly whilst expanding macros). It therefore must not be used by any code that they might call: specifically the lexer and the guts of the macro expander. All existing other uses clearly fit this restriction: storing registered pragmas during initialization. */ unsigned char * _cpp_aligned_alloc (cpp_reader *pfile, size_t len) { _cpp_buff *buff = pfile->a_buff; unsigned char *result = buff->cur; if (len > (size_t) (buff->limit - result)) { buff = _cpp_get_buff (pfile, len); buff->next = pfile->a_buff; pfile->a_buff = buff; result = buff->cur; } buff->cur = result + len; return result; }
/* Initialize a cpp_reader structure. */ cpp_reader * cpp_create_reader (enum c_lang lang, hash_table *table, struct line_maps *line_table) { cpp_reader *pfile; /* Initialize this instance of the library if it hasn't been already. */ init_library (); pfile = XCNEW (cpp_reader); memset (&pfile->base_context, 0, sizeof (pfile->base_context)); cpp_set_lang (pfile, lang); CPP_OPTION (pfile, warn_multichar) = 1; CPP_OPTION (pfile, discard_comments) = 1; CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1; CPP_OPTION (pfile, tabstop) = 8; CPP_OPTION (pfile, operator_names) = 1; CPP_OPTION (pfile, warn_trigraphs) = 2; CPP_OPTION (pfile, warn_endif_labels) = 1; CPP_OPTION (pfile, cpp_warn_deprecated) = 1; CPP_OPTION (pfile, cpp_warn_long_long) = 0; CPP_OPTION (pfile, dollars_in_ident) = 1; CPP_OPTION (pfile, warn_dollars) = 1; CPP_OPTION (pfile, warn_variadic_macros) = 1; CPP_OPTION (pfile, warn_builtin_macro_redefined) = 1; /* By default, track locations of tokens resulting from macro expansion. The '2' means, track the locations with the highest accuracy. Read the comments for struct cpp_options::track_macro_expansion to learn about the other values. */ CPP_OPTION (pfile, track_macro_expansion) = 2; CPP_OPTION (pfile, warn_normalize) = normalized_C; CPP_OPTION (pfile, warn_literal_suffix) = 1; /* Default CPP arithmetic to something sensible for the host for the benefit of dumb users like fix-header. */ CPP_OPTION (pfile, precision) = CHAR_BIT * sizeof (long); CPP_OPTION (pfile, char_precision) = CHAR_BIT; CPP_OPTION (pfile, wchar_precision) = CHAR_BIT * sizeof (int); CPP_OPTION (pfile, int_precision) = CHAR_BIT * sizeof (int); CPP_OPTION (pfile, unsigned_char) = 0; CPP_OPTION (pfile, unsigned_wchar) = 1; CPP_OPTION (pfile, bytes_big_endian) = 1; /* does not matter */ /* Default to no charset conversion. */ CPP_OPTION (pfile, narrow_charset) = _cpp_default_encoding (); CPP_OPTION (pfile, wide_charset) = 0; /* Default the input character set to UTF-8. */ CPP_OPTION (pfile, input_charset) = _cpp_default_encoding (); /* A fake empty "directory" used as the starting point for files looked up without a search path. Name cannot be '/' because we don't want to prepend anything at all to filenames using it. All other entries are correct zero-initialized. */ pfile->no_search_path.name = (char *) ""; /* Initialize the line map. */ pfile->line_table = line_table; /* Initialize lexer state. */ pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); /* Set up static tokens. */ pfile->avoid_paste.type = CPP_PADDING; pfile->avoid_paste.val.source = NULL; pfile->eof.type = CPP_EOF; pfile->eof.flags = 0; /* Create a token buffer for the lexer. */ _cpp_init_tokenrun (&pfile->base_run, 250); pfile->cur_run = &pfile->base_run; pfile->cur_token = pfile->base_run.base; /* Initialize the base context. */ pfile->context = &pfile->base_context; pfile->base_context.c.macro = 0; pfile->base_context.prev = pfile->base_context.next = 0; /* Aligned and unaligned storage. */ pfile->a_buff = _cpp_get_buff (pfile, 0); pfile->u_buff = _cpp_get_buff (pfile, 0); /* Initialize table for push_macro/pop_macro. */ pfile->pushed_macros = 0; /* Do not force token locations by default. */ pfile->forced_token_location_p = NULL; /* The expression parser stack. */ _cpp_expand_op_stack (pfile); /* Initialize the buffer obstack. */ _obstack_begin (&pfile->buffer_ob, 0, 0, (void *(*) (long)) xmalloc, (void (*) (void *)) free); _cpp_init_files (pfile); _cpp_init_hashtable (pfile, table); return pfile; }
/* Initialize a cpp_reader structure. */ cpp_reader * cpp_create_reader (enum c_lang lang, hash_table *table) { cpp_reader *pfile; /* Initialize this instance of the library if it hasn't been already. */ init_library (); pfile = xcalloc (1, sizeof (cpp_reader)); cpp_set_lang (pfile, lang); CPP_OPTION (pfile, warn_multichar) = 1; CPP_OPTION (pfile, discard_comments) = 1; CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1; CPP_OPTION (pfile, show_column) = 1; CPP_OPTION (pfile, tabstop) = 8; CPP_OPTION (pfile, operator_names) = 1; CPP_OPTION (pfile, warn_trigraphs) = 2; CPP_OPTION (pfile, warn_endif_labels) = 1; CPP_OPTION (pfile, warn_deprecated) = 1; CPP_OPTION (pfile, warn_long_long) = !CPP_OPTION (pfile, c99); CPP_OPTION (pfile, dollars_in_ident) = 1; CPP_OPTION (pfile, warn_dollars) = 1; /* Default CPP arithmetic to something sensible for the host for the benefit of dumb users like fix-header. */ CPP_OPTION (pfile, precision) = CHAR_BIT * sizeof (long); CPP_OPTION (pfile, char_precision) = CHAR_BIT; CPP_OPTION (pfile, wchar_precision) = CHAR_BIT * sizeof (int); CPP_OPTION (pfile, int_precision) = CHAR_BIT * sizeof (int); CPP_OPTION (pfile, unsigned_char) = 0; CPP_OPTION (pfile, unsigned_wchar) = 1; CPP_OPTION (pfile, bytes_big_endian) = 1; /* does not matter */ /* Default to locale/UTF-8. */ CPP_OPTION (pfile, narrow_charset) = _cpp_default_encoding (); CPP_OPTION (pfile, wide_charset) = 0; CPP_OPTION (pfile, input_charset) = _cpp_default_encoding (); /* A fake empty "directory" used as the starting point for files looked up without a search path. Name cannot be '/' because we don't want to prepend anything at all to filenames using it. All other entries are correct zero-initialized. */ pfile->no_search_path.name = (char *) ""; /* Initialize the line map. Start at logical line 1, so we can use a line number of zero for special states. */ linemap_init (&pfile->line_maps); pfile->line = 1; /* Initialize lexer state. */ pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments); /* Set up static tokens. */ pfile->avoid_paste.type = CPP_PADDING; pfile->avoid_paste.val.source = NULL; pfile->eof.type = CPP_EOF; pfile->eof.flags = 0; /* Create a token buffer for the lexer. */ _cpp_init_tokenrun (&pfile->base_run, 250); pfile->cur_run = &pfile->base_run; pfile->cur_token = pfile->base_run.base; /* Initialize the base context. */ pfile->context = &pfile->base_context; pfile->base_context.macro = 0; pfile->base_context.prev = pfile->base_context.next = 0; /* Aligned and unaligned storage. */ pfile->a_buff = _cpp_get_buff (pfile, 0); pfile->u_buff = _cpp_get_buff (pfile, 0); /* The expression parser stack. */ _cpp_expand_op_stack (pfile); /* Initialize the buffer obstack. */ _obstack_begin (&pfile->buffer_ob, 0, 0, (void *(*) (long)) xmalloc, (void (*) (void *)) free); _cpp_init_files (pfile); _cpp_init_hashtable (pfile, table); return pfile; }