libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2010, 2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU Lesser General Public License as 00007 * published by the Free Software Foundation; either version 3 of the 00008 * License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/assert.h> 00020 #include <libexplain/ac/stdio.h> 00021 #include <libexplain/ac/string.h> 00022 00023 #include <libexplain/buffer/einval.h> 00024 00025 00026 void 00027 explain_buffer_einval_format_string(explain_string_buffer_t *sb, 00028 const char *caption, const char *value, size_t errpos) 00029 { 00030 const char *end; 00031 const char *percent; 00032 size_t nbytes; 00033 explain_string_buffer_t yuck_sb; 00034 char yuck[1000]; 00035 const char *internal; 00036 00037 /* 00038 * The sequences "...%l%..." and "...%l%" are errors, but we don't 00039 * want the last %, we want the first. Thus we move back one. 00040 * But must also be wary of "...%" or "...%l" i.e. unterminated 00041 * specifications. 00042 * 00043 * The unterminated cases that start with '%' are hard to detect, so 00044 * intially we ignore them. 00045 * 00046 * The last character is the offending character, or the actual 00047 * specifier (which is not in the "internal" set), step over it (it 00048 * could also be a percent). 00049 */ 00050 assert(errpos > 0); 00051 end = value + errpos; 00052 percent = end - 1; 00053 00054 /* 00055 * The errpos indicates the *end* of the broken format, 00056 * hunt backwards for the starting '%'. 00057 */ 00058 internal = " #$'+-.0123456789ILZhjlqtz"; 00059 while (percent > value) 00060 { 00061 unsigned char c; 00062 --percent; 00063 c = *percent; 00064 if (c == '%') 00065 break; 00066 if (!strchr(internal, c)) 00067 { 00068 /* 00069 * Oh dear, the error is uglier than we thought. 00070 * Probably an unterminated specifier (like "...%"). 00071 */ 00072 percent = end - 1; 00073 break; 00074 } 00075 } 00076 00077 /* 00078 * Build ourselves a quoted string. 00079 */ 00080 explain_string_buffer_init(&yuck_sb, yuck, sizeof(yuck)); 00081 nbytes = end - percent; 00082 explain_string_buffer_puts_quoted_n(&yuck_sb, percent, nbytes); 00083 00084 /* 00085 * Explain why it is broken. 00086 */ 00087 explain_string_buffer_printf_gettext 00088 ( 00089 sb, 00090 /* 00091 * xgettext: This error message is issued when a system call 00092 * reports a problem with a printf(3)-style format string, 00093 * in the case where a format specifier is malformed. 00094 * 00095 * %1$s => the name of the offending system-call argument. 00096 * %2$s => the offending format specification (already quoted) 00097 * %3$ld => the byte position of the invalid format specifier within 00098 * the format string 00099 */ 00100 i18n("within the %s argument the conversion specification %s, " 00101 "starting at position %ld, is not valid"), 00102 caption, 00103 yuck, 00104 (long)(percent - value) 00105 ); 00106 } 00107 00108 00109 void 00110 explain_buffer_einval_format_string_hole(explain_string_buffer_t *sb, 00111 const char *caption, int hole_index) 00112 { 00113 char buf[30]; 00114 00115 snprintf(buf, sizeof(buf), "\"%%%d$\"", hole_index); 00116 explain_string_buffer_printf_gettext 00117 ( 00118 sb, 00119 /* 00120 * xgettext: This error message is issued when a system call 00121 * reports a problem with a printf(3)-style format string, 00122 * in the case where a %n$ specifier has not been used. 00123 * 00124 * %1$s => the name of the offending system-call argument. 00125 * %2$s => the argument position of the missing format specifier, 00126 * already quoted (including percent and dollar sign). 00127 */ 00128 i18n("the %s argument does not contain a %s specification"), 00129 caption, 00130 buf 00131 ); 00132 } 00133 00134 00135 /* vim: set ts=8 sw=4 et : */