Print the information specified by the format string, FORMAT, calling PRINT_FUNC for each %-directive encountered. Return zero upon success, nonzero upon failure. */
| 1127 | calling PRINT_FUNC for each %-directive encountered. |
| 1128 | Return zero upon success, nonzero upon failure. */ |
| 1129 | NODISCARD |
| 1130 | static bool |
| 1131 | print_it (char const *format, int fd, char const *filename, |
| 1132 | bool (*print_func) (char *, size_t, char, char, |
| 1133 | int, char const *, void const *), |
| 1134 | void const *data) |
| 1135 | { |
| 1136 | bool fail = false; |
| 1137 | |
| 1138 | /* Add 2 to accommodate our conversion of the stat '%s' format string |
| 1139 | to the longer printf '%llu' one. */ |
| 1140 | enum |
| 1141 | { |
| 1142 | MAX_ADDITIONAL_BYTES = |
| 1143 | (MAX (sizeof "jd", |
| 1144 | MAX (sizeof "jo", MAX (sizeof "ju", sizeof "jx"))) |
| 1145 | - 1) |
| 1146 | }; |
| 1147 | size_t n_alloc = strlen (format) + MAX_ADDITIONAL_BYTES + 1; |
| 1148 | char *dest = xmalloc (n_alloc); |
| 1149 | for (char const *b = format; *b; b++) |
| 1150 | { |
| 1151 | switch (*b) |
| 1152 | { |
| 1153 | case '%': |
| 1154 | { |
| 1155 | size_t len = format_code_offset (b); |
| 1156 | char fmt_char = *(b + len); |
| 1157 | char mod_char = 0; |
| 1158 | memcpy (dest, b, len); |
| 1159 | b += len; |
| 1160 | |
| 1161 | switch (fmt_char) |
| 1162 | { |
| 1163 | case '\0': |
| 1164 | --b; |
| 1165 | FALLTHROUGH; |
| 1166 | case '%': |
| 1167 | if (1 < len) |
| 1168 | { |
| 1169 | dest[len] = fmt_char; |
| 1170 | dest[len + 1] = '\0'; |
| 1171 | error (EXIT_FAILURE, 0, _("%s: invalid directive"), |
| 1172 | quote (dest)); |
| 1173 | } |
| 1174 | putchar ('%'); |
| 1175 | break; |
| 1176 | case 'H': |
| 1177 | case 'L': |
| 1178 | mod_char = fmt_char; |
| 1179 | fmt_char = *(b + 1); |
| 1180 | if (print_func == print_stat |
| 1181 | && (fmt_char == 'd' || fmt_char == 'r')) |
| 1182 | { |
| 1183 | b++; |
| 1184 | } |
| 1185 | else |
| 1186 | { |
no test coverage detected