"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/iconv.c" between
recode-3.7.11.tar.gz and recode-3.7.12.tar.gz

About: recode is a charset converter tool and library (fork of the original and now unmaintained GNU recode).

iconv.c  (recode-3.7.11):iconv.c  (recode-3.7.12)
/* Conversion of files between different charsets and surfaces. /* Conversion of files between different charsets and surfaces.
Copyright © 1999, 2000, 2001, 2008 Free Software Foundation, Inc. Copyright © 1999-2022 Free Software Foundation, Inc.
Contributed by François Pinard <pinard@iro.umontreal.ca>, 1999, Contributed by François Pinard <pinard@iro.umontreal.ca>, 1999,
and Bruno Haible <haible@clisp.cons.org>, 2000. and Bruno Haible <haible@clisp.cons.org>, 2000.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 3 of the as published by the Free Software Foundation; either version 3 of the
License, or (at your option) any later version. License, or (at your option) any later version.
This library is distributed in the hope that it will be This library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty useful, but WITHOUT ANY WARRANTY; without even the implied warranty
skipping to change at line 31 skipping to change at line 31
#include "config.h" #include "config.h"
#include "common.h" #include "common.h"
#include "decsteps.h" #include "decsteps.h"
#include <iconv.h> #include <iconv.h>
#include "iconvdecl.h" #include "iconvdecl.h"
/*--------------------------------------. /*--------------------------------------.
| Use `iconv' to handle a double step. | | Use `iconv' to handle a double step. |
`--------------------------------------*/ `--------------------------------------*/
static void
do_iconv (RECODE_OUTER outer,
iconv_t conversion,
char **input, size_t *input_left,
char **output, size_t *output_left,
int *saved_errno)
{
size_t converted = iconv (conversion, input, input_left, output, output_left);
if (converted == (size_t) -1 && !(errno == EILSEQ && outer->force))
*saved_errno = errno;
}
#define BUFFER_SIZE 2048 #define BUFFER_SIZE 2048
static bool static bool
wrapped_transform (iconv_t conversion, RECODE_SUBTASK subtask) wrapped_transform (iconv_t conversion, RECODE_SUBTASK subtask)
{ {
char output_buffer[BUFFER_SIZE]; char output_buffer[BUFFER_SIZE];
char input_buffer[BUFFER_SIZE]; char input_buffer[BUFFER_SIZE];
int input_char = get_byte (subtask); int input_char = get_byte (subtask);
char *cursor = input_buffer; char *cursor = input_buffer;
bool drain_first = false; bool drain_first = false;
while (true) while (true)
{ {
/* The output buffer is fully available at this point. */ /* The output buffer is fully available at this point. */
char *input = input_buffer; char *input = input_buffer;
char *output = output_buffer; char *output = output_buffer;
size_t input_left = 0; size_t input_left = 0;
size_t output_left = BUFFER_SIZE; size_t output_left = BUFFER_SIZE;
int saved_errno = 0; int saved_errno = 0;
size_t converted;
if (drain_first) if (drain_first)
{ {
/* Drain all accumulated partial state and emit output /* Drain all accumulated partial state and emit output
to return to the initial shift state. */ to return to the initial shift state. */
converted = iconv (conversion, NULL, NULL, &output, &output_left); do_iconv (subtask->task->request->outer,
if (converted == (size_t) -1) conversion,
saved_errno = errno; NULL, NULL,
&output, &output_left,
&saved_errno);
} }
if (saved_errno == 0) if (saved_errno == 0)
{ {
/* Continue filling the input buffer. */ /* Continue filling the input buffer. */
while (input_char != EOF && cursor < input_buffer + BUFFER_SIZE) while (input_char != EOF && cursor < input_buffer + BUFFER_SIZE)
{ {
*cursor++ = input_char; *cursor++ = input_char;
input_char = get_byte (subtask); input_char = get_byte (subtask);
} }
skipping to change at line 87 skipping to change at line 100
break; break;
drain_first = true; drain_first = true;
continue; continue;
} }
} }
else else
{ {
/* Convert accumulated input and add it to the output buffer. */ /* Convert accumulated input and add it to the output buffer. */
input = input_buffer; input = input_buffer;
input_left = cursor - input_buffer; input_left = cursor - input_buffer;
converted = iconv (conversion, do_iconv (subtask->task->request->outer,
&input, &input_left, conversion,
&output, &output_left); &input, &input_left,
if (converted == (size_t) -1) &output, &output_left,
saved_errno = errno; &saved_errno);
} }
} }
/* Send the converted result, so freeing the output buffer. */ /* Send the converted result, so freeing the output buffer. */
for (cursor = output_buffer; cursor < output; cursor++) for (cursor = output_buffer; cursor < output; cursor++)
put_byte (*cursor, subtask); put_byte (*cursor, subtask);
/* Act according to the outcome of the iconv call. */ /* Act according to the outcome of the iconv call. */
drain_first = false; drain_first = false;
skipping to change at line 137 skipping to change at line 150
if (check_converted != (size_t) -1) if (check_converted != (size_t) -1)
recode_error = RECODE_UNTRANSLATABLE; recode_error = RECODE_UNTRANSLATABLE;
free (check_output_buffer); free (check_output_buffer);
} }
iconv_close (check_conversion); iconv_close (check_conversion);
} }
/* Invalid or untranslatable input. Skip one byte. */ /* Invalid or untranslatable input. */
/* FIXME: We cannot tell how many bytes to skip for
untranslatable input. The likely result is that we'll
get an "invalid input" error on the next step. */
RETURN_IF_NOGO (recode_error, subtask); RETURN_IF_NOGO (recode_error, subtask);
assert (input_left > 0);
input++;
input_left--;
/* Why is draining required? */
drain_first = true;
} }
else if (saved_errno == EINVAL) else if (saved_errno == EINVAL)
{ {
if (input + input_left < input_buffer + BUFFER_SIZE if (input + input_left < input_buffer + BUFFER_SIZE
&& input_char == EOF) && input_char == EOF)
/* Incomplete multibyte sequence at end of input. */ /* Incomplete multibyte sequence at end of input. */
RETURN_IF_NOGO (RECODE_INVALID_INPUT, subtask); RETURN_IF_NOGO (RECODE_INVALID_INPUT, subtask);
} }
else else
{ {
skipping to change at line 177 skipping to change at line 182
SUBTASK_RETURN (subtask); SUBTASK_RETURN (subtask);
} }
static bool static bool
ends_with (const char *s, size_t s_len, const char *suff, size_t suff_len) ends_with (const char *s, size_t s_len, const char *suff, size_t suff_len)
{ {
return suff_len <= s_len && !memcmp (s + s_len - suff_len, suff, suff_len); return suff_len <= s_len && !memcmp (s + s_len - suff_len, suff, suff_len);
} }
static char * static char *
iconv_fix_options (const char *charset) iconv_fix_options (RECODE_OUTER outer, const char *charset)
{ {
size_t charset_len = strlen (charset); size_t charset_len = strlen (charset);
bool ignore = false, translit = false; bool translit = false;
do { if (ends_with (charset, charset_len, "-translit", strlen ("-translit")))
if (ends_with (charset, charset_len, "-translit", strlen ("-translit"))) {
{ translit = true;
translit = true; charset_len -= strlen ("-translit");
charset_len -= strlen ("-translit"); }
}
else if (ends_with (charset, charset_len, "-ignore", strlen ("-ignore")))
{
ignore = true;
charset_len -= strlen ("-ignore");
}
else
break;
} while (true);
char *result; char *result;
if (asprintf (&result, "%.*s%s%s", (int) charset_len, charset, if (asprintf (&result, "%.*s%s%s", (int) charset_len, charset,
translit ? "//TRANSLIT" : "", translit ? "//TRANSLIT" : "",
ignore ? "//IGNORE": "") outer->strict_mapping ? "//IGNORE": "")
== -1) == -1)
return NULL; return NULL;
return result; return result;
} }
bool bool
transform_with_iconv (RECODE_SUBTASK subtask) transform_with_iconv (RECODE_SUBTASK subtask)
{ {
RECODE_OUTER outer = subtask->task->request->outer;
RECODE_CONST_STEP step = subtask->step; RECODE_CONST_STEP step = subtask->step;
char *tocode = iconv_fix_options (step->after->iconv_name); char *tocode = iconv_fix_options (outer, step->after->iconv_name);
char *fromcode = iconv_fix_options (step->before->iconv_name); const char *fromcode = step->before->iconv_name;
iconv_t conversion = (iconv_t) -1; iconv_t conversion = (iconv_t) -1;
if (tocode && fromcode) if (tocode)
conversion = iconv_open (tocode, fromcode); conversion = iconv_open (tocode, fromcode);
if (conversion == (iconv_t) -1) if (conversion == (iconv_t) -1)
{ {
recode_if_nogo (RECODE_SYSTEM_ERROR, subtask); recode_if_nogo (RECODE_SYSTEM_ERROR, subtask);
free (fromcode);
free (tocode); free (tocode);
SUBTASK_RETURN (subtask); SUBTASK_RETURN (subtask);
} }
bool status = wrapped_transform (conversion, subtask); bool status = wrapped_transform (conversion, subtask);
iconv_close (conversion); iconv_close (conversion);
free (fromcode);
free (tocode); free (tocode);
return status; return status;
} }
/*------------------------------------------------------. /*------------------------------------------------------.
| Declare all character sets which `iconv' may handle. | | Declare all character sets which `iconv' may handle. |
`------------------------------------------------------*/ `------------------------------------------------------*/
bool bool
module_iconv (RECODE_OUTER outer) module_iconv (RECODE_OUTER outer)
 End of changes. 16 change blocks. 
41 lines changed or deleted 36 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)