popt
1.14
|
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) */