From 14fb44b17123b27e562379f51b75ee889982688d Mon Sep 17 00:00:00 2001 From: James Maki Date: Fri, 23 Apr 2010 11:58:20 -0500 Subject: initial commit --- src/xprintf.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 src/xprintf.c (limited to 'src/xprintf.c') diff --git a/src/xprintf.c b/src/xprintf.c new file mode 100644 index 0000000..8fbfab6 --- /dev/null +++ b/src/xprintf.c @@ -0,0 +1,217 @@ +/* + * 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; +} -- cgit v1.2.3