diff options
Diffstat (limited to 'macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c')
-rw-r--r-- | macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c | 140 |
1 files changed, 80 insertions, 60 deletions
diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c index 560e637f87..f97edbfd4e 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c @@ -1,4 +1,4 @@ -/* Copyright 2010-2019 Free Software Foundation, Inc. +/* Copyright 2010-2020 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,7 +24,7 @@ #include <errno.h> #include <sys/stat.h> -#include "tree_types.h" +#include "errors.h" #include "input.h" #include "text.h" #include "commands.h" @@ -34,8 +34,11 @@ enum input_type { IN_file, IN_text }; enum character_encoding { ce_latin1, ce_latin2, + ce_latin15, ce_utf8, - ce_shiftjis + ce_shiftjis, + ce_koi8r, + ce_koi8u }; typedef struct { @@ -49,12 +52,28 @@ typedef struct { into lines. */ } INPUT; -static char *input_encoding; +enum character_encoding input_encoding; void set_input_encoding (char *encoding) { - input_encoding = encoding; + if (!strcasecmp (encoding, "utf-8")) + input_encoding = ce_utf8; + else if (!strcmp (encoding, "iso-8859-1") + || !strcmp (encoding, "us-ascii")) + input_encoding = ce_latin1; + else if (!strcmp (encoding, "iso-8859-2")) + input_encoding = ce_latin2; + else if (!strcmp (encoding, "iso-8859-15")) + input_encoding = ce_latin15; + else if (!strcmp (encoding, "shift_jis")) + input_encoding = ce_shiftjis; + else if (!strcmp (encoding, "koi8-r")) + input_encoding = ce_koi8r; + else if (!strcmp (encoding, "koi8-u")) + input_encoding = ce_koi8u; + else + fprintf (stderr, "warning: unhandled encoding %s\n", encoding); } @@ -112,9 +131,13 @@ new_line (void) } -static iconv_t iconv_from_latin1 = (iconv_t) 0; +static iconv_t iconv_from_latin1; static iconv_t iconv_from_latin2; +static iconv_t iconv_from_latin15; static iconv_t iconv_from_shiftjis; +static iconv_t iconv_from_koi8u; +static iconv_t iconv_from_koi8r; +static iconv_t iconv_validate_utf8; /* Run iconv using text buffer as output buffer. */ size_t @@ -141,70 +164,44 @@ text_buffer_iconv (TEXT *buf, iconv_t iconv_state, } - -/* Return conversion of S according to ENCODING. This function frees S. */ +/* Return conversion of S according to input_encoding. This function + frees S. */ static char * -convert_to_utf8 (char *s, char *encoding) +convert_to_utf8 (char *s) { - iconv_t our_iconv; + iconv_t our_iconv = (iconv_t) -1; static TEXT t; ICONV_CONST char *inptr; size_t bytes_left; size_t iconv_ret; enum character_encoding enc; /* Convert from @documentencoding to UTF-8. - It might be possible not to convert to UTF-8 and use an 8-bit encoding + It might be possible not to convert to UTF-8 and use an 8-bit encoding throughout, but then we'd have to not set the UTF-8 flag on the Perl strings in api.c. If multiple character encodings were used in a single file, then we'd have to keep track of which strings needed the UTF-8 flag and which didn't. */ - /* Could and check for malformed input: see - <http://savannah.gnu.org/bugs/?42896>. */ - + /* Initialize conversions for the first time. */ + if (iconv_validate_utf8 == (iconv_t) 0) + iconv_validate_utf8 = iconv_open ("UTF-8", "UTF-8"); if (iconv_from_latin1 == (iconv_t) 0) - { - /* Initialize the conversion for the first time. */ - iconv_from_latin1 = iconv_open ("UTF-8", "ISO-8859-1"); - if (iconv_from_latin1 == (iconv_t) -1) - { - abort (); - - /* big trouble. if we do return it unconverted, we will have to - remember not to set the UTF-8 flags on the Perl strings, otherwise - Perl will choke. */ - return s; - } - } + iconv_from_latin1 = iconv_open ("UTF-8", "ISO-8859-1"); if (iconv_from_latin2 == (iconv_t) 0) - { - /* Initialize the conversion for the first time. */ - iconv_from_latin2 = iconv_open ("UTF-8", "ISO-8859-2"); - if (iconv_from_latin2 == (iconv_t) -1) - iconv_from_latin2 = iconv_from_latin1; - } + iconv_from_latin2 = iconv_open ("UTF-8", "ISO-8859-2"); + if (iconv_from_latin15 == (iconv_t) 0) + iconv_from_latin15 = iconv_open ("UTF-8", "ISO-8859-15"); if (iconv_from_shiftjis == (iconv_t) 0) - { - /* Initialize the conversion for the first time. */ - iconv_from_shiftjis = iconv_open ("UTF-8", "SHIFT-JIS"); - if (iconv_from_shiftjis == (iconv_t) -1) - iconv_from_shiftjis = iconv_from_latin1; - } - - enc = ce_latin1; - if (!encoding) - ; - else if (!strcmp (encoding, "utf-8")) - enc = ce_utf8; - else if (!strcmp (encoding, "iso-8859-2")) - enc = ce_latin2; - else if (!strcmp (encoding, "shift_jis")) - enc = ce_shiftjis; + iconv_from_shiftjis = iconv_open ("UTF-8", "SHIFT-JIS"); + if (iconv_from_koi8r == (iconv_t) 0) + iconv_from_koi8r = iconv_open ("UTF-8", "KOI8-R"); + if (iconv_from_koi8u == (iconv_t) 0) + iconv_from_koi8u = iconv_open ("UTF-8", "KOI8-U"); - switch (enc) + switch (input_encoding) { case ce_utf8: - return s; /* no conversion required. */ + our_iconv = iconv_validate_utf8; break; case ce_latin1: our_iconv = iconv_from_latin1; @@ -212,9 +209,26 @@ convert_to_utf8 (char *s, char *encoding) case ce_latin2: our_iconv = iconv_from_latin2; break; + case ce_latin15: + our_iconv = iconv_from_latin15; + break; case ce_shiftjis: our_iconv = iconv_from_shiftjis; break; + case ce_koi8r: + our_iconv = iconv_from_koi8r; + break; + case ce_koi8u: + our_iconv = iconv_from_koi8u; + break; + } + + if (our_iconv == (iconv_t) -1) + { + /* In case the converter couldn't be initialised. + Danger: this will cause problems if the input is not in UTF-8 as + the Perl strings that are created are flagged as being UTF-8. */ + return s; } t.end = 0; @@ -236,20 +250,25 @@ convert_to_utf8 (char *s, char *encoding) /* Success: all of input converted. */ break; + if (bytes_left == 0) + break; + switch (errno) { case E2BIG: text_alloc (&t, t.space + 20); break; + case EILSEQ: default: - abort (); + fprintf(stderr, "%s:%d: encoding error at byte 0x%2x\n", + line_nr.file_name, line_nr.line_nr, *(unsigned char *)inptr); + inptr++; bytes_left--; break; } } free (s); t.text[t.end] = '\0'; - //fprintf (stderr, "CONVERTED STRING IS <<%s>>", t.text); return strdup (t.text); } @@ -310,7 +329,7 @@ next_text (void) return new; break; - case IN_file: // 1911 + case IN_file: input_file = input_stack[input_number - 1].file; status = getline (&line, &n, input_file); if (status != -1) @@ -333,12 +352,12 @@ next_text (void) i->line_nr.line_nr++; line_nr = i->line_nr; - return convert_to_utf8 (line, input_encoding); + return convert_to_utf8 (line); } free (line); line = 0; break; default: - abort (); + fatal ("unknown input source type"); } /* Top input source failed. Pop it and try the next one. */ @@ -369,7 +388,7 @@ input_push (char *text, char *macro, char *filename, int line_number) input_space++; input_space *= 1.5; input_stack = realloc (input_stack, input_space * sizeof (INPUT)); if (!input_stack) - abort (); + fatal ("realloc failed"); } input_stack[input_number].type = IN_text; @@ -405,7 +424,7 @@ save_string (char *string) small_strings = realloc (small_strings, small_strings_space * sizeof (char *)); if (!small_strings) - abort (); + fatal ("realloc failed"); } small_strings[small_strings_num++] = ret; } @@ -501,6 +520,7 @@ add_include_directory (char *filename) filename[len - 1] = '\0'; } +/* Return value to be freed by caller. */ char * locate_include_file (char *filename) { @@ -519,7 +539,7 @@ locate_include_file (char *filename) { status = stat (filename, &dummy); if (status == 0) - return filename; + return strdup (filename); } else { @@ -550,7 +570,7 @@ input_push_file (char *filename) { input_stack = realloc (input_stack, (input_space += 5) * sizeof (INPUT)); if (!input_stack) - abort (); + fatal ("realloc failed"); } /* Strip off a leading directory path. */ |