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

Generated for popt by  doxygen 1.7.6.1