/* * extended printf functions and specifiers * * Copyright (C) 2010 by James Maki * * Author: James Maki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #define _GNU_SOURCE #include #include #include #include #include "xprintf.h" #include "log.h" #if HAVE_REGISTER_PRINTF_SPECIFIER int print_buffer_inspect_arginfo(const struct printf_info *info, size_t n, int *argtypes, int *size) #else int print_buffer_inspect_arginfo(const struct printf_info *info, size_t n, int *argtypes) #endif { if (n > 0) { argtypes[0] = PA_POINTER; #if HAVE_REGISTER_PRINTF_SPECIFIER size[0] = sizeof(void *); #endif } return 1; } static const char *__char_inspect[] = { "\\x00", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\a", "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "\\x0E", "\\x0F", "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17", "\\x18", "\\x19", "\\x1A", "\\x1B", "\\x1C", "\\x1D", "\\x1E", "\\x1F", " ", "!", "\\\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "[", "\\\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "\\x7F", "\\x80", "\\x81", "\\x82", "\\x83", "\\x84", "\\x85", "\\x86", "\\x87", "\\x88", "\\x89", "\\x8A", "\\x8B", "\\x8C", "\\x8D", "\\x8E", "\\x8F", "\\x90", "\\x91", "\\x92", "\\x93", "\\x94", "\\x95", "\\x96", "\\x97", "\\x98", "\\x99", "\\x9A", "\\x9B", "\\x9C", "\\x9D", "\\x9E", "\\x9F", "\\xA0", "\\xA1", "\\xA2", "\\xA3", "\\xA4", "\\xA5", "\\xA6", "\\xA7", "\\xA8", "\\xA9", "\\xAA", "\\xAB", "\\xAC", "\\xAD", "\\xAE", "\\xAF", "\\xB0", "\\xB1", "\\xB2", "\\xB3", "\\xB4", "\\xB5", "\\xB6", "\\xB7", "\\xB8", "\\xB9", "\\xBA", "\\xBB", "\\xBC", "\\xBD", "\\xBE", "\\xBF", "\\xC0", "\\xC1", "\\xC2", "\\xC3", "\\xC4", "\\xC5", "\\xC6", "\\xC7", "\\xC8", "\\xC9", "\\xCA", "\\xCB", "\\xCC", "\\xCD", "\\xCE", "\\xCF", "\\xD0", "\\xD1", "\\xD2", "\\xD3", "\\xD4", "\\xD5", "\\xD6", "\\xD7", "\\xD8", "\\xD9", "\\xDA", "\\xDB", "\\xDC", "\\xDD", "\\xDE", "\\xDF", "\\xE0", "\\xE1", "\\xE2", "\\xE3", "\\xE4", "\\xE5", "\\xE6", "\\xE7", "\\xE8", "\\xE9", "\\xEA", "\\xEB", "\\xEC", "\\xED", "\\xEE", "\\xEF", "\\xF0", "\\xF1", "\\xF2", "\\xF3", "\\xF4", "\\xF5", "\\xF6", "\\xF7", "\\xF8", "\\xF9", "\\xFA", "\\xFB", "\\xFC", "\\xFD", "\\xFE", "\\xFF", }; int print_buffer_inspect(FILE *stream, const struct printf_info *info, const void *const *args) { int i; int total; char *arg; char *buf; int prec = info->prec; arg = (char *) *((const char **) (args[0])); if (prec < 0) { prec = strlen(arg); } total = 0; for (i = 0; i < prec; i++) { total += strlen(__char_inspect[((unsigned char *) arg)[i]]); } buf = alloca(total + 1); if (!buf) { return -1; } *buf = '\0'; for (i = 0; i < prec; i++) { strcat(buf, __char_inspect[((unsigned char *) arg)[i]]); } total = fprintf(stream, "%*s", (info->left ? -info->width : info->width), buf); return total; } #if HAVE_REGISTER_PRINTF_SPECIFIER int print_buffer_bin_arginfo(const struct printf_info *info, size_t n, int *argtypes, int *size) #else int print_buffer_bin_arginfo(const struct printf_info *info, size_t n, int *argtypes) #endif { if (n > 0) { argtypes[0] = PA_POINTER; #if HAVE_REGISTER_PRINTF_SPECIFIER size[0] = sizeof(void *); #endif } return 1; } int print_buffer_bin(FILE *stream, const struct printf_info *info, const void *const *args) { int i; int j; int total; char *arg; unsigned char c; int prec = info->prec; char *buf; arg = (char *) *((const char **) (args[0])); if (prec < 0) { prec = strlen(arg); } buf = alloca(prec * 8 + 1); if (!buf) { return -1; } total = 0; for (i = 0; i < prec; i++) { c = ((unsigned char *) arg)[i]; for (j = 7; j >= 0; j--) { buf[total++] = (c & (1 << j)) ? '1' : '0'; } } if (total) { buf[total] = '\0'; } total = fprintf(stream, "%*s", (info->left ? -info->width : info->width), buf); return total; } int xprintf_init() { #if HAVE_REGISTER_PRINTF_SPECIFIER register_printf_specifier(XPRINTF_INSPECT_SPEC, print_buffer_inspect, print_buffer_inspect_arginfo); register_printf_specifier(XPRINTF_BIN_SPEC, print_buffer_bin, print_buffer_bin_arginfo); #else register_printf_function(XPRINTF_INSPECT_SPEC, print_buffer_inspect, print_buffer_inspect_arginfo); register_printf_function(XPRINTF_BIN_SPEC, print_buffer_bin, print_buffer_bin_arginfo); #endif return 0; }