diff options
Diffstat (limited to 'libcpp/files.cc')
-rw-r--r-- | libcpp/files.cc | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/libcpp/files.cc b/libcpp/files.cc index 8f9a5a4..fbbd59e 100644 --- a/libcpp/files.cc +++ b/libcpp/files.cc @@ -1239,15 +1239,19 @@ finish_embed (cpp_reader *pfile, _cpp_file *file, if (params->limit < limit) limit = params->limit; - /* For sizes larger than say 64 bytes, this is just a temporary - solution, we should emit a single new token which the FEs will - handle as an optimization. */ + size_t embed_tokens = 0; + if (!CPP_OPTION (pfile, cplusplus) + && CPP_OPTION (pfile, lang) != CLK_ASM + && limit >= 64) + embed_tokens = ((limit - 2) / INT_MAX) + (((limit - 2) % INT_MAX) != 0); + size_t max = INTTYPE_MAXIMUM (size_t) / sizeof (cpp_token); - if (limit > max / 2 + if ((embed_tokens ? (embed_tokens > (max - 3) / 2) : (limit > max / 2)) || (limit ? (params->prefix.count > max || params->suffix.count > max - || (limit * 2 - 1 + params->prefix.count + || ((embed_tokens ? embed_tokens * 2 + 3 : limit * 2 - 1) + + params->prefix.count + params->suffix.count > max)) : params->if_empty.count > max)) { @@ -1281,13 +1285,16 @@ finish_embed (cpp_reader *pfile, _cpp_file *file, "%s is too large", file->path); return 0; } + if (embed_tokens && i == 0) + i = limit - 2; } uchar *s = len ? _cpp_unaligned_alloc (pfile, len) : NULL; _cpp_buff *tok_buff = NULL; cpp_token *tok = &pfile->directive_result, *toks = tok; size_t count = 0; if (limit) - count = (params->prefix.count + limit * 2 - 1 + count = (params->prefix.count + + (embed_tokens ? embed_tokens * 2 + 3 : limit * 2 - 1) + params->suffix.count) - 1; else if (params->if_empty.count) count = params->if_empty.count - 1; @@ -1339,6 +1346,34 @@ finish_embed (cpp_reader *pfile, _cpp_file *file, tok->flags = NO_EXPAND; tok++; } + if (i == 0 && embed_tokens) + { + ++i; + for (size_t j = 0; j < embed_tokens; ++j) + { + tok->src_loc = params->loc; + tok->type = CPP_EMBED; + tok->flags = NO_EXPAND; + tok->val.str.text = &buffer[i]; + tok->val.str.len + = limit - 1 - i > INT_MAX ? INT_MAX : limit - 1 - i; + i += tok->val.str.len; + if (tok->val.str.len < 32 && j) + { + /* Avoid CPP_EMBED with a fewer than 32 bytes, shrink the + previous CPP_EMBED by 64 and grow this one by 64. */ + tok[-2].val.str.len -= 64; + tok->val.str.text -= 64; + tok->val.str.len += 64; + } + tok++; + tok->src_loc = params->loc; + tok->type = CPP_COMMA; + tok->flags = NO_EXPAND; + tok++; + } + --i; + } } if (limit && params->suffix.count) { |