diff options
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | builtin.c | 3 | ||||
-rw-r--r-- | builtin_commandline.c | 3 | ||||
-rw-r--r-- | builtin_complete.c | 3 | ||||
-rw-r--r-- | builtin_set.c | 3 | ||||
-rw-r--r-- | builtin_ulimit.c | 3 | ||||
-rw-r--r-- | common.c | 3 | ||||
-rw-r--r-- | complete.c | 3 | ||||
-rw-r--r-- | env.c | 3 | ||||
-rw-r--r-- | env_universal.c | 3 | ||||
-rw-r--r-- | env_universal_common.c | 3 | ||||
-rw-r--r-- | event.c | 3 | ||||
-rw-r--r-- | exec.c | 3 | ||||
-rw-r--r-- | expand.c | 3 | ||||
-rw-r--r-- | fallback.c | 882 | ||||
-rw-r--r-- | fallback.h | 192 | ||||
-rw-r--r-- | fish_pager.c | 3 | ||||
-rw-r--r-- | fish_tests.c | 3 | ||||
-rw-r--r-- | fishd.c | 3 | ||||
-rw-r--r-- | function.c | 3 | ||||
-rw-r--r-- | halloc.c | 3 | ||||
-rw-r--r-- | halloc_util.c | 3 | ||||
-rw-r--r-- | highlight.c | 3 | ||||
-rw-r--r-- | history.c | 3 | ||||
-rw-r--r-- | input.c | 3 | ||||
-rw-r--r-- | input_common.c | 3 | ||||
-rw-r--r-- | intern.c | 3 | ||||
-rw-r--r-- | io.c | 3 | ||||
-rw-r--r-- | kill.c | 3 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | mimedb.c | 3 | ||||
-rw-r--r-- | output.c | 13 | ||||
-rw-r--r-- | parse_util.c | 3 | ||||
-rw-r--r-- | parser.c | 3 | ||||
-rw-r--r-- | proc.c | 3 | ||||
-rw-r--r-- | reader.c | 3 | ||||
-rw-r--r-- | sanity.c | 3 | ||||
-rw-r--r-- | set_color.c | 1 | ||||
-rw-r--r-- | signal.c | 3 | ||||
-rw-r--r-- | tokenizer.c | 3 | ||||
-rw-r--r-- | translate.c | 3 | ||||
-rw-r--r-- | util.c | 3 | ||||
-rw-r--r-- | wgetopt.c | 1 | ||||
-rw-r--r-- | wildcard.c | 3 | ||||
-rw-r--r-- | wutil.c | 831 | ||||
-rw-r--r-- | wutil.h | 178 |
46 files changed, 1199 insertions, 1015 deletions
diff --git a/Makefile.in b/Makefile.in index 7c0888e3..5a906137 100644 --- a/Makefile.in +++ b/Makefile.in @@ -57,7 +57,7 @@ ETC_DIR_INSTALL = etc/fish_interactive.fish # Set to 1 if we have gettext HAVE_GETTEXT=@HAVE_GETTEXT@ -CORE_OBJS := util.o common.o halloc.o halloc_util.o +CORE_OBJS := util.o common.o halloc.o halloc_util.o fallback.o # All objects used by fish, that are compiled from an ordinary .c file # using an ordinary .h file. @@ -38,7 +38,10 @@ #include <time.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "builtin.h" #include "function.h" diff --git a/builtin_commandline.c b/builtin_commandline.c index 224b7e7d..500a27de 100644 --- a/builtin_commandline.c +++ b/builtin_commandline.c @@ -12,7 +12,10 @@ Functions used for implementing the commandline builtin. #include <signal.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "builtin.h" #include "common.h" diff --git a/builtin_complete.c b/builtin_complete.c index e9f315aa..13877c92 100644 --- a/builtin_complete.c +++ b/builtin_complete.c @@ -12,7 +12,10 @@ Functions used for implementing the complete builtin. #include <signal.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "builtin.h" #include "common.h" diff --git a/builtin_set.c b/builtin_set.c index 3a2f7545..5383456e 100644 --- a/builtin_set.c +++ b/builtin_set.c @@ -12,7 +12,10 @@ Functions used for implementing the set builtin. #include <signal.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "builtin.h" #include "env.h" diff --git a/builtin_ulimit.c b/builtin_ulimit.c index f20e7ec8..13af9cd5 100644 --- a/builtin_ulimit.c +++ b/builtin_ulimit.c @@ -13,7 +13,10 @@ Functions used for implementing the ulimit builtin. #include <errno.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "builtin.h" #include "common.h" #include "wgetopt.h" @@ -6,6 +6,7 @@ parts of fish. #include "config.h" + #include <stdlib.h> #include <termios.h> #include <wchar.h> @@ -50,7 +51,9 @@ parts of fish. #include <ncurses/term.h> #endif +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "common.h" #include "expand.h" @@ -21,7 +21,10 @@ #include <wchar.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "tokenizer.h" #include "wildcard.h" #include "proc.h" @@ -33,7 +33,10 @@ #include <errno.h> + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "proc.h" #include "common.h" diff --git a/env_universal.c b/env_universal.c index ab817e4d..48e0697d 100644 --- a/env_universal.c +++ b/env_universal.c @@ -1,5 +1,6 @@ #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <wchar.h> @@ -26,7 +27,9 @@ #include <signal.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" #include "env_universal_common.h" diff --git a/env_universal_common.c b/env_universal_common.c index 07123e0c..2d39fc51 100644 --- a/env_universal_common.c +++ b/env_universal_common.c @@ -7,6 +7,7 @@ */ #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <wchar.h> @@ -27,7 +28,9 @@ #include <signal.h> #include <sys/stat.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" #include "env_universal_common.h" @@ -12,7 +12,10 @@ #include <string.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "function.h" #include "proc.h" @@ -22,7 +22,10 @@ #include <dirent.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" #include "proc.h" @@ -27,7 +27,10 @@ parameter expansion. #endif #include "config.h" + +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" #include "env.h" diff --git a/fallback.c b/fallback.c new file mode 100644 index 00000000..de9fe23a --- /dev/null +++ b/fallback.c @@ -0,0 +1,882 @@ +/** + This file only contains fallback implementations of functions which + have been found to be missing or broken by the configuration + scripts. +*/ + +#include "config.h" + + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <wchar.h> +#include <wctype.h> +#include <string.h> +#include <dirent.h> +#include <stdarg.h> +#include <limits.h> + +#if HAVE_NCURSES_H +#include <ncurses.h> +#else +#include <curses.h> +#endif + +#if HAVE_TERMIO_H +#include <termio.h> +#endif + +#if HAVE_TERM_H +#include <term.h> +#elif HAVE_NCURSES_TERM_H +#include <ncurses/term.h> +#endif + +#ifdef TPUTS_KLUDGE + +int tputs(const char *str, int affcnt, int (*putc)(tputs_arg_t)) +{ + while( *str ) + { + putc( *str++ ); + } +} + +#endif + + + +#if !HAVE_FWPRINTF + +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; + if( is_long ) + { + ss = va_arg(va, wchar_t *); + } + else + { + char *ns = va_arg(va, char*); + + if( ns ) + { + ss = str2wcs( ns ); + } + } + + 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 ); + } + + if( !is_long ) + free( ss ); + + 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 ) +{ + putwc( 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=0; + mbstate_t state; + memset (&state, '\0', sizeof (state)); + + while(1) + { + int b = fgetc( stream ); + char bb; + + int sz; + + if( b == EOF ) + return WEOF; + + bb=b; + + sz = mbrtowc( &res, &bb, 1, &state ); + + switch( sz ) + { + case -1: + memset (&state, '\0', sizeof (state)); + return WEOF; + + case -2: + break; + case 0: + return 0; + default: + return res; + } + } + +} + + +wint_t getwc(FILE *stream) +{ + return fgetwc( stream ); +} + + +#endif + +#ifndef HAVE_FPUTWC + +wint_t fputwc(wchar_t wc, FILE *stream) +{ + int res; + char s[MB_CUR_MAX+1]; + memset( s, 0, MB_CUR_MAX+1 ); + wctomb( s, wc ); + res = fputs( s, stream ); + return res==EOF?WEOF:wc; +} + +wint_t putwc(wchar_t wc, FILE *stream) +{ + return fputwc( wc, stream ); +} + +#endif + +#ifndef HAVE_WCSTOK + +/* + Used by fallback wcstok. Borrowed from glibc +*/ +static size_t fish_wcsspn (const wchar_t *wcs, + const wchar_t *accept ) +{ + register const wchar_t *p; + register const wchar_t *a; + register size_t count = 0; + + for (p = wcs; *p != L'\0'; ++p) + { + for (a = accept; *a != L'\0'; ++a) + if (*p == *a) + break; + + if (*a == L'\0') + return count; + else + ++count; + } + return count; +} + +/* + Used by fallback wcstok. Borrowed from glibc +*/ +static wchar_t *fish_wcspbrk (const wchar_t *wcs, const wchar_t *accept) +{ + while (*wcs != L'\0') + if (wcschr (accept, *wcs) == NULL) + ++wcs; + else + return (wchar_t *) wcs; + return NULL; +} + +/* + Fallback wcstok implementation. Borrowed from glibc. +*/ +wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **save_ptr) +{ + wchar_t *result; + + if (wcs == NULL) + { + if (*save_ptr == NULL) + { + errno = EINVAL; + return NULL; + } + else + wcs = *save_ptr; + } + + /* Scan leading delimiters. */ + wcs += fish_wcsspn (wcs, delim); + + if (*wcs == L'\0') + { + *save_ptr = NULL; + return NULL; + } + + /* Find the end of the token. */ + result = wcs; + + wcs = fish_wcspbrk (result, delim); + + if (wcs == NULL) + { + /* This token finishes the string. */ + *save_ptr = NULL; + } + else + { + /* Terminate the token and make *SAVE_PTR point past it. */ + *wcs = L'\0'; + *save_ptr = wcs + 1; + } + return result; +} + +#endif + +#ifndef HAVE_WCSDUP +wchar_t *wcsdup( const wchar_t *in ) +{ + size_t len=wcslen(in); + wchar_t *out = malloc( sizeof( wchar_t)*(len+1)); + if( out == 0 ) + { + return 0; + } + + memcpy( out, in, sizeof( wchar_t)*(len+1)); + return out; + +} +#endif + +#ifndef HAVE_WCSLEN +size_t wcslen(const wchar_t *in) +{ + const wchar_t *end=in; + while( *end ) + end++; + return end-in; +} +#endif + + +#ifndef HAVE_WCSCASECMP +int wcscasecmp( const wchar_t *a, const wchar_t *b ) +{ + if( *a == 0 ) + { + return (*b==0)?0:-1; + } + else if( *b == 0 ) + { + return 1; + } + int diff = towlower(*a)-towlower(*b); + if( diff != 0 ) + return diff; + else + return wcscasecmp( a+1,b+1); +} +#endif + + +#ifndef HAVE_WCSNCASECMP +int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count ) +{ + if( count == 0 ) + return 0; + + if( *a == 0 ) + { + return (*b==0)?0:-1; + } + else if( *b == 0 ) + { + return 1; + } + int diff = towlower(*a)-towlower(*b); + if( diff != 0 ) + return diff; + else + return wcsncasecmp( a+1,b+1, count-1); +} +#endif + +#ifndef HAVE_WCWIDTH +int wcwidth( wchar_t c ) +{ + if( c < 32 ) + return 0; + if ( c == 127 ) + return 0; + return 1; +} +#endif + +#ifndef HAVE_WCSNDUP +wchar_t *wcsndup( const wchar_t *in, int c ) +{ + wchar_t *res = malloc( sizeof(wchar_t)*(c+1) ); + if( res == 0 ) + { + return 0; + } + wcsncpy( res, in, c+1 ); + res[c] = L'\0'; + return res; +} +#endif + +long convert_digit( wchar_t d, int base ) +{ + long res=-1; + if( (d <= L'9') && (d >= L'0') ) + { + res = d - L'0'; + } + else if( (d <= L'z') && (d >= L'a') ) + { + res = d + 10 - L'a'; + } + else if( (d <= L'Z') && (d >= L'A') ) + { + res = d + 10 - L'A'; + } + if( res >= base ) + { + res = -1; + } + + return res; +} + +#ifndef HAVE_WCSTOL +long wcstol(const wchar_t *nptr, + wchar_t **endptr, + int base) +{ + long long res=0; + int is_set=0; + if( base > 36 ) + { + errno = EINVAL; + return 0; + } + + while( 1 ) + { + long nxt = convert_digit( *nptr, base ); + if( endptr != 0 ) + *endptr = (wchar_t *)nptr; + if( nxt < 0 ) + { + if( !is_set ) + { + errno = EINVAL; + } + return res; + } + res = (res*base)+nxt; + is_set = 1; + if( res > LONG_MAX ) + { + errno = ERANGE; + return LONG_MAX; + } + if( res < LONG_MIN ) + { + errno = ERANGE; + return LONG_MIN; + } + nptr++; + } +} +#endif + + diff --git a/fallback.h b/fallback.h new file mode 100644 index 00000000..c4e1312a --- /dev/null +++ b/fallback.h @@ -0,0 +1,192 @@ + +#ifndef FISH_FALLBACK_H +#define FISH_FALLBACK_H + +#ifdef TPUTS_KLUDGE + +/** + Linux on PPC seems to have a tputs implementation that sometimes + behaves strangely. This fallback seems to fix things. +*/ +int tputs(const char *str, int affcnt, int (*putc)(tputs_arg_t)); + +#endif + +/* + Here follows the prototypes for fallback implementations of various + standarcs libc functions relating to wide character support. Some of + these prototypes are always defined, since some libc versions + include the code, but you have to use special magical #defines for + the prototype to appear. +*/ + +#if !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); + +/** + Fallback implementation of getwc +*/ +wint_t getwc(FILE *stream); + +#endif + +#ifndef HAVE_FPUTWC + +/** + Fallback implementation of fputwc +*/ +wint_t fputwc(wchar_t wc, FILE *stream); +/** + Fallback implementation of putwc +*/ +wint_t putwc(wchar_t wc, FILE *stream); + +#endif + +#ifndef HAVE_WCSTOK +/** + Fallback implementation of wcstok. Uses code borrowed from glibc. +*/ +wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr); + +#endif + +/** + Return the number of columns used by a character. This is a libc + function, but the prototype for this function is missing in some libc + implementations. + + Fish has a fallback implementation in case the implementation is + missing altogether. In locales without a native wcwidth, Unicode + is probably so broken that it isn't worth trying to implement a + real wcwidth. Therefore, the fallback wcwidth assumes any printing + character takes up one column and anything else uses 0 columns. +*/ +int wcwidth( wchar_t c ); + +/** + Create a duplicate string. Wide string version of strdup. Will + automatically exit if out of memory. +*/ +wchar_t *wcsdup(const wchar_t *in); + +size_t wcslen(const wchar_t *in); + +/** + Case insensitive string compare function. Wide string version of + strcasecmp. + + This implementation of wcscasecmp does not take into account + esoteric locales where uppercase and lowercase do not cleanly + transform between each other. Hopefully this should be fine since + fish only uses this function with one of the strings supplied by + fish and guaranteed to be a sane, english word. Using wcscasecmp on + a user-supplied string should be considered a bug. +*/ +int wcscasecmp( const wchar_t *a, const wchar_t *b ); + +/** + Case insensitive string compare function. Wide string version of + strncasecmp. + + This implementation of wcsncasecmp does not take into account + esoteric locales where uppercase and lowercase do not cleanly + transform between each other. Hopefully this should be fine since + fish only uses this function with one of the strings supplied by + fish and guaranteed to be a sane, english word. Using wcsncasecmp on + a user-supplied string should be considered a bug. +*/ +int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count ); + +/** + Returns a newly allocated wide character string wich is a copy of + the string in, but of length c or shorter. The returned string is + always null terminated, and the null is not included in the string + length. +*/ +wchar_t *wcsndup( const wchar_t *in, int c ); + +/** + Converts from wide char to digit in the specified base. If d is not + a valid digit in the specified base, return -1. +*/ +long convert_digit( wchar_t d, int base ); + +/** + Fallback implementation. Convert a wide character string to a + number in the specified base. This functions is the wide character + string equivalent of strtol. For bases of 10 or lower, 0..9 are + used to represent numbers. For bases below 36, a-z and A-Z are used + to represent numbers higher than 9. Higher bases than 36 are not + supported. +*/ +long wcstol(const wchar_t *nptr, + wchar_t **endptr, + int base); + + + +#endif diff --git a/fish_pager.c b/fish_pager.c index 5d9ef1ec..9fbf17fa 100644 --- a/fish_pager.c +++ b/fish_pager.c @@ -35,7 +35,10 @@ #include <signal.h> + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "common.h" #include "complete.h" diff --git a/fish_tests.c b/fish_tests.c index 2275eccd..7328d2c9 100644 --- a/fish_tests.c +++ b/fish_tests.c @@ -4,6 +4,7 @@ #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <wchar.h> @@ -26,7 +27,9 @@ #include <locale.h> #include <dirent.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "proc.h" #include "reader.h" @@ -41,6 +41,7 @@ time the original barrier request was sent have been received. #include "config.h" + #include <stdio.h> #include <stdlib.h> #include <wchar.h> @@ -61,7 +62,9 @@ time the original barrier request was sent have been received. #include <locale.h> #include <signal.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" #include "env_universal_common.h" @@ -9,8 +9,11 @@ #include <signal.h> #include "config.h" + #include "wutil.h" +#include "fallback.h" #include "util.h" + #include "function.h" #include "proc.h" #include "parser.h" @@ -8,10 +8,13 @@ #include "config.h" + #include <stdlib.h> #include <unistd.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "halloc.h" diff --git a/halloc_util.c b/halloc_util.c index 3213fd70..a5d8ae81 100644 --- a/halloc_util.c +++ b/halloc_util.c @@ -8,11 +8,14 @@ #include "config.h" + #include <stdlib.h> #include <unistd.h> #include <string.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "halloc.h" diff --git a/highlight.c b/highlight.c index 51f33665..6ebcb00f 100644 --- a/highlight.c +++ b/highlight.c @@ -12,7 +12,10 @@ #include <signal.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "highlight.h" #include "tokenizer.h" @@ -12,7 +12,10 @@ #include "config.h" + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "history.h" #include "common.h" @@ -43,7 +43,10 @@ implementation in fish is as of yet incomplete. #include <wctype.h> + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "reader.h" #include "proc.h" diff --git a/input_common.c b/input_common.c index 2f034e95..a7abc800 100644 --- a/input_common.c +++ b/input_common.c @@ -5,6 +5,7 @@ Implementation file for the low level input library */ #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -15,7 +16,9 @@ Implementation file for the low level input library #include <wchar.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" #include "input_common.h" @@ -5,12 +5,15 @@ */ #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <wchar.h> #include <unistd.h> +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "common.h" #include "intern.h" @@ -5,6 +5,7 @@ Utilities for io redirection. */ #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <wchar.h> @@ -31,7 +32,9 @@ Utilities for io redirection. #include <ncurses/term.h> #endif +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "exec.h" #include "common.h" @@ -18,7 +18,10 @@ #include "config.h" + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "kill.h" #include "proc.h" @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <wchar.h> @@ -40,7 +41,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <locale.h> #include <signal.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "reader.h" #include "builtin.h" @@ -21,6 +21,7 @@ license. Read the source code of the library for more information. #include "config.h" + #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -43,8 +44,10 @@ license. Read the source code of the library for more information. #endif #include "xdgmime.h" +#include "fallback.h" #include "util.h" + /** Location of the applications .desktop file, relative to a base mime directory */ @@ -38,7 +38,10 @@ #include <time.h> #include <wchar.h> + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "expand.h" #include "common.h" @@ -292,15 +295,7 @@ int writeb( tputs_arg_t b ) int writembs( char *str ) { -#ifdef TPUTS_KLUDGE - while( *str ) - { - out( *str ); - } -#else - tputs(str,1,writeb); -#endif - return 0; + return tputs(str,1,&writeb)==ERR?1:0; } int writech( wint_t ch ) diff --git a/parse_util.c b/parse_util.c index 18ffad8a..a326b646 100644 --- a/parse_util.c +++ b/parse_util.c @@ -6,6 +6,7 @@ #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <sys/types.h> @@ -17,7 +18,9 @@ #include <time.h> #include <assert.h> +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "common.h" #include "tokenizer.h" @@ -18,7 +18,10 @@ The fish parser. Contains functions for parsing code. #include <signal.h> #include "config.h" + +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" #include "proc.h" @@ -42,7 +42,10 @@ Some of the code in this file is based on code from the Glibc manual. #include <ncurses/term.h> #endif + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "proc.h" #include "common.h" @@ -59,7 +59,10 @@ commence. #include <assert.h> + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "highlight.h" #include "reader.h" @@ -14,7 +14,10 @@ #include "config.h" + +#include "fallback.h" #include "util.h" + #include "common.h" #include "sanity.h" #include "proc.h" diff --git a/set_color.c b/set_color.c index 5ac2d564..5228987e 100644 --- a/set_color.c +++ b/set_color.c @@ -1,5 +1,6 @@ #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -6,6 +6,7 @@ The library for various signal related issues #include "config.h" + #include <stdlib.h> #include <stdio.h> #include <sys/types.h> @@ -15,7 +16,9 @@ The library for various signal related issues #include <errno.h> #include "common.h" +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "signal.h" #include "event.h" diff --git a/tokenizer.c b/tokenizer.c index ee9f7eb2..8548852b 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -15,7 +15,10 @@ #include <string.h> #include <unistd.h> + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "tokenizer.h" #include "common.h" diff --git a/translate.c b/translate.c index 4a109ecd..23de015a 100644 --- a/translate.c +++ b/translate.c @@ -6,6 +6,7 @@ Translation library, internally uses catgets #include "config.h" + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -16,7 +17,9 @@ Translation library, internally uses catgets #endif #include "common.h" +#include "fallback.h" #include "util.h" + #include "halloc_util.h" #if HAVE_GETTEXT @@ -6,6 +6,7 @@ #include "config.h" + #include <stdio.h> #include <stdlib.h> #include <wchar.h> @@ -22,7 +23,9 @@ #include <errno.h> +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" @@ -94,6 +94,7 @@ #include "wutil.h" + /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. @@ -18,7 +18,10 @@ wildcards using **. #include <dirent.h> #include <errno.h> + +#include "fallback.h" #include "util.h" + #include "wutil.h" #include "complete.h" #include "common.h" @@ -20,7 +20,10 @@ #include <stdarg.h> #include <limits.h> + +#include "fallback.h" #include "util.h" + #include "common.h" #include "wutil.h" @@ -329,831 +332,3 @@ wchar_t *wrealpath(const wchar_t *pathname, wchar_t *resolved_path) } #endif - -#if !HAVE_FWPRINTF - -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; - if( is_long ) - { - ss = va_arg(va, wchar_t *); - } - else - { - char *ns = va_arg(va, char*); - - if( ns ) - { - ss = str2wcs( ns ); - } - } - - 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 ); - } - - if( !is_long ) - free( ss ); - - 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 ) -{ - putwc( 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=0; - mbstate_t state; - memset (&state, '\0', sizeof (state)); - - while(1) - { - int b = fgetc( stream ); - char bb; - - int sz; - - if( b == EOF ) - return WEOF; - - bb=b; - - sz = mbrtowc( &res, &bb, 1, &state ); - - switch( sz ) - { - case -1: - memset (&state, '\0', sizeof (state)); - return WEOF; - - case -2: - break; - case 0: - return 0; - default: - return res; - } - } - -} - - -wint_t getwc(FILE *stream) -{ - return fgetwc( stream ); -} - - -#endif - -#ifndef HAVE_FPUTWC - -wint_t fputwc(wchar_t wc, FILE *stream) -{ - int res; - char s[MB_CUR_MAX+1]; - memset( s, 0, MB_CUR_MAX+1 ); - wctomb( s, wc ); - res = fputs( s, stream ); - return res==EOF?WEOF:wc; -} - -wint_t putwc(wchar_t wc, FILE *stream) -{ - return fputwc( wc, stream ); -} - -#endif - -#ifndef HAVE_WCSTOK - -/* - Used by fallback wcstok. Borrowed from glibc -*/ -static size_t fish_wcsspn (const wchar_t *wcs, - const wchar_t *accept ) -{ - register const wchar_t *p; - register const wchar_t *a; - register size_t count = 0; - - for (p = wcs; *p != L'\0'; ++p) - { - for (a = accept; *a != L'\0'; ++a) - if (*p == *a) - break; - - if (*a == L'\0') - return count; - else - ++count; - } - return count; -} - -/* - Used by fallback wcstok. Borrowed from glibc -*/ -static wchar_t *fish_wcspbrk (const wchar_t *wcs, const wchar_t *accept) -{ - while (*wcs != L'\0') - if (wcschr (accept, *wcs) == NULL) - ++wcs; - else - return (wchar_t *) wcs; - return NULL; -} - -/* - Fallback wcstok implementation. Borrowed from glibc. -*/ -wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **save_ptr) -{ - wchar_t *result; - - if (wcs == NULL) - { - if (*save_ptr == NULL) - { - errno = EINVAL; - return NULL; - } - else - wcs = *save_ptr; - } - - /* Scan leading delimiters. */ - wcs += fish_wcsspn (wcs, delim); - - if (*wcs == L'\0') - { - *save_ptr = NULL; - return NULL; - } - - /* Find the end of the token. */ - result = wcs; - - wcs = fish_wcspbrk (result, delim); - - if (wcs == NULL) - { - /* This token finishes the string. */ - *save_ptr = NULL; - } - else - { - /* Terminate the token and make *SAVE_PTR point past it. */ - *wcs = L'\0'; - *save_ptr = wcs + 1; - } - return result; -} - -#endif - -#ifndef HAVE_WCSDUP -wchar_t *wcsdup( const wchar_t *in ) -{ - size_t len=wcslen(in); - wchar_t *out = malloc( sizeof( wchar_t)*(len+1)); - if( out == 0 ) - { - die_mem(); - } - - memcpy( out, in, sizeof( wchar_t)*(len+1)); - return out; - -} -#endif - -#ifndef HAVE_WCSLEN -size_t wcslen(const wchar_t *in) -{ - const wchar_t *end=in; - while( *end ) - end++; - return end-in; -} -#endif - - -#ifndef HAVE_WCSCASECMP -int wcscasecmp( const wchar_t *a, const wchar_t *b ) -{ - if( *a == 0 ) - { - return (*b==0)?0:-1; - } - else if( *b == 0 ) - { - return 1; - } - int diff = towlower(*a)-towlower(*b); - if( diff != 0 ) - return diff; - else - return wcscasecmp( a+1,b+1); -} -#endif - - -#ifndef HAVE_WCSNCASECMP -int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count ) -{ - if( count == 0 ) - return 0; - - if( *a == 0 ) - { - return (*b==0)?0:-1; - } - else if( *b == 0 ) - { - return 1; - } - int diff = towlower(*a)-towlower(*b); - if( diff != 0 ) - return diff; - else - return wcsncasecmp( a+1,b+1, count-1); -} -#endif - -#ifndef HAVE_WCWIDTH -int wcwidth( wchar_t c ) -{ - if( c < 32 ) - return 0; - if ( c == 127 ) - return 0; - return 1; -} -#endif - -#ifndef HAVE_WCSNDUP -wchar_t *wcsndup( const wchar_t *in, int c ) -{ - wchar_t *res = malloc( sizeof(wchar_t)*(c+1) ); - if( res == 0 ) - { - die_mem(); - } - wcsncpy( res, in, c+1 ); - res[c] = L'\0'; - return res; -} -#endif - -long convert_digit( wchar_t d, int base ) -{ - long res=-1; - if( (d <= L'9') && (d >= L'0') ) - { - res = d - L'0'; - } - else if( (d <= L'z') && (d >= L'a') ) - { - res = d + 10 - L'a'; - } - else if( (d <= L'Z') && (d >= L'A') ) - { - res = d + 10 - L'A'; - } - if( res >= base ) - { - res = -1; - } - - return res; -} - -#ifndef HAVE_WCSTOL -long wcstol(const wchar_t *nptr, - wchar_t **endptr, - int base) -{ - long long res=0; - int is_set=0; - if( base > 36 ) - { - errno = EINVAL; - return 0; - } - - while( 1 ) - { - long nxt = convert_digit( *nptr, base ); - if( endptr != 0 ) - *endptr = (wchar_t *)nptr; - if( nxt < 0 ) - { - if( !is_set ) - { - errno = EINVAL; - } - return res; - } - res = (res*base)+nxt; - is_set = 1; - if( res > LONG_MAX ) - { - errno = ERANGE; - return LONG_MAX; - } - if( res < LONG_MIN ) - { - errno = ERANGE; - return LONG_MIN; - } - nptr++; - } -} -#endif - @@ -1,8 +1,7 @@ /** \file wutil.h Prototypes for wide character equivalents of various standard unix - functions. Also contains fallback implementations of a large number - of wide character unix functions. + functions. */ #ifndef FISH_WUTIL_H #define FISH_WUTIL_H @@ -100,179 +99,4 @@ wchar_t *wrealpath(const wchar_t *pathname, wchar_t *resolved_path); struct wdirent *wreaddir(DIR *dir ); -/* - Here follows the prototypes for fallback implementations of various - standarcs libc functions relating to wide character support. Some of - these prototypes are always defined, since some libc versions - include the code, but you have to use special magical #defines for - the prototype to appear. -*/ - -#if !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); - -/** - Fallback implementation of getwc -*/ -wint_t getwc(FILE *stream); - -#endif - -#ifndef HAVE_FPUTWC - -/** - Fallback implementation of fputwc -*/ -wint_t fputwc(wchar_t wc, FILE *stream); -/** - Fallback implementation of putwc -*/ -wint_t putwc(wchar_t wc, FILE *stream); - -#endif - -#ifndef HAVE_WCSTOK -/** - Fallback implementation of wcstok. Uses code borrowed from glibc. -*/ -wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr); - -#endif - -/** - Return the number of columns used by a character. This is a libc - function, but the prototype for this function is missing in some libc - implementations. - - Fish has a fallback implementation in case the implementation is - missing altogether. In locales without a native wcwidth, Unicode - is probably so broken that it isn't worth trying to implement a - real wcwidth. Therefore, the fallback wcwidth assumes any printing - character takes up one column and anything else uses 0 columns. -*/ -int wcwidth( wchar_t c ); - -/** - Create a duplicate string. Wide string version of strdup. Will - automatically exit if out of memory. -*/ -wchar_t *wcsdup(const wchar_t *in); - -size_t wcslen(const wchar_t *in); - -/** - Case insensitive string compare function. Wide string version of - strcasecmp. - - This implementation of wcscasecmp does not take into account - esoteric locales where uppercase and lowercase do not cleanly - transform between each other. Hopefully this should be fine since - fish only uses this function with one of the strings supplied by - fish and guaranteed to be a sane, english word. Using wcscasecmp on - a user-supplied string should be considered a bug. -*/ -int wcscasecmp( const wchar_t *a, const wchar_t *b ); - -/** - Case insensitive string compare function. Wide string version of - strncasecmp. - - This implementation of wcsncasecmp does not take into account - esoteric locales where uppercase and lowercase do not cleanly - transform between each other. Hopefully this should be fine since - fish only uses this function with one of the strings supplied by - fish and guaranteed to be a sane, english word. Using wcsncasecmp on - a user-supplied string should be considered a bug. -*/ -int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count ); - -/** - Returns a newly allocated wide character string wich is a copy of - the string in, but of length c or shorter. The returned string is - always null terminated, and the null is not included in the string - length. -*/ -wchar_t *wcsndup( const wchar_t *in, int c ); - -/** - Converts from wide char to digit in the specified base. If d is not - a valid digit in the specified base, return -1. -*/ -long convert_digit( wchar_t d, int base ); - -/** - Fallback implementation. Convert a wide character string to a - number in the specified base. This functions is the wide character - string equivalent of strtol. For bases of 10 or lower, 0..9 are - used to represent numbers. For bases below 36, a-z and A-Z are used - to represent numbers higher than 9. Higher bases than 36 are not - supported. -*/ -long wcstol(const wchar_t *nptr, - wchar_t **endptr, - int base); - #endif |