diff options
author | Tom Tromey <tromey@redhat.com> | 2009-03-20 23:04:40 +0000 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2009-03-20 23:04:40 +0000 |
commit | 6c7a06a3facfa3f71606655871d0617d3cad80d9 (patch) | |
tree | 34aa9f54c4d9d5748c654b09f2992a92e217f6cd /gdb/c-exp.y | |
parent | cb249c71f6bfb565578d4258eaab9144a45716fe (diff) | |
download | gdb-6c7a06a3facfa3f71606655871d0617d3cad80d9.zip gdb-6c7a06a3facfa3f71606655871d0617d3cad80d9.tar.gz gdb-6c7a06a3facfa3f71606655871d0617d3cad80d9.tar.bz2 |
gdb:
2009-03-19 Tom Tromey <tromey@redhat.com>
Julian Brown <julian@codesourcery.com>
PR i18n/7220, PR i18n/7821, PR exp/8815, PR exp/9103,
PR i18n/9401, PR exp/9613:
* NEWS: Update
* value.h (value_typed_string): Declare.
(val_print_string): Update.
* valprint.h (print_char_chars): Update.
* valprint.c (print_char_chars): Add type argument. Update.
(val_print_string): Likewise.
* valops.c (value_typed_string): New function.
* utils.c (host_char_to_target): New function.
(parse_escape): Use host_char_to_target, host_hex_value. Update.
Remove '^' case.
(no_control_char_error): Remove.
* typeprint.c (print_type_scalar): Update.
* scm-valprint.c (scm_scmval_print): Update.
* scm-lang.h (scm_printchar, scm_printstr): Update.
* scm-lang.c (scm_printchar): Add type argument.
(scm_printstr): Likewise.
* printcmd.c (print_formatted): Update.
(print_scalar_formatted): Update.
(printf_command) <wide_string_arg, wide_char_arg>: New constants.
Handle '%lc' and '%ls'.
* parser-defs.h (struct typed_stoken): New type.
(struct stoken_vector): Likewise.
(write_exp_string_vector): Declare.
* parse.c (write_exp_string_vector): New function.
* p-valprint.c (pascal_val_print): Update.
* p-lang.h (is_pascal_string_type, pascal_printchar,
pascal_printstr): Update.
* p-lang.c (is_pascal_string_type): Remove 'char_size' argument.
Add 'char_type' argument.
(pascal_emit_char): Add type argument.
(pascal_printchar): Likewise.
(pascal_printstr): Likewise.
* objc-lang.c (objc_emit_char): Add type argument.
(objc_printchar): Likewise.
(objc_printstr): Likewise.
* macroexp.c (get_character_constant): Handle unicode characters.
Use c_parse_escape.
(get_string_literal): Handle unicode strings. Use
c_parse_escape.
* m2-valprint.c (print_unpacked_pointer): Update.
(m2_print_array_contents): Update.
(m2_val_print): Update.
* m2-lang.c (m2_emit_char): Add type argument.
(m2_printchar): Likewise.
(m2_printstr): Likewise.
* language.h (struct language_defn) <la_printchar>: Add type
argument.
<la_printstr, la_emitchar>: Likewise.
(LA_PRINT_CHAR): Likewise.
(LA_PRINT_STRING): Likewise.
(LA_EMIT_CHAR): Likewise.
* language.c (unk_lang_emit_char): Add type argument.
(unk_lang_printchar): Likewise.
(unk_lang_printstr): Likewise.
* jv-valprint.c (java_val_print): Update.
* jv-lang.c (java_emit_char): Add type argument.
* f-valprint.c (f_val_print): Update.
* f-lang.c (f_emit_char): Add type argument.
(f_printchar): Likewise.
(f_printstr): Likewise.
* expprint.c (print_subexp_standard): Update.
* charset.h (target_wide_charset): Declare.
(c_target_char_has_backslash_escape, c_parse_backslash,
host_char_print_literally, host_char_to_target,
target_char_to_host, target_char_to_control_char): Remove.
(enum transliterations): New type.
(convert_between_encodings): Declare.
(HOST_ESCAPE_CHAR): New define.
(host_letter_to_control_character, host_hex_value): Declare.
(enum wchar_iterate_result): New enum.
(struct wchar_iterator): Declare.
(make_wchar_iterator, make_cleanup_wchar_iterator, wchar_iterator,
wchar_push_back): Declare.
* charset-list.h: New file.
* c-valprint.c (textual_name): New function.
(textual_element_type): Handle wide character types.
(c_val_print): Pass original type to textual_element_type. Handle
wide character types.
(c_value_print): Use textual_element_type. Pass original type of
value to val_print.
* c-lang.h (enum c_string_type): New type.
(c_printchar, c_printstr): Update.
* c-lang.c (classify_type): New function.
(print_wchar): Likewise.
(c_emit_char): Add type argument. Handle wide characters.
(c_printchar): Likewise.
(c_printstr): Add type argument. Handle wide and multibyte
character sets.
(convert_ucn): New function.
(emit_numeric_character): Likewise.
(convert_octal): Likewise.
(convert_hex): Likewise.
(ADVANCE): New macro.
(convert_escape): New function.
(parse_one_string): Likewise.
(evaluate_subexp_c): Likewise.
(exp_descriptor_c): New global.
(c_language_defn): Use exp_descriptor_c.
(cplus_language_defn): Likewise.
(asm_language_defn): Likewise.
(minimal_language_defn): Likewise.
(charset_for_string_type): New function.
* c-exp.y (%union): Add 'svec' and 'tsval'.
(CHAR): New token.
(exp): Add CHAR production.
(string_exp): Rewrite.
(exp) <string_exp>: Rewrite.
(tempbuf): Now global.
(tempbuf_init): New global.
(parse_string_or_char): New function.
(yylex) <tempbuf>: Now global.
<tokptr, tempbufindex, tempbufsize, token_string, class_prefix>:
Remove.
Handle 'u', 'U', and 'L' prefixes. Call parse_string_or_char.
(c_parse_escape): New function.
* auxv.c (fprint_target_auxv): Update.
* ada-valprint.c (ada_emit_char): Add type argument.
(ada_printchar): Likewise.
(ada_print_scalar): Update.
(printstr): Add type argument. Update calls to ada_emit_char.
(ada_printstr): Add type argument.
(ada_val_print_array): Update.
(ada_val_print_1): Likewise.
* ada-lang.c (emit_char): Add type argument.
* ada-lang.h (ada_emit_char, ada_printchar, ada_printstr): Add
type arguments.
* gdb_locale.h: Include langinfo.h.
* charset.c (_initialize_charset): Set default host charset from
the locale. Don't register charsets. Add target-wide-charset
commands. Call find_charset_names.
(struct charset, struct translation): Remove.
(GDB_DEFAULT_HOST_CHARSET): Remove.
(GDB_DEFAULT_TARGET_WIDE_CHARSET): New define.
(target_wide_charset_name): New global.
(show_host_charset_name): Handle "auto".
(show_target_wide_charset_name): New function.
(host_charset_enum, target_charset_enum): Remove.
(charset_enum): New global.
(all_charsets, register_charset, lookup_charset, all_translations,
register_translation, lookup_translation): Remove.
(simple_charset, ascii_print_literally, ascii_to_control): Remove.
(iso_8859_print_literally, iso_8859_to_control,
iso_8859_family_charset): Remove.
(ebcdic_print_literally, ebcdic_to_control,
ebcdic_family_charset): Remove.
(struct cached_iconv, check_iconv_cache, cached_iconv_convert,
register_iconv_charsets): Remove.
(target_wide_charset_be_name, target_wide_charset_le_name): New
globals.
(identity_either_char_to_other): Remove.
(set_be_le_names, validate): New functions.
(backslashable, backslashed, represented): Remove.
(default_c_target_char_has_backslash_escape): Remove.
(default_c_parse_backslash, iconv_convert): Remove.
(ascii_to_iso_8859_1_table, ascii_to_ebcdic_us_table,
ascii_to_ibm1047_table, iso_8859_1_to_ascii_table,
iso_8859_1_to_ebcdic_us_table, iso_8859_1_to_ibm1047_table,
ebcdic_us_to_ascii_table, ebcdic_us_to_iso_8859_1_table,
ebcdic_us_to_ibm1047_table, ibm1047_to_ascii_table,
ibm1047_to_iso_8859_1_table, ibm1047_to_ebcdic_us_table): Remove.
(table_convert_char, table_translation, simple_table_translation):
Remove.
(current_host_charset, current_target_charset,
c_target_char_has_backslash_escape_func,
c_target_char_has_backslash_escape_baton): Remove.
(c_parse_backslash_func, c_parse_backslash_baton): Remove.
(host_char_to_target_func, host_char_to_target_baton): Remove.
(target_char_to_host_func, target_char_to_host_baton): Remove.
(cached_iconv_host_to_target, cached_iconv_target_to_host):
Remove.
(lookup_charset_or_error, check_valid_host_charset): Remove.
(set_host_and_target_charsets): Remove.
(set_host_charset, set_target_charset): Remove.
(set_host_charset_sfunc, set_target_charset_sfunc): Rewrite.
(set_target_wide_charset_sfunc): New function.
(show_charset): Print target wide character set.
(host_charset, target_charset): Rewrite.
(target_wide_charset): New function.
(c_target_char_has_backslash_escape): Remove.
(c_parse_backslash): Remove.
(host_letter_to_control_character): New function.
(host_char_print_literally): Remove.
(host_hex_value): New function.
(target_char_to_control_char): Remove.
(cleanup_iconv): New function.
(convert_between_encodings): New function.
(target_char_to_host): Remove.
(struct wchar_iterator): Define.
(make_wchar_iterator, make_cleanup_wchar_iterator, wchar_iterator,
wchar_push_back): New functions.
(do_cleanup_iterator): New function.
(char_ptr): New typedef.
(charsets): New global.
(add_one, find_charset_names): New functions.
(default_charset_names): New global.
(auto_host_charset_name): Likewise.
* aclocal.m4, config.in, configure: Rebuild.
* configure.ac: Call AM_LANGINFO_CODESET.
(GDB_DEFAULT_HOST_CHARSET): Default to UTF-8.
(AM_ICONV): Invoke earlier.
* acinclude.m4: Include codeset.m4. Subst LIBICONV_INCLUDE and
LIBICONV_LIBDIR. Check for libiconv in build tree.
* Makefile.in (LIBICONV_LIBDIR, LIBICONV_INCLUDE): New macros.
(INTERNAL_CFLAGS_BASE): Add LIBICONV_INCLUDE.
(INTERNAL_LDFLAGS): Add LIBICONV_LIBDIR.
* gdb_obstack.h (obstack_grow_wstr): New define.
* gdb_wchar.h: New file.
* defs.h: Include it.
gdb/testsuite:
* gdb.base/store.exp: Update for change to escape output.
* gdb.base/callfuncs.exp (fetch_all_registers): Update for change
to escape output.
* gdb.base/pointers.exp: Update for change to escape output.
* gdb.base/long_long.exp (gdb_test_long_long): Update for change
to escape output.
* gdb.base/constvars.exp (do_constvar_tests): Update for change to
escape output.
* gdb.base/call-rt-st.exp (print_struct_call): Update for change
to escape output.
* gdb.cp/ref-types.exp (gdb_start_again): Update for change to
escape output.
* gdb.base/setvar.exp: Update for change to escape output.
* lib/gdb.exp (default_gdb_start): Set LC_CTYPE to C.
* gdb.base/printcmds.exp (test_print_all_chars): Update for change
to escape output.
(test_print_string_constants): Likewise.
* gdb.base/charset.exp (valid_host_charset): Check size of
wchar_t. Handle UCS-2 and UCS-4. Add tests for wide and unicode
cases. Handle "auto"-related output.
* gdb.base/charset.c (char16_t, char32_t): New typedefs.
(uvar, Uvar): New globals.
gdb/doc:
* gdb.texinfo (Character Sets): Remove obsolete text. Document
set target-wide-charset.
(Requirements): Mention iconv.
Diffstat (limited to 'gdb/c-exp.y')
-rw-r--r-- | gdb/c-exp.y | 477 |
1 files changed, 340 insertions, 137 deletions
diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 04911ec..92d6c21 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -141,6 +141,7 @@ void yyerror (char *); struct symbol *sym; struct type *tval; struct stoken sval; + struct typed_stoken tsval; struct ttype tsym; struct symtoken ssym; int voidval; @@ -148,6 +149,7 @@ void yyerror (char *); enum exp_opcode opcode; struct internalvar *ivar; + struct stoken_vector svec; struct type **tvec; int *ivec; } @@ -180,11 +182,13 @@ static int parse_number (char *, int, int, YYSTYPE *); Contexts where this distinction is not important can use the nonterminal "name", which matches either NAME or TYPENAME. */ -%token <sval> STRING +%token <tsval> STRING +%token <tsval> CHAR %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */ %token <voidval> COMPLETE %token <tsym> TYPENAME -%type <sval> name string_exp +%type <sval> name +%type <svec> string_exp %type <ssym> name_not_typename %type <tsym> typename @@ -522,6 +526,15 @@ exp : INT write_exp_elt_opcode (OP_LONG); } ; +exp : CHAR + { + struct stoken_vector vec; + vec.len = 1; + vec.tokens = &$1; + write_exp_string_vector ($1.type, &vec); + } + ; + exp : NAME_OR_INT { YYSTYPE val; parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val); @@ -570,48 +583,64 @@ string_exp: string. Note that we follow the NUL-termination convention of the lexer. */ - $$.length = $1.length; - $$.ptr = malloc ($1.length + 1); - memcpy ($$.ptr, $1.ptr, $1.length + 1); + struct typed_stoken *vec = XNEW (struct typed_stoken); + $$.len = 1; + $$.tokens = vec; + + vec->type = $1.type; + vec->length = $1.length; + vec->ptr = malloc ($1.length + 1); + memcpy (vec->ptr, $1.ptr, $1.length + 1); } | string_exp STRING { /* Note that we NUL-terminate here, but just for convenience. */ - struct stoken t; - t.length = $1.length + $2.length; - t.ptr = malloc (t.length + 1); - memcpy (t.ptr, $1.ptr, $1.length); - memcpy (t.ptr + $1.length, $2.ptr, $2.length + 1); - free ($1.ptr); - $$ = t; + char *p; + ++$$.len; + $$.tokens = realloc ($$.tokens, + $$.len * sizeof (struct typed_stoken)); + + p = malloc ($2.length + 1); + memcpy (p, $2.ptr, $2.length + 1); + + $$.tokens[$$.len - 1].type = $2.type; + $$.tokens[$$.len - 1].length = $2.length; + $$.tokens[$$.len - 1].ptr = p; } ; exp : string_exp - { /* C strings are converted into array constants with - an explicit null byte added at the end. Thus - the array upper bound is the string length. - There is no such thing in C as a completely empty - string. */ - char *sp = $1.ptr; int count = $1.length; - while (count-- > 0) + { + int i; + enum c_string_type type = C_STRING; + + for (i = 0; i < $1.len; ++i) { - write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (parse_type->builtin_char); - write_exp_elt_longcst ((LONGEST)(*sp++)); - write_exp_elt_opcode (OP_LONG); + switch ($1.tokens[i].type) + { + case C_STRING: + break; + case C_WIDE_STRING: + case C_STRING_16: + case C_STRING_32: + if (type != C_STRING + && type != $1.tokens[i].type) + error ("Undefined string concatenation."); + type = $1.tokens[i].type; + break; + default: + /* internal error */ + internal_error (__FILE__, __LINE__, + "unrecognized type in string concatenation"); + } } - write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (parse_type->builtin_char); - write_exp_elt_longcst ((LONGEST)'\0'); - write_exp_elt_opcode (OP_LONG); - write_exp_elt_opcode (OP_ARRAY); - write_exp_elt_longcst ((LONGEST) 0); - write_exp_elt_longcst ((LONGEST) ($1.length)); - write_exp_elt_opcode (OP_ARRAY); - free ($1.ptr); + + write_exp_string_vector (type, &$1); + for (i = 0; i < $1.len; ++i) + free ($1.tokens[i].ptr); + free ($1.tokens); } ; @@ -1359,6 +1388,263 @@ parse_number (p, len, parsed_float, putithere) return INT; } +/* Temporary obstack used for holding strings. */ +static struct obstack tempbuf; +static int tempbuf_init; + +/* Parse a C escape sequence. The initial backslash of the sequence + is at (*PTR)[-1]. *PTR will be updated to point to just after the + last character of the sequence. If OUTPUT is not NULL, the + translated form of the escape sequence will be written there. If + OUTPUT is NULL, no output is written and the call will only affect + *PTR. If an escape sequence is expressed in target bytes, then the + entire sequence will simply be copied to OUTPUT. Return 1 if any + character was emitted, 0 otherwise. */ + +int +c_parse_escape (char **ptr, struct obstack *output) +{ + char *tokptr = *ptr; + int result = 1; + + /* Some escape sequences undergo character set conversion. Those we + translate here. */ + switch (*tokptr) + { + /* Hex escapes do not undergo character set conversion, so keep + the escape sequence for later. */ + case 'x': + if (output) + obstack_grow_str (output, "\\x"); + ++tokptr; + if (!isxdigit (*tokptr)) + error (_("\\x escape without a following hex digit")); + while (isxdigit (*tokptr)) + { + if (output) + obstack_1grow (output, *tokptr); + ++tokptr; + } + break; + + /* Octal escapes do not undergo character set conversion, so + keep the escape sequence for later. */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + if (output) + obstack_grow_str (output, "\\"); + while (isdigit (*tokptr) && *tokptr != '8' && *tokptr != '9') + { + if (output) + obstack_1grow (output, *tokptr); + ++tokptr; + } + break; + + /* We handle UCNs later. We could handle them here, but that + would mean a spurious error in the case where the UCN could + be converted to the target charset but not the host + charset. */ + case 'u': + case 'U': + { + char c = *tokptr; + int i, len = c == 'U' ? 8 : 4; + if (output) + { + obstack_1grow (output, '\\'); + obstack_1grow (output, *tokptr); + } + ++tokptr; + if (!isxdigit (*tokptr)) + error (_("\\%c escape without a following hex digit"), c); + for (i = 0; i < len && isxdigit (*tokptr); ++i) + { + if (output) + obstack_1grow (output, *tokptr); + ++tokptr; + } + } + break; + + /* We must pass backslash through so that it does not + cause quoting during the second expansion. */ + case '\\': + if (output) + obstack_grow_str (output, "\\\\"); + ++tokptr; + break; + + /* Escapes which undergo conversion. */ + case 'a': + if (output) + obstack_1grow (output, '\a'); + ++tokptr; + break; + case 'b': + if (output) + obstack_1grow (output, '\b'); + ++tokptr; + break; + case 'f': + if (output) + obstack_1grow (output, '\f'); + ++tokptr; + break; + case 'n': + if (output) + obstack_1grow (output, '\n'); + ++tokptr; + break; + case 'r': + if (output) + obstack_1grow (output, '\r'); + ++tokptr; + break; + case 't': + if (output) + obstack_1grow (output, '\t'); + ++tokptr; + break; + case 'v': + if (output) + obstack_1grow (output, '\v'); + ++tokptr; + break; + + /* GCC extension. */ + case 'e': + if (output) + obstack_1grow (output, HOST_ESCAPE_CHAR); + ++tokptr; + break; + + /* Backslash-newline expands to nothing at all. */ + case '\n': + ++tokptr; + result = 0; + break; + + /* A few escapes just expand to the character itself. */ + case '\'': + case '\"': + case '?': + /* GCC extensions. */ + case '(': + case '{': + case '[': + case '%': + /* Unrecognized escapes turn into the character itself. */ + default: + if (output) + obstack_1grow (output, *tokptr); + ++tokptr; + break; + } + *ptr = tokptr; + return result; +} + +/* Parse a string or character literal from TOKPTR. The string or + character may be wide or unicode. *OUTPTR is set to just after the + end of the literal in the input string. The resulting token is + stored in VALUE. This returns a token value, either STRING or + CHAR, depending on what was parsed. *HOST_CHARS is set to the + number of host characters in the literal. */ +static int +parse_string_or_char (char *tokptr, char **outptr, struct typed_stoken *value, + int *host_chars) +{ + int quote, i; + enum c_string_type type; + + /* Build the gdb internal form of the input string in tempbuf. Note + that the buffer is null byte terminated *only* for the + convenience of debugging gdb itself and printing the buffer + contents when the buffer contains no embedded nulls. Gdb does + not depend upon the buffer being null byte terminated, it uses + the length string instead. This allows gdb to handle C strings + (as well as strings in other languages) with embedded null + bytes */ + + if (!tempbuf_init) + tempbuf_init = 1; + else + obstack_free (&tempbuf, NULL); + obstack_init (&tempbuf); + + /* Record the string type. */ + if (*tokptr == 'L') + { + type = C_WIDE_STRING; + ++tokptr; + } + else if (*tokptr == 'u') + { + type = C_STRING_16; + ++tokptr; + } + else if (*tokptr == 'U') + { + type = C_STRING_32; + ++tokptr; + } + else + type = C_STRING; + + /* Skip the quote. */ + quote = *tokptr; + if (quote == '\'') + type |= C_CHAR; + ++tokptr; + + *host_chars = 0; + + while (*tokptr) + { + char c = *tokptr; + if (c == '\\') + { + ++tokptr; + *host_chars += c_parse_escape (&tokptr, &tempbuf); + } + else if (c == quote) + break; + else + { + obstack_1grow (&tempbuf, c); + ++tokptr; + /* FIXME: this does the wrong thing with multi-byte host + characters. We could use mbrlen here, but that would + make "set host-charset" a bit less useful. */ + ++*host_chars; + } + } + + if (*tokptr != quote) + { + if (quote == '"') + error ("Unterminated string in expression."); + else + error ("Unmatched single quote."); + } + ++tokptr; + + value->type = type; + value->ptr = obstack_base (&tempbuf); + value->length = obstack_object_size (&tempbuf); + + *outptr = tokptr; + + return quote == '"' ? STRING : CHAR; +} + struct token { char *operator; @@ -1528,12 +1814,6 @@ yylex () int namelen; unsigned int i; char *tokstart; - char *tokptr; - int tempbufindex; - static char *tempbuf; - static int tempbufsize; - char * token_string = NULL; - int class_prefix = 0; int saw_structop = last_was_structop; char *copy; @@ -1605,46 +1885,6 @@ yylex () lexptr++; goto retry; - case '\'': - /* We either have a character constant ('0' or '\177' for example) - or we have a quoted symbol reference ('foo(int,int)' in C++ - for example). */ - lexptr++; - c = *lexptr++; - if (c == '\\') - c = parse_escape (&lexptr); - else if (c == '\'') - error ("Empty character constant."); - else if (! host_char_to_target (c, &c)) - { - int toklen = lexptr - tokstart + 1; - char *tok = alloca (toklen + 1); - memcpy (tok, tokstart, toklen); - tok[toklen] = '\0'; - error ("There is no character corresponding to %s in the target " - "character set `%s'.", tok, target_charset ()); - } - - yylval.typed_val_int.val = c; - yylval.typed_val_int.type = parse_type->builtin_char; - - c = *lexptr++; - if (c != '\'') - { - namelen = skip_quoted (tokstart) - tokstart; - if (namelen > 2) - { - lexptr = tokstart + namelen; - if (lexptr[-1] != '\'') - error ("Unmatched single quote."); - namelen -= 2; - tokstart++; - goto tryname; - } - error ("Invalid character constant."); - } - return INT; - case '(': paren_depth++; lexptr++; @@ -1762,70 +2002,33 @@ yylex () lexptr++; return c; + case 'L': + case 'u': + case 'U': + if (tokstart[1] != '"' && tokstart[1] != '\'') + break; + /* Fall through. */ + case '\'': case '"': - - /* Build the gdb internal form of the input string in tempbuf, - translating any standard C escape forms seen. Note that the - buffer is null byte terminated *only* for the convenience of - debugging gdb itself and printing the buffer contents when - the buffer contains no embedded nulls. Gdb does not depend - upon the buffer being null byte terminated, it uses the length - string instead. This allows gdb to handle C strings (as well - as strings in other languages) with embedded null bytes */ - - tokptr = ++tokstart; - tempbufindex = 0; - - do { - char *char_start_pos = tokptr; - - /* Grow the static temp buffer if necessary, including allocating - the first one on demand. */ - if (tempbufindex + 1 >= tempbufsize) - { - tempbuf = (char *) realloc (tempbuf, tempbufsize += 64); - } - switch (*tokptr) + { + int host_len; + int result = parse_string_or_char (tokstart, &lexptr, &yylval.tsval, + &host_len); + if (result == CHAR) { - case '\0': - case '"': - /* Do nothing, loop will terminate. */ - break; - case '\\': - tokptr++; - c = parse_escape (&tokptr); - if (c == -1) + if (host_len == 0) + error ("Empty character constant."); + else if (host_len > 2 && c == '\'') { - continue; + ++tokstart; + namelen = lexptr - tokstart - 1; + goto tryname; } - tempbuf[tempbufindex++] = c; - break; - default: - c = *tokptr++; - if (! host_char_to_target (c, &c)) - { - int len = tokptr - char_start_pos; - char *copy = alloca (len + 1); - memcpy (copy, char_start_pos, len); - copy[len] = '\0'; - - error ("There is no character corresponding to `%s' " - "in the target character set `%s'.", - copy, target_charset ()); - } - tempbuf[tempbufindex++] = c; - break; + else if (host_len > 1) + error ("Invalid character constant."); } - } while ((*tokptr != '"') && (*tokptr != '\0')); - if (*tokptr++ != '"') - { - error ("Unterminated string in expression."); - } - tempbuf[tempbufindex] = '\0'; /* See note above */ - yylval.sval.ptr = tempbuf; - yylval.sval.length = tempbufindex; - lexptr = tokptr; - return (STRING); + return result; + } } if (!(c == '_' || c == '$' |