+ const unsigned char *str = token->val.str.text;
+ const unsigned char *limit = str + token->val.str.len;
+ unsigned int chars_seen = 0;
+ size_t width, max_chars;
+ cppchar_t c, mask, result = 0;
+ bool unsigned_p;
+
+#ifdef MULTIBYTE_CHARS
+ (void) local_mbtowc (NULL, NULL, 0);
+#endif
+
+ /* Width in bits. */
+ if (token->type == CPP_CHAR)
+ {
+ width = CPP_OPTION (pfile, char_precision);
+ max_chars = CPP_OPTION (pfile, int_precision) / width;
+ unsigned_p = CPP_OPTION (pfile, unsigned_char);
+ }
+ else
+ {
+ width = CPP_OPTION (pfile, wchar_precision);
+ max_chars = 1;
+ unsigned_p = CPP_OPTION (pfile, unsigned_wchar);
+ }
+
+ if (width < BITS_PER_CPPCHAR_T)
+ mask = ((cppchar_t) 1 << width) - 1;
+ else
+ mask = ~0;
+
+ while (str < limit)
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int char_len;
+
+ char_len = local_mbtowc (&wc, str, limit - str);
+ if (char_len == -1)
+ {
+ cpp_error (pfile, DL_WARNING,
+ "ignoring invalid multibyte character");
+ c = *str++;
+ }
+ else
+ {
+ str += char_len;
+ c = wc;
+ }
+#else
+ c = *str++;
+#endif
+
+ if (c == '\\')
+ c = cpp_parse_escape (pfile, &str, limit, token->type == CPP_WCHAR);
+
+#ifdef MAP_CHARACTER
+ if (ISPRINT (c))
+ c = MAP_CHARACTER (c);
+#endif
+
+ chars_seen++;
+
+ /* Truncate the character, scale the result and merge the two. */
+ c &= mask;
+ if (width < BITS_PER_CPPCHAR_T)
+ result = (result << width) | c;
+ else
+ result = c;
+ }
+
+ if (chars_seen == 0)
+ cpp_error (pfile, DL_ERROR, "empty character constant");
+ else if (chars_seen > 1)
+ {
+ /* Multichar charconsts are of type int and therefore signed. */
+ unsigned_p = 0;
+
+ if (chars_seen > max_chars)
+ {
+ chars_seen = max_chars;
+ cpp_error (pfile, DL_WARNING,
+ "character constant too long for its type");
+ }
+ else if (CPP_OPTION (pfile, warn_multichar))
+ cpp_error (pfile, DL_WARNING, "multi-character character constant");
+ }
+
+ /* Sign-extend or truncate the constant to cppchar_t. The value is
+ in WIDTH bits, but for multi-char charconsts it's value is the
+ full target type's width. */
+ if (chars_seen > 1)
+ width *= max_chars;
+ if (width < BITS_PER_CPPCHAR_T)
+ {
+ mask = ((cppchar_t) 1 << width) - 1;
+ if (unsigned_p || !(result & (1 << (width - 1))))
+ result &= mask;
+ else
+ result |= ~mask;
+ }
+
+ *pchars_seen = chars_seen;
+ *unsignedp = unsigned_p;
+ return result;
+}
+
+/* Memory buffers. Changing these three constants can have a dramatic
+ effect on performance. The values here are reasonable defaults,
+ but might be tuned. If you adjust them, be sure to test across a
+ range of uses of cpplib, including heavy nested function-like macro
+ expansion. Also check the change in peak memory usage (NJAMD is a
+ good tool for this). */
+#define MIN_BUFF_SIZE 8000
+#define BUFF_SIZE_UPPER_BOUND(MIN_SIZE) (MIN_BUFF_SIZE + (MIN_SIZE) * 3 / 2)
+#define EXTENDED_BUFF_SIZE(BUFF, MIN_EXTRA) \
+ (MIN_EXTRA + ((BUFF)->limit - (BUFF)->cur) * 2)
+
+#if MIN_BUFF_SIZE > BUFF_SIZE_UPPER_BOUND (0)
+ #error BUFF_SIZE_UPPER_BOUND must be at least as large as MIN_BUFF_SIZE!
+#endif
+
+struct dummy
+{
+ char c;
+ union
+ {
+ double d;
+ int *p;
+ } u;
+};
+
+#define DEFAULT_ALIGNMENT (offsetof (struct dummy, u))
+#define CPP_ALIGN(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
+
+/* Create a new allocation buffer. Place the control block at the end
+ of the buffer, so that buffer overflows will cause immediate chaos. */
+static _cpp_buff *
+new_buff (len)
+ size_t len;
+{
+ _cpp_buff *result;