libexplain  1.4.D001
libexplain/printf_format/representation.c
Go to the documentation of this file.
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 : */