From: Bruno Haible Date: Tue, 4 Aug 2009 06:55:16 +0000 (+0200) Subject: Port msgfilter to Woe32 platforms. X-Git-Tag: v0.18~166 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2a6642170e4b06346bf80a45c124da94b0d0688c;p=thirdparty%2Fgettext.git Port msgfilter to Woe32 platforms. --- diff --git a/ChangeLog b/ChangeLog index efde47442..a6e0b3879 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-08-04 Bruno Haible + + Port msgfilter to Woe32 platforms. + * autogen.sh (GNULIB_MODULES_TOOLS_FOR_SRC): Add pipe-filter-ii. + 2009-08-03 Bruno Haible * autogen.sh: Remove statements to fix permissions. Now fixed in git. diff --git a/NEWS b/NEWS index ab8bb1b64..6870a42e5 100644 --- a/NEWS +++ b/NEWS @@ -36,6 +36,9 @@ Version 0.18 - January 2008 'gfc-internal-format'. * Updated the meaning of 'gcc-internal-format' to match GCC 4.3. + +* Portability: + The msgfilter program now also works on native Woe32 platforms. Version 0.17 - November 2007 diff --git a/autogen.sh b/autogen.sh index 9b637ee3e..98a280350 100755 --- a/autogen.sh +++ b/autogen.sh @@ -152,6 +152,7 @@ if ! $skip_gnulib; then openmp ostream pipe + pipe-filter-ii progname propername relocatable-prog diff --git a/gettext-tools/gnulib-lib/.gitignore b/gettext-tools/gnulib-lib/.gitignore index 2c6fda368..3a3dde744 100644 --- a/gettext-tools/gnulib-lib/.gitignore +++ b/gettext-tools/gnulib-lib/.gitignore @@ -174,6 +174,10 @@ /ostream.oo.c /ostream.oo.h /pathmax.h +/pipe-filter-aux.h +/pipe-filter-ii.c +/pipe-filter.c +/pipe-filter.h /pipe-safer.c /pipe.c /pipe.h diff --git a/gettext-tools/gnulib-tests/.gitignore b/gettext-tools/gnulib-tests/.gitignore index b37c6747d..d78e0bfb3 100644 --- a/gettext-tools/gnulib-tests/.gitignore +++ b/gettext-tools/gnulib-tests/.gitignore @@ -93,6 +93,13 @@ /test-moo-sub2.oo.c /test-moo-sub2.oo.h /test-open.c +/test-pipe-filter-ii1.c +/test-pipe-filter-ii1.sh +/test-pipe-filter-ii2-child.c +/test-pipe-filter-ii2-main.c +/test-pipe-filter-ii2.sh +/test-pipe-filter.c +/test-pipe-filter.sh /test-pipe.c /test-pipe.sh /test-posix_spawn1.c @@ -146,6 +153,7 @@ /test-term-ostream.c /test-tls.c /test-unistd.c +/test-vasnprintf-posix.c /test-vasnprintf.c /test-vasprintf.c /test-vsnprintf.c diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog index 0d68bdcbd..83588505b 100644 --- a/gettext-tools/src/ChangeLog +++ b/gettext-tools/src/ChangeLog @@ -1,3 +1,17 @@ +2009-08-04 Bruno Haible + + Port msgfilter to Woe32 platforms. + * msgfilter.c: Don't include errno.h, fcntl.h, io.h, sys/select.h, + pipe.h, wait-process.h. Include pipe-filter.h instead. + (HAVE_SELECT): Remove undefine. + (nonintr_close, nonintr_read, nonintr_write, nonintr_select): Remove + functions. + (O_NONBLOCK): Remove fallback. + (IS_EAGAIN): Remove macro. + (struct locals): New type. + (prepare_write, done_write, prepare_read, done_read): New functions. + (generic_filter): Implement using pipe_filter_ii_execute. + 2009-07-27 Часлав Илић (Chusslove Illich) Extend recode-sr-latin to also transform letters with accents. diff --git a/gettext-tools/src/msgfilter.c b/gettext-tools/src/msgfilter.c index 69f67a560..88662ba0e 100644 --- a/gettext-tools/src/msgfilter.c +++ b/gettext-tools/src/msgfilter.c @@ -20,8 +20,6 @@ # include "config.h" #endif -#include -#include #include #include #include @@ -31,14 +29,6 @@ #include #include #include -#if defined _MSC_VER || defined __MINGW32__ -# include -#endif - -/* Get fd_set (on AIX or Minix) or select() declaration (on EMX). */ -#if defined (_AIX) || defined (_MINIX) || defined (__EMX__) -# include -#endif #include "closeout.h" #include "dir-list.h" @@ -60,8 +50,7 @@ #include "msgl-charset.h" #include "xalloc.h" #include "findprog.h" -#include "pipe.h" -#include "wait-process.h" +#include "pipe-filter.h" #include "xsetenv.h" #include "filters.h" #include "msgl-iconv.h" @@ -72,17 +61,7 @@ #define _(str) gettext (str) -/* We use a child process, and communicate through a bidirectional pipe. - To avoid deadlocks, let the child process decide when it wants to read - or to write, and let the parent behave accordingly. The parent uses - select() to know whether it must write or read. On platforms without - select(), we use non-blocking I/O. (This means the parent is busy - looping while waiting for the child. Not good.) */ - -/* On BeOS select() works only on sockets, not on normal file descriptors. */ -#ifdef __BEOS__ -# undef HAVE_SELECT -#endif +/* We use a child process, and communicate through a bidirectional pipe. */ /* Force output of PO file even if empty. */ @@ -495,87 +474,64 @@ Informative output:\n")); } -#ifdef EINTR - -/* EINTR handling for close(), read(), write(), select(). - These functions can return -1/EINTR even though we don't have any - signal handlers set up, namely when we get interrupted via SIGSTOP. */ +/* Callbacks called from pipe_filter_ii_execute. */ -static inline int -nonintr_close (int fd) +struct locals { - int retval; + /* String being written. */ + const char *str; + size_t len; + /* String being read and accumulated. */ + char *result; + size_t allocated; + size_t length; +}; - do - retval = close (fd); - while (retval < 0 && errno == EINTR); +static const void * +prepare_write (size_t *num_bytes_p, void *private_data) +{ + struct locals *l = (struct locals *) private_data; - return retval; + if (l->len > 0) + { + *num_bytes_p = l->len; + return l->str; + } + else + return NULL; } -#define close nonintr_close -static inline ssize_t -nonintr_read (int fd, void *buf, size_t count) +static void +done_write (void *data_written, size_t num_bytes_written, void *private_data) { - ssize_t retval; + struct locals *l = (struct locals *) private_data; - do - retval = read (fd, buf, count); - while (retval < 0 && errno == EINTR); - - return retval; + l->str += num_bytes_written; + l->len -= num_bytes_written; } -#define read nonintr_read -static inline ssize_t -nonintr_write (int fd, const void *buf, size_t count) +static void * +prepare_read (size_t *num_bytes_p, void *private_data) { - ssize_t retval; - - do - retval = write (fd, buf, count); - while (retval < 0 && errno == EINTR); + struct locals *l = (struct locals *) private_data; - return retval; + if (l->length == l->allocated) + { + l->allocated = l->allocated + (l->allocated >> 1); + l->result = (char *) xrealloc (l->result, l->allocated); + } + *num_bytes_p = l->allocated - l->length; + return l->result + l->length; } -#undef write /* avoid warning on VMS */ -#define write nonintr_write -# if HAVE_SELECT - -static inline int -nonintr_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - struct timeval *timeout) +static void +done_read (void *data_read, size_t num_bytes_read, void *private_data) { - int retval; - - do - retval = select (n, readfds, writefds, exceptfds, timeout); - while (retval < 0 && errno == EINTR); + struct locals *l = (struct locals *) private_data; - return retval; + l->length += num_bytes_read; } -#undef select /* avoid warning on VMS */ -#define select nonintr_select -# endif - -#endif - - -/* Non-blocking I/O. */ -#ifndef O_NONBLOCK -# define O_NONBLOCK O_NDELAY -#endif -#if HAVE_SELECT -# define IS_EAGAIN(errcode) 0 -#else -# ifdef EWOULDBLOCK -# define IS_EAGAIN(errcode) ((errcode) == EAGAIN || (errcode) == EWOULDBLOCK) -# else -# define IS_EAGAIN(errcode) ((errcode) == EAGAIN) -# endif -#endif /* Process a string STR of size LEN bytes through the subprogram. Store the freshly allocated result at *RESULTP and its length at *LENGTHP. @@ -583,140 +539,20 @@ nonintr_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, static void generic_filter (const char *str, size_t len, char **resultp, size_t *lengthp) { -#if defined _MSC_VER || defined __MINGW32__ - /* Native Woe32 API. */ - /* Not yet implemented. */ - error (EXIT_FAILURE, 0, _("Not yet implemented.")); -#else - pid_t child; - int fd[2]; - char *result; - size_t allocated; - size_t length; - int exitstatus; - - /* Open a bidirectional pipe to a subprocess. */ - child = create_pipe_bidi (sub_name, sub_path, sub_argv, false, true, true, - fd); - - /* Enable non-blocking I/O. This permits the read() and write() calls - to return -1/EAGAIN without blocking; this is important for polling - if HAVE_SELECT is not defined. It also permits the read() and write() - calls to return after partial reads/writes; this is important if - HAVE_SELECT is defined, because select() only says that some data - can be read or written, not how many. Without non-blocking I/O, - Linux 2.2.17 and BSD systems prefer to block instead of returning - with partial results. */ - { - int fcntl_flags; - - if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0 - || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) < 0 - || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0 - || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) < 0) - error (EXIT_FAILURE, errno, - _("cannot set up nonblocking I/O to %s subprocess"), sub_name); - } - - allocated = len + (len >> 2) + 1; - result = XNMALLOC (allocated, char); - length = 0; - - for (;;) - { -#if HAVE_SELECT - int n; - fd_set readfds; - fd_set writefds; - - FD_ZERO (&readfds); - FD_SET (fd[0], &readfds); - n = fd[0] + 1; - if (str != NULL) - { - FD_ZERO (&writefds); - FD_SET (fd[1], &writefds); - if (n <= fd[1]) - n = fd[1] + 1; - } - - n = select (n, &readfds, (str != NULL ? &writefds : NULL), NULL, NULL); - if (n < 0) - error (EXIT_FAILURE, errno, - _("communication with %s subprocess failed"), sub_name); - if (str != NULL && FD_ISSET (fd[1], &writefds)) - goto try_write; - if (FD_ISSET (fd[0], &readfds)) - goto try_read; - /* How could select() return if none of the two descriptors is ready? */ - abort (); -#endif - - /* Attempt to write. */ -#if HAVE_SELECT - try_write: -#endif - if (str != NULL) - { - if (len > 0) - { - ssize_t nwritten = write (fd[1], str, len); - if (nwritten < 0 && !IS_EAGAIN (errno)) - error (EXIT_FAILURE, errno, - _("write to %s subprocess failed"), sub_name); - if (nwritten > 0) - { - str += nwritten; - len -= nwritten; - } - } - else - { - /* Tell the child there is nothing more the parent will send. */ - close (fd[1]); - str = NULL; - } - } -#if HAVE_SELECT - continue; -#endif - - /* Attempt to read. */ -#if HAVE_SELECT - try_read: -#endif - if (length == allocated) - { - allocated = allocated + (allocated >> 1); - result = (char *) xrealloc (result, allocated); - } - { - ssize_t nread = read (fd[0], result + length, allocated - length); - if (nread < 0 && !IS_EAGAIN (errno)) - error (EXIT_FAILURE, errno, - _("read from %s subprocess failed"), sub_name); - if (nread > 0) - length += nread; - if (nread == 0 && str == NULL) - break; - } -#if HAVE_SELECT - continue; -#endif - } + struct locals l; - close (fd[0]); + l.str = str; + l.len = len; + l.allocated = len + (len >> 2) + 1; + l.result = XNMALLOC (l.allocated, char); + l.length = 0; - /* Remove zombie process from process list. */ - exitstatus = - wait_subprocess (child, sub_name, false, false, true, true, NULL); - if (exitstatus != 0) - error (EXIT_FAILURE, 0, _("%s subprocess terminated with exit code %d"), - sub_name, exitstatus); + pipe_filter_ii_execute (sub_name, sub_path, sub_argv, false, true, + prepare_write, done_write, prepare_read, done_read, + &l); - *resultp = result; - *lengthp = length; -#endif + *resultp = l.result; + *lengthp = l.length; }