libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2010, 2013 Peter Miller 00004 * Written by Peter Miller <pmiller@opensource.org.au> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as 00008 * published by the Free Software Foundation; either version 3 of the 00009 * License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include <libexplain/ac/stdint.h> 00021 #include <libexplain/ac/wchar.h> 00022 00023 #include <libexplain/buffer/double.h> 00024 #include <libexplain/buffer/int.h> 00025 #include <libexplain/buffer/long.h> 00026 #include <libexplain/buffer/long_double.h> 00027 #include <libexplain/buffer/long_long.h> 00028 #include <libexplain/buffer/pathname.h> 00029 #include <libexplain/buffer/pointer.h> 00030 #include <libexplain/buffer/size_t.h> 00031 #include <libexplain/buffer/ssize_t.h> 00032 #include <libexplain/printf_format.h> 00033 00034 00035 #define PAIR(a, b) \ 00036 (((a) << 8) | (b)) 00037 00038 00039 void 00040 explain_printf_format_representation(explain_string_buffer_t *sb, 00041 const char *format, va_list ap) 00042 { 00043 explain_printf_format_list_t specs; 00044 size_t errpos; 00045 00046 explain_printf_format_list_constructor(&specs); 00047 errpos = explain_printf_format(format, &specs); 00048 if (errpos == 0) 00049 { 00050 int cur_idx; 00051 size_t j; 00052 00053 explain_printf_format_list_sort(&specs); 00054 /* duplicates are OK, holes are not */ 00055 cur_idx = 0; 00056 for (j = 0; j < specs.length; ++j) 00057 { 00058 const explain_printf_format_t *p; 00059 00060 p = &specs.list[j]; 00061 explain_string_buffer_puts(sb, ", "); 00062 if (p->index > cur_idx) 00063 { 00064 /* we found a hole */ 00065 break; 00066 } 00067 /* duplicates are OK */ 00068 if (p->index == cur_idx) 00069 { 00070 switch (PAIR(p->modifier, p->specifier)) 00071 { 00072 case PAIR('H', 'o'): 00073 explain_string_buffer_printf 00074 ( 00075 sb, 00076 "%#o", 00077 (unsigned char)va_arg(ap, int) 00078 ); 00079 break; 00080 00081 case PAIR('H', 'd'): 00082 case PAIR('H', 'i'): 00083 explain_buffer_int(sb, (char)va_arg(ap, int)); 00084 break; 00085 00086 case PAIR('H', 'u'): 00087 explain_buffer_uint(sb, (unsigned char)va_arg(ap, int)); 00088 break; 00089 00090 case PAIR('H', 'x'): 00091 case PAIR('H', 'X'): 00092 explain_string_buffer_printf 00093 ( 00094 sb, 00095 "0x%02X", 00096 (unsigned char)va_arg(ap, int) 00097 ); 00098 break; 00099 00100 case PAIR(0, 'c'): 00101 explain_string_buffer_putc_quoted(sb, va_arg(ap, int)); 00102 break; 00103 00104 case PAIR('h', 'o'): 00105 explain_string_buffer_printf 00106 ( 00107 sb, 00108 "%#o", 00109 (unsigned short)va_arg(ap, int) 00110 ); 00111 break; 00112 00113 case PAIR('h', 'd'): 00114 case PAIR('h', 'i'): 00115 explain_buffer_int(sb, (short)va_arg(ap, int)); 00116 break; 00117 00118 case PAIR('h', 'u'): 00119 explain_buffer_uint(sb, (unsigned short)va_arg(ap, int)); 00120 break; 00121 00122 case PAIR('h', 'x'): 00123 case PAIR('h', 'X'): 00124 explain_string_buffer_printf 00125 ( 00126 sb, 00127 "0x%04X", 00128 (unsigned short)va_arg(ap, int) 00129 ); 00130 break; 00131 00132 case PAIR(0, 'o'): 00133 explain_string_buffer_printf 00134 ( 00135 sb, 00136 "%#o", 00137 va_arg(ap, unsigned int) 00138 ); 00139 break; 00140 00141 case PAIR(0, 'd'): 00142 case PAIR(0, 'i'): 00143 explain_buffer_int(sb, va_arg(ap, int)); 00144 break; 00145 00146 case PAIR(0, 'u'): 00147 explain_buffer_uint(sb, va_arg(ap, unsigned int)); 00148 break; 00149 00150 case PAIR(0, 'x'): 00151 case PAIR(0, 'X'): 00152 explain_string_buffer_printf 00153 ( 00154 sb, 00155 "0x%04X", 00156 va_arg(ap, unsigned int) 00157 ); 00158 break; 00159 00160 case PAIR('l', 'o'): 00161 explain_string_buffer_printf 00162 ( 00163 sb, 00164 "%#lo", 00165 va_arg(ap, unsigned long int) 00166 ); 00167 break; 00168 00169 case PAIR('l', 'd'): 00170 case PAIR('l', 'i'): 00171 explain_buffer_long(sb, va_arg(ap, long int)); 00172 break; 00173 00174 case PAIR('l', 'u'): 00175 explain_buffer_ulong(sb, va_arg(ap, unsigned long int)); 00176 break; 00177 00178 case PAIR('l', 'x'): 00179 case PAIR('l', 'X'): 00180 explain_string_buffer_printf 00181 ( 00182 sb, 00183 "0x%08lX", 00184 va_arg(ap, unsigned long int) 00185 ); 00186 break; 00187 00188 case PAIR('l', 'c'): 00189 /* FIXME: print the equivalent multi-byte char? */ 00190 explain_buffer_long(sb, va_arg(ap, wint_t)); 00191 break; 00192 00193 case PAIR('L', 'o'): 00194 case PAIR('q', 'o'): 00195 explain_string_buffer_printf 00196 ( 00197 sb, 00198 "%#llo", 00199 va_arg(ap, unsigned long long int) 00200 ); 00201 break; 00202 00203 case PAIR('L', 'u'): 00204 case PAIR('q', 'u'): 00205 explain_buffer_unsigned_long_long 00206 ( 00207 sb, 00208 va_arg(ap, unsigned long long int) 00209 ); 00210 break; 00211 00212 case PAIR('L', 'd'): 00213 case PAIR('q', 'd'): 00214 case PAIR('L', 'i'): 00215 case PAIR('q', 'i'): 00216 explain_buffer_long_long(sb, va_arg(ap, long long int)); 00217 break; 00218 00219 case PAIR('L', 'x'): 00220 case PAIR('L', 'X'): 00221 case PAIR('q', 'x'): 00222 case PAIR('q', 'X'): 00223 explain_string_buffer_printf 00224 ( 00225 sb, 00226 "0x%08llX", 00227 va_arg(ap, unsigned long long int) 00228 ); 00229 break; 00230 break; 00231 00232 case PAIR('j', 'd'): 00233 case PAIR('j', 'i'): 00234 explain_buffer_long_long(sb, va_arg(ap, intmax_t)); 00235 break; 00236 00237 case PAIR('j', 'o'): 00238 case PAIR('j', 'x'): 00239 case PAIR('j', 'X'): 00240 case PAIR('j', 'u'): 00241 explain_buffer_unsigned_long_long(sb, va_arg(ap, intmax_t)); 00242 break; 00243 00244 case PAIR('t', 'd'): 00245 case PAIR('t', 'i'): 00246 explain_buffer_long_long(sb, va_arg(ap, ptrdiff_t)); 00247 break; 00248 00249 case PAIR('t', 'o'): 00250 case PAIR('t', 'x'): 00251 case PAIR('t', 'X'): 00252 case PAIR('t', 'u'): 00253 explain_buffer_unsigned_long_long 00254 ( 00255 sb, 00256 va_arg(ap, ptrdiff_t) 00257 ); 00258 break; 00259 00260 case PAIR('Z', 'd'): 00261 case PAIR('Z', 'i'): 00262 case PAIR('z', 'd'): 00263 case PAIR('z', 'i'): 00264 explain_buffer_ssize_t(sb, va_arg(ap, size_t)); 00265 break; 00266 00267 case PAIR('Z', 'X'): 00268 case PAIR('Z', 'o'): 00269 case PAIR('Z', 'u'): 00270 case PAIR('Z', 'x'): 00271 case PAIR('z', 'X'): 00272 case PAIR('z', 'o'): 00273 case PAIR('z', 'u'): 00274 case PAIR('z', 'x'): 00275 explain_buffer_size_t(sb, va_arg(ap, size_t)); 00276 break; 00277 00278 case PAIR(0, 'n'): 00279 explain_buffer_pointer(sb, va_arg(ap, int *)); 00280 break; 00281 00282 case PAIR('l', 'n'): 00283 explain_buffer_pointer(sb, va_arg(ap, long *)); 00284 break; 00285 00286 case PAIR('L', 'n'): 00287 explain_buffer_pointer(sb, va_arg(ap, long long *)); 00288 break; 00289 00290 case PAIR('h', 'n'): 00291 explain_buffer_pointer(sb, va_arg(ap, short *)); 00292 break; 00293 00294 case PAIR('H', 'n'): 00295 explain_buffer_pointer(sb, va_arg(ap, char *)); 00296 break; 00297 00298 case PAIR(0, 's'): 00299 explain_buffer_pathname(sb, va_arg(ap, const char *)); 00300 break; 00301 00302 case PAIR('l', 's'): 00303 explain_buffer_pointer(sb, va_arg(ap, const wchar_t *)); 00304 break; 00305 00306 case PAIR(0, 'p'): 00307 explain_buffer_pointer(sb, va_arg(ap, void *)); 00308 break; 00309 00310 case PAIR(0, 'a'): 00311 case PAIR(0, 'A'): 00312 case PAIR(0, 'e'): 00313 case PAIR(0, 'f'): 00314 case PAIR(0, 'g'): 00315 explain_buffer_double(sb, va_arg(ap, double)); 00316 break; 00317 00318 case PAIR('l', 'a'): 00319 case PAIR('l', 'A'): 00320 case PAIR('l', 'e'): 00321 case PAIR('L', 'e'): 00322 case PAIR('l', 'f'): 00323 case PAIR('L', 'f'): 00324 case PAIR('l', 'g'): 00325 case PAIR('L', 'g'): 00326 explain_buffer_long_double(sb, va_arg(ap, long double)); 00327 break; 00328 00329 default: 00330 /* Help the poor person who has to debug this one. */ 00331 explain_string_buffer_putc(sb, '%'); 00332 if (p->modifier) 00333 explain_string_buffer_putc(sb, p->modifier); 00334 explain_string_buffer_putc(sb, p->specifier); 00335 break; 00336 } 00337 ++cur_idx; 00338 } 00339 } 00340 } 00341 explain_printf_format_list_destructor(&specs); 00342 } 00343 00344 00345 /* vim: set ts=8 sw=4 et : */