popt  1.16
poptint.c
Go to the documentation of this file.
00001 #include "system.h"
00002 #include <stdarg.h>
00003 #include "poptint.h"
00004 
00005 /* Any pair of 32 bit hashes can be used. lookup3.c generates pairs, will do. */
00006 #define _JLU3_jlu32lpair        1
00007 #define jlu32lpair      poptJlu32lpair
00008 #include "lookup3.c"
00009 
00010 /*@-varuse +charint +ignoresigns @*/
00011 /*@unchecked@*/ /*@observer@*/
00012 static const unsigned char utf8_skip_data[256] = {
00013     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,
00014     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,
00015     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,
00016     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,
00017     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,
00018     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,
00019     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,
00020     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
00021 };
00022 /*@=varuse =charint =ignoresigns @*/
00023 
00024 const char *
00025 POPT_prev_char (const char *str)
00026 {
00027     const char *p = str;
00028 
00029     while (1) {
00030         p--;
00031         if (((unsigned)*p & 0xc0) != (unsigned)0x80)
00032             return p;
00033     }
00034 }
00035 
00036 const char *
00037 POPT_next_char (const char *str)
00038 {
00039     const char *p = str;
00040 
00041     while (*p != '\0') {
00042         p++;
00043         if (((unsigned)*p & 0xc0) != (unsigned)0x80)
00044             break;
00045     }
00046     return p;
00047 }
00048 
00049 #if !defined(POPT_fprintf)      /* XXX lose all the goop ... */
00050 
00051 #if defined(HAVE_DCGETTEXT) && !defined(__LCLINT__)
00052 /*
00053  * Rebind a "UTF-8" codeset for popt's internal use.
00054  */
00055 char *
00056 POPT_dgettext(const char * dom, const char * str)
00057 {
00058     char * codeset = NULL;
00059     char * retval = NULL;
00060 
00061     if (!dom) 
00062         dom = textdomain(NULL);
00063     codeset = bind_textdomain_codeset(dom, NULL);
00064     bind_textdomain_codeset(dom, "UTF-8");
00065     retval = dgettext(dom, str);
00066     bind_textdomain_codeset(dom, codeset);
00067 
00068     return retval;
00069 }
00070 #endif
00071 
00072 #ifdef HAVE_ICONV
00073 
00078 static /*@only@*/ /*@null@*/ char *
00079 strdup_locale_from_utf8 (/*@null@*/ char * istr)
00080         /*@*/
00081 {
00082     char * codeset = NULL;
00083     char * ostr = NULL;
00084     iconv_t cd;
00085 
00086     if (istr == NULL)
00087         return NULL;
00088 
00089 #ifdef HAVE_LANGINFO_H
00090     codeset = nl_langinfo ((nl_item)CODESET);
00091 #endif
00092 
00093     if (codeset != NULL && strcmp(codeset, "UTF-8") != 0
00094      && (cd = iconv_open(codeset, "UTF-8")) != (iconv_t)-1)
00095     {
00096         char * shift_pin = NULL;
00097         size_t db = strlen(istr);
00098 /*@owned@*/
00099         char * dstr = malloc((db + 1) * sizeof(*dstr));
00100         char * pin = istr;
00101         char * pout = dstr;
00102         size_t ib = db;
00103         size_t ob = db;
00104         size_t err;
00105 
00106         if (dstr == NULL)
00107             return NULL;
00108         err = iconv(cd, NULL, NULL, NULL, NULL);
00109         while (1) {
00110             *pout = '\0';
00111             err = iconv(cd, &pin, &ib, &pout, &ob);
00112             if (err != (size_t)-1) {
00113                 if (shift_pin == NULL) {
00114                     shift_pin = pin;
00115                     pin = NULL;
00116                     ib = 0;
00117                     continue;
00118                 }
00119             } else
00120             switch (errno) {
00121             case E2BIG:
00122             {   size_t used = (size_t)(pout - dstr);
00123                 db *= 2;
00124                 dstr = realloc(dstr, (db + 1) * sizeof(*dstr));
00125                 if (dstr != NULL) {
00126                     pout = dstr + used;
00127                     ob = db - used;
00128                     continue;
00129                 }
00130             }   /*@switchbreak@*/ break;
00131             case EINVAL:
00132             case EILSEQ:
00133             default:
00134                 /*@switchbreak@*/ break;
00135             }
00136             break;
00137         }
00138         (void) iconv_close(cd);
00139         *pout = '\0';
00140         ostr = xstrdup(dstr);
00141         free(dstr);
00142     } else
00143         ostr = xstrdup(istr);
00144 
00145     return ostr;
00146 }
00147 #endif
00148 
00149 int
00150 POPT_fprintf (FILE * stream, const char * format, ...)
00151 {
00152     char * b = NULL, * ob = NULL;
00153     int rc;
00154     va_list ap;
00155 
00156 #if defined(HAVE_VASPRINTF) && !defined(__LCLINT__)
00157     va_start(ap, format);
00158     if ((rc = vasprintf(&b, format, ap)) < 0)
00159         b = NULL;
00160     va_end(ap);
00161 #else
00162     size_t nb = (size_t)1;
00163 
00164     /* HACK: add +1 to the realloc no. of bytes "just in case". */
00165     /* XXX Likely unneeded, the issues wrto vsnprintf(3) return b0rkage have
00166      * to do with whether the final '\0' is counted (or not). The code
00167      * below already adds +1 for the (possibly already counted) trailing NUL.
00168      */
00169     while ((b = realloc(b, nb+1)) != NULL) {
00170         va_start(ap, format);
00171         rc = vsnprintf(b, nb, format, ap);
00172         va_end(ap);
00173         if (rc > -1) {  /* glibc 2.1 */
00174             if ((size_t)rc < nb)
00175                 break;
00176             nb = (size_t)(rc + 1);      /* precise buffer length known */
00177         } else          /* glibc 2.0 */
00178             nb += (nb < (size_t)100 ? (size_t)100 : nb);
00179         ob = b;
00180     }
00181 #endif
00182 
00183     rc = 0;
00184     if (b != NULL) {
00185 #ifdef HAVE_ICONV
00186         ob = strdup_locale_from_utf8(b);
00187         if (ob != NULL) {
00188             rc = fprintf(stream, "%s", ob);
00189             free(ob);
00190         } else
00191 #endif
00192             rc = fprintf(stream, "%s", b);
00193         free (b);
00194     }
00195 
00196     return rc;
00197 }
00198 
00199 #endif  /* !defined(POPT_fprintf) */

Generated for popt by  doxygen 1.7.6.1