blob: 83fa7d6c19633019554d1fce51be46feddb7e9b0 [file] [log] [blame]
#include "system.h"
#include <stdarg.h>
#include "poptint.h"
/* Any pair of 32 bit hashes can be used. lookup3.c generates pairs, will do. */
#define _JLU3_jlu32lpair 1
#define jlu32lpair poptJlu32lpair
#include "lookup3.c"
/*@-varuse +charint +ignoresigns @*/
/*@unchecked@*/ /*@observer@*/
static const unsigned char utf8_skip_data[256] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
};
/*@=varuse =charint =ignoresigns @*/
const char *
POPT_prev_char (const char *str)
{
const char *p = str;
while (1) {
p--;
if (((unsigned)*p & 0xc0) != (unsigned)0x80)
return p;
}
}
const char *
POPT_next_char (const char *str)
{
const char *p = str;
while (*p != '\0') {
p++;
if (((unsigned)*p & 0xc0) != (unsigned)0x80)
break;
}
return p;
}
#if !defined(POPT_fprintf) /* XXX lose all the goop ... */
#if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
/*
* Rebind a "UTF-8" codeset for popt's internal use.
*/
char *
POPT_dgettext(const char * dom, const char * str)
{
char * codeset = NULL;
char * retval = NULL;
if (!dom)
dom = textdomain(NULL);
codeset = bind_textdomain_codeset(dom, NULL);
bind_textdomain_codeset(dom, "UTF-8");
retval = dgettext(dom, str);
bind_textdomain_codeset(dom, codeset);
return retval;
}
#endif
#ifdef HAVE_ICONV
/**
* Return malloc'd string converted from UTF-8 to current locale.
* @param istr input string (UTF-8 encoding assumed)
* @return localized string
*/
static /*@only@*/ /*@null@*/ char *
strdup_locale_from_utf8 (/*@null@*/ char * istr)
/*@*/
{
char * codeset = NULL;
char * ostr = NULL;
iconv_t cd;
if (istr == NULL)
return NULL;
#ifdef HAVE_LANGINFO_H
codeset = nl_langinfo ((nl_item)CODESET);
#endif
if (codeset != NULL && strcmp(codeset, "UTF-8") != 0
&& (cd = iconv_open(codeset, "UTF-8")) != (iconv_t)-1)
{
char * shift_pin = NULL;
size_t db = strlen(istr);
/*@owned@*/
char * dstr = malloc((db + 1) * sizeof(*dstr));
char * pin = istr;
char * pout = dstr;
size_t ib = db;
size_t ob = db;
size_t err;
if (dstr == NULL)
return NULL;
err = iconv(cd, NULL, NULL, NULL, NULL);
while (1) {
*pout = '\0';
err = iconv(cd, &pin, &ib, &pout, &ob);
if (err != (size_t)-1) {
if (shift_pin == NULL) {
shift_pin = pin;
pin = NULL;
ib = 0;
continue;
}
} else
switch (errno) {
case E2BIG:
{ size_t used = (size_t)(pout - dstr);
db *= 2;
dstr = realloc(dstr, (db + 1) * sizeof(*dstr));
if (dstr != NULL) {
pout = dstr + used;
ob = db - used;
continue;
}
} /*@switchbreak@*/ break;
case EINVAL:
case EILSEQ:
default:
/*@switchbreak@*/ break;
}
break;
}
(void) iconv_close(cd);
*pout = '\0';
ostr = xstrdup(dstr);
free(dstr);
} else
ostr = xstrdup(istr);
return ostr;
}
#endif
int
POPT_fprintf (FILE * stream, const char * format, ...)
{
char * b = NULL, * ob = NULL;
int rc;
va_list ap;
#if defined(HAVE_VASPRINTF) && !defined(__LCLINT__)
va_start(ap, format);
if ((rc = vasprintf(&b, format, ap)) < 0)
b = NULL;
va_end(ap);
#else
size_t nb = (size_t)1;
/* HACK: add +1 to the realloc no. of bytes "just in case". */
/* XXX Likely unneeded, the issues wrto vsnprintf(3) return b0rkage have
* to do with whether the final '\0' is counted (or not). The code
* below already adds +1 for the (possibly already counted) trailing NUL.
*/
while ((b = realloc(b, nb+1)) != NULL) {
va_start(ap, format);
rc = vsnprintf(b, nb, format, ap);
va_end(ap);
if (rc > -1) { /* glibc 2.1 */
if ((size_t)rc < nb)
break;
nb = (size_t)(rc + 1); /* precise buffer length known */
} else /* glibc 2.0 */
nb += (nb < (size_t)100 ? (size_t)100 : nb);
ob = b;
}
#endif
rc = 0;
if (b != NULL) {
#ifdef HAVE_ICONV
ob = strdup_locale_from_utf8(b);
if (ob != NULL) {
rc = fprintf(stream, "%s", ob);
free(ob);
} else
#endif
rc = fprintf(stream, "%s", b);
free (b);
}
return rc;
}
#endif /* !defined(POPT_fprintf) */