diff --git a/configure.ac b/configure.ac index 48fdaf350..c1d02404b 100644 --- a/configure.ac +++ b/configure.ac @@ -310,7 +310,7 @@ AC_STRUCT_DIRENT_D_TYPE # Check for presense of various functions used by fish # -AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp fwprintf ) +AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp ) AC_CHECK_FUNCS( futimes wcwidth wcswidth wcstok fputwc fgetwc ) AC_CHECK_FUNCS( wcstol wcslcat wcslcpy lrand48_r killpg ) AC_CHECK_FUNCS( backtrace backtrace_symbols_fd getifaddrs ) diff --git a/src/fallback.cpp b/src/fallback.cpp index 15c5614f5..518e907a9 100644 --- a/src/fallback.cpp +++ b/src/fallback.cpp @@ -90,417 +90,6 @@ char *tparm_solaris_kludge(char *str, ...) { #endif -#ifndef HAVE_FWPRINTF -#define INTERNAL_FWPRINTF 1 -#endif - -#ifdef INTERNAL_FWPRINTF - -/// Internal function for the wprintf fallbacks. USed to write the specified number of spaces. -static void pad(void (*writer)(wchar_t), int count) { - int i; - if (count < 0) return; - - for (i = 0; i < count; i++) { - writer(L' '); - } -} - -/// Generic formatting function. All other string formatting functions are secretly a wrapper around -/// this function. vgprintf does not implement all the filters supported by printf, only those that -/// are currently used by fish. vgprintf internally uses snprintf to implement the number outputs, -/// such as %f and %x. -/// -/// Currently supported functionality: -/// -/// - precision specification, both through .* and .N -/// - Padding through * and N -/// - Right padding using the - prefix -/// - long versions of all filters thorugh l and ll prefix -/// - Character output using %c -/// - String output through %s -/// - Floating point number output through %f -/// - Integer output through %d, %i, %u, %o, %x and %X -/// -/// For a full description on the usage of *printf, see use 'man 3 printf'. -static int vgwprintf(void (*writer)(wchar_t), const wchar_t *filter, va_list va) { - const wchar_t *filter_org = filter; - int count = 0; - - for (; *filter; filter++) { - if (*filter == L'%') { - int is_long = 0; - int width = -1; - filter++; - int loop = 1; - int precision = -1; - int pad_left = 1; - - if (iswdigit(*filter)) { - width = 0; - while ((*filter >= L'0') && (*filter <= L'9')) { - width = 10 * width + (*filter++ - L'0'); - } - } - - while (loop) { - switch (*filter) { - case L'l': { - // Long variable. - is_long++; - filter++; - break; - } - case L'*': { - // Set minimum field width. - width = va_arg(va, int); - filter++; - break; - } - case L'-': { - filter++; - pad_left = 0; - break; - } - case L'.': { - // Set precision. - filter++; - if (*filter == L'*') { - precision = va_arg(va, int); - } else { - precision = 0; - while ((*filter >= L'0') && (*filter <= L'9')) { - precision = 10 * precision + (*filter++ - L'0'); - } - } - break; - } - default: { - loop = 0; - break; - } - } - } - - switch (*filter) { - case L'c': { - wchar_t c; - - if ((width >= 0) && pad_left) { - pad(writer, width - 1); - count += maxi(width - 1, 0); - } - - c = is_long ? va_arg(va, wint_t) : btowc(va_arg(va, int)); - if (precision != 0) writer(c); - - if ((width >= 0) && !pad_left) { - pad(writer, width - 1); - count += maxi(width - 1, 0); - } - - count++; - break; - } - case L's': { - wchar_t *ss = 0; - wcstring wide_ss; - if (is_long) { - ss = va_arg(va, wchar_t *); - } else { - char *ns = va_arg(va, char *); - - if (ns) { - wide_ss = str2wcstring(ns); - ss = wide_ss.c_str(); - } - } - - if (!ss) { - return -1; - } - - if ((width >= 0) && pad_left) { - pad(writer, width - wcslen(ss)); - count += maxi(width - wcslen(ss), 0); - } - - wchar_t *s = ss; - int precount = count; - - while (*s) { - if ((precision > 0) && (precision <= (count - precount))) break; - writer(*(s++)); - count++; - } - - if ((width >= 0) && !pad_left) { - pad(writer, width - wcslen(ss)); - count += maxi(width - wcslen(ss), 0); - } - - break; - } - case L'd': - case L'i': - case L'o': - case L'u': - case L'x': - case L'X': { - char str[33]; - char *pos; - char format[16]; - int len; - - format[0] = 0; - strcat(format, "%"); - if (precision >= 0) strcat(format, ".*"); - switch (is_long) { - case 2: { - strcat(format, "ll"); - break; - } - case 1: { - strcat(format, "l"); - break; - } - } - - len = strlen(format); - format[len++] = (char)*filter; - format[len] = 0; - - switch (*filter) { - case L'd': - case L'i': { - switch (is_long) { - case 0: { - int d = va_arg(va, int); - if (precision >= 0) - snprintf(str, 32, format, precision, d); - else - snprintf(str, 32, format, d); - - break; - } - case 1: { - long d = va_arg(va, long); - if (precision >= 0) - snprintf(str, 32, format, precision, d); - else - snprintf(str, 32, format, d); - break; - } - case 2: { - long long d = va_arg(va, long long); - if (precision >= 0) - snprintf(str, 32, format, precision, d); - else - snprintf(str, 32, format, d); - break; - } - default: { - debug(0, L"Invalid length modifier in string %ls\n", - filter_org); - return -1; - } - } - break; - } - - case L'u': - case L'o': - case L'x': - case L'X': { - switch (is_long) { - case 0: { - unsigned d = va_arg(va, unsigned); - if (precision >= 0) - snprintf(str, 32, format, precision, d); - else - snprintf(str, 32, format, d); - break; - } - case 1: { - unsigned long d = va_arg(va, unsigned long); - if (precision >= 0) - snprintf(str, 32, format, precision, d); - else - snprintf(str, 32, format, d); - break; - } - case 2: { - unsigned long long d = va_arg(va, unsigned long long); - if (precision >= 0) - snprintf(str, 32, format, precision, d); - else - snprintf(str, 32, format, d); - break; - } - default: { - debug(0, L"Invalid length modifier in string %ls\n", - filter_org); - return -1; - } - } - break; - } - default: { - debug(0, L"Invalid filter %ls in string %ls\n", *filter, filter_org); - return -1; - } - } - - if ((width >= 0) && pad_left) { - int l = maxi(width - strlen(str), 0); - pad(writer, l); - count += l; - } - - pos = str; - - while (*pos) { - writer(*(pos++)); - count++; - } - - if ((width >= 0) && !pad_left) { - int l = maxi(width - strlen(str), 0); - pad(writer, l); - count += l; - } - - break; - } - - case L'f': { - char str[32]; - char *pos; - double val = va_arg(va, double); - - if (precision >= 0) { - if (width >= 0) { - snprintf(str, 32, "%*.*f", width, precision, val); - } else { - snprintf(str, 32, "%.*f", precision, val); - } - } else { - if (width >= 0) { - snprintf(str, 32, "%*f", width, val); - } else { - snprintf(str, 32, "%f", val); - } - } - - pos = str; - - while (*pos) { - writer(*(pos++)); - count++; - } - - break; - } - - case L'n': { - int *n = va_arg(va, int *); - - *n = count; - break; - } - case L'%': { - writer('%'); - count++; - break; - } - default: { - debug(0, L"Unknown switch %lc in string %ls\n", *filter, filter_org); - return -1; - } - } - } else { - writer(*filter); - count++; - } - } - - return count; -} - -/// Holds data for swprintf writer. -static struct { - int count; - int max; - wchar_t *pos; -} sw_data; - -/// Writers for string output. -static void sw_writer(wchar_t c) { - if (sw_data.count < sw_data.max) *(sw_data.pos++) = c; - sw_data.count++; -} - -int vswprintf(wchar_t *out, size_t n, const wchar_t *filter, va_list va) { - int written; - - sw_data.pos = out; - sw_data.max = n; - sw_data.count = 0; - written = vgwprintf(&sw_writer, filter, va); - if (written < n) { - *sw_data.pos = 0; - } else { - written = -1; - } - - return written; -} - -int swprintf(wchar_t *out, size_t n, const wchar_t *filter, ...) { - va_list va; - int written; - - va_start(va, filter); - written = vswprintf(out, n, filter, va); - va_end(va); - return written; -} - -/// Holds auxiliary data for fwprintf and wprintf writer. -static FILE *fw_data; - -static void fw_writer(wchar_t c) { fputwc(c, fw_data); } - -/// Writers for file output. -int vfwprintf(FILE *f, const wchar_t *filter, va_list va) { - fw_data = f; - return vgwprintf(&fw_writer, filter, va); -} - -int fwprintf(FILE *f, const wchar_t *filter, ...) { - va_list va; - int written; - - va_start(va, filter); - written = vfwprintf(f, filter, va); - va_end(va); - return written; -} - -int vwprintf(const wchar_t *filter, va_list va) { return vfwprintf(stdout, filter, va); } - -int wprintf(const wchar_t *filter, ...) { - va_list va; - int written; - - va_start(va, filter); - written = vwprintf(filter, va); - va_end(va); - return written; -} - -#endif - #ifndef HAVE_FGETWC wint_t fgetwc(FILE *stream) { wchar_t res; diff --git a/src/fallback.h b/src/fallback.h index 241edb5ac..13caf0b39 100644 --- a/src/fallback.h +++ b/src/fallback.h @@ -63,38 +63,6 @@ struct winsize { char *tparm_solaris_kludge(char *str, ...); #endif -#ifndef HAVE_FWPRINTF -/// Print formated string. Some operating systems (Like NetBSD) do not have wide string formating -/// functions. Therefore we implement our own. Not at all complete. Supports wide and narrow -/// characters, strings and decimal numbers, position (%n), field width and precision. -int fwprintf(FILE *f, const wchar_t *format, ...); - -/// Print formated string. Some operating systems (Like NetBSD) do not have wide string formating -/// functions. Therefore we define our own. Not at all complete. Supports wide and narrow -/// characters, strings and decimal numbers, position (%n), field width and precision. -int swprintf(wchar_t *str, size_t l, const wchar_t *format, ...); - -/// Print formated string. Some operating systems (Like NetBSD) do not have wide string formating -/// functions. Therefore we define our own. Not at all complete. Supports wide and narrow -/// characters, strings and decimal numbers, position (%n), field width and precision. -int wprintf(const wchar_t *format, ...); - -/// Print formated string. Some operating systems (Like NetBSD) do not have wide string formating -/// functions. Therefore we define our own. Not at all complete. Supports wide and narrow -/// characters, strings and decimal numbers, position (%n), field width and precision. -int vwprintf(const wchar_t *filter, va_list va); - -/// Print formated string. Some operating systems (Like NetBSD) do not have wide string formating -/// functions. Therefore we define our own. Not at all complete. Supports wide and narrow -/// characters, strings and decimal numbers, position (%n), field width and precision. -int vfwprintf(FILE *f, const wchar_t *filter, va_list va); - -/// Print formated string. Some operating systems (Like NetBSD) do not have wide string formating -/// functions. Therefore we define our own. Not at all complete. Supports wide and narrow -/// characters, strings and decimal numbers, position (%n), field width and precision. -int vswprintf(wchar_t *out, size_t n, const wchar_t *filter, va_list va); -#endif - #ifndef HAVE_FGETWC // Fallback implementation of fgetwc. wint_t fgetwc(FILE *stream);