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