+/**
+ * Concatenate two strings.
+ */
+string_t concat_strings(const string_t *const s1, const string_t *const s2)
+{
+ const size_t len1 = s1->size - 1;
+ const size_t len2 = s2->size - 1;
+
+ char *const concat = obstack_alloc(&symbol_obstack, len1 + len2 + 1);
+ memcpy(concat, s1->begin, len1);
+ memcpy(concat + len1, s2->begin, len2 + 1);
+
+ return identify_string(concat, len1 + len2 + 1);
+}
+
+string_t make_string(const char *string)
+{
+ size_t len = strlen(string) + 1;
+ char *const space = obstack_alloc(&symbol_obstack, len);
+ memcpy(space, string, len);
+
+ return identify_string(space, len);
+}
+
+/**
+ * Parse a string literal and set lexer_token.
+ */
+static void parse_string_literal(void)
+{
+ eat('"');
+
+ while (true) {
+ switch (c) {
+ case '\\': {
+ utf32 const tc = parse_escape_sequence();
+ if (tc >= 0x100) {
+ warningf(WARN_OTHER, &lexer_pos, "escape sequence out of range");
+ }
+ obstack_1grow(&symbol_obstack, tc);