summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--popthelp.c2
-rw-r--r--poptint.c145
-rw-r--r--poptint.h5
4 files changed, 152 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index b8049ad..63ce37f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,7 @@ include_HEADERS = popt.h
usrlibdir = $(libdir)@MARK64@
usrlib_LTLIBRARIES = libpopt.la
-libpopt_la_SOURCES = popt.c findme.c poptparse.c poptconfig.c popthelp.c
+libpopt_la_SOURCES = popt.c findme.c poptparse.c poptconfig.c popthelp.c poptint.c
libpopt_la_LDFLAGS = -no-undefined @LTLIBINTL@
if HAVE_LD_VERSION_SCRIPT
diff --git a/popthelp.c b/popthelp.c
index 2a18c32..51c20a9 100644
--- a/popthelp.c
+++ b/popthelp.c
@@ -532,7 +532,7 @@ static void singleTableHelp(poptContext con, FILE * fp,
sub_transdom = translation_domain;
if (opt->descrip)
- fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
+ POPT_fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
singleTableHelp(con, fp, opt->arg, left, sub_transdom);
}
diff --git a/poptint.c b/poptint.c
new file mode 100644
index 0000000..20cb3ca
--- /dev/null
+++ b/poptint.c
@@ -0,0 +1,145 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <iconv.h>
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
+#include "system.h"
+#include "poptint.h"
+
+#define STD_VFPRINTF(stream, format, args, retval) \
+ va_start ((args), (format)); \
+ (retval) = vfprintf ((stream), (format), (args)); \
+ va_end ((args));
+
+static char *
+strdup_locale_from_utf8 (char *buffer)
+{
+ char *codeset = NULL;
+ char *pout = NULL, *dest_str;
+ iconv_t fd;
+ int ib, ob, dest_size;
+ int done, is_error;
+ size_t err, used;
+
+ if (!buffer)
+ return NULL;
+
+#ifdef HAVE_LANGINFO_H
+ codeset = nl_langinfo (CODESET);
+#endif
+
+ if (codeset &&
+ strcmp (codeset, "UTF-8") &&
+ (fd = iconv_open (codeset, "UTF-8")) != (iconv_t)-1) {
+ char *pin = buffer;
+ char *shift_pin = NULL;
+
+ iconv (fd, NULL, (size_t*)&ib, &pout, (size_t*)&ob);
+ ib = strlen (buffer);
+ dest_size = ob = ib;
+ dest_str = pout = malloc ((dest_size + 1) * sizeof (char));
+ done = is_error = 0;
+ while (!done && !is_error) {
+ err = iconv (fd, (const char**)&pin, (size_t*)&ib, &pout, (size_t*)&ob);
+
+ if (err == (size_t)-1) {
+ switch (errno) {
+ case EINVAL:
+ done = 1;
+ break;
+ case E2BIG:
+ used = pout - dest_str;
+ dest_size *= 2;
+ dest_str = realloc (dest_str, (dest_size + 1) * sizeof (char));
+ pout = dest_str + used;
+ ob = dest_size - used;
+ break;
+ case EILSEQ:
+ is_error = 1;
+ break;
+ default:
+ is_error = 1;
+ break;
+ }
+ } else {
+ if (!shift_pin) {
+ shift_pin = pin;
+ pin = NULL;
+ ib = 0;
+ } else {
+ done = 1;
+ }
+ }
+ }
+ iconv_close (fd);
+ *pout = '\0';
+ dest_str = strdup (dest_str);
+ } else {
+ dest_str = strdup (buffer);
+ }
+
+ return dest_str;
+}
+
+static char *
+strdup_vprintf (const char *format, va_list args)
+{
+ char *buffer = NULL;
+ va_list args2;
+ char c;
+
+ args2 = args;
+ buffer = calloc (sizeof (char), vsnprintf (&c, 1, format, args) + 1);
+ vsprintf (buffer, format, args2);
+ va_end (args2);
+
+ return buffer;
+}
+
+char *
+POPT_prev_char (const char *str)
+{
+ char *p = (char*)str;
+
+ while (1) {
+ p--;
+ if ((*p & 0xc0) != 0x80)
+ return (char *)p;
+ }
+}
+
+int
+POPT_fprintf (FILE* stream, const char *format, ...)
+{
+ int retval = 0;
+ va_list args;
+ char *buffer = NULL;
+ char *locale_str = NULL;
+
+ va_start (args, format);
+ buffer = strdup_vprintf (format, args);
+ va_end (args);
+
+ locale_str = strdup_locale_from_utf8 (buffer);
+ if (locale_str) {
+ retval = fprintf (stream, "%s", locale_str);
+ free (locale_str);
+ } else {
+ fprintf (stderr, POPT_WARNING "%s\n", "Invalid UTF-8");
+ retval = fprintf (stream, "%s", buffer);
+ }
+ free (buffer);
+
+ return retval;
+
+}
+
+#undef STD_VFPRINTF
+
diff --git a/poptint.h b/poptint.h
index ff9f978..dae91bc 100644
--- a/poptint.h
+++ b/poptint.h
@@ -114,4 +114,9 @@ struct poptContext_s {
#define N_(foo) foo
+#define POPT_WARNING "(popt): Warning **: "
+
+int POPT_fprintf (FILE* steam, const char *format, ...);
+char *POPT_prev_char (const char *str);
+
#endif