aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile.in2
-rw-r--r--builtin.c3
-rw-r--r--builtin_commandline.c3
-rw-r--r--builtin_complete.c3
-rw-r--r--builtin_set.c3
-rw-r--r--builtin_ulimit.c3
-rw-r--r--common.c3
-rw-r--r--complete.c3
-rw-r--r--env.c3
-rw-r--r--env_universal.c3
-rw-r--r--env_universal_common.c3
-rw-r--r--event.c3
-rw-r--r--exec.c3
-rw-r--r--expand.c3
-rw-r--r--fallback.c882
-rw-r--r--fallback.h192
-rw-r--r--fish_pager.c3
-rw-r--r--fish_tests.c3
-rw-r--r--fishd.c3
-rw-r--r--function.c3
-rw-r--r--halloc.c3
-rw-r--r--halloc_util.c3
-rw-r--r--highlight.c3
-rw-r--r--history.c3
-rw-r--r--input.c3
-rw-r--r--input_common.c3
-rw-r--r--intern.c3
-rw-r--r--io.c3
-rw-r--r--kill.c3
-rw-r--r--main.c3
-rw-r--r--mimedb.c3
-rw-r--r--output.c13
-rw-r--r--parse_util.c3
-rw-r--r--parser.c3
-rw-r--r--proc.c3
-rw-r--r--reader.c3
-rw-r--r--sanity.c3
-rw-r--r--set_color.c1
-rw-r--r--signal.c3
-rw-r--r--tokenizer.c3
-rw-r--r--translate.c3
-rw-r--r--util.c3
-rw-r--r--wgetopt.c1
-rw-r--r--wildcard.c3
-rw-r--r--wutil.c831
-rw-r--r--wutil.h178
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.
diff --git a/builtin.c b/builtin.c
index dee20bff..62f7911f 100644
--- a/builtin.c
+++ b/builtin.c
@@ -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"
diff --git a/common.c b/common.c
index 76da6eba..fa9ad60f 100644
--- a/common.c
+++ b/common.c
@@ -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"
diff --git a/complete.c b/complete.c
index cc7fa2ca..c7919567 100644
--- a/complete.c
+++ b/complete.c
@@ -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"
diff --git a/env.c b/env.c
index 54c53de4..45075e0f 100644
--- a/env.c
+++ b/env.c
@@ -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"
diff --git a/event.c b/event.c
index d7004ba2..f45c95f4 100644
--- a/event.c
+++ b/event.c
@@ -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"
diff --git a/exec.c b/exec.c
index 627fec47..9dff5985 100644
--- a/exec.c
+++ b/exec.c
@@ -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"
diff --git a/expand.c b/expand.c
index 4664a8b4..764cd72a 100644
--- a/expand.c
+++ b/expand.c
@@ -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"
diff --git a/fishd.c b/fishd.c
index 7afc1187..c78a0fcf 100644
--- a/fishd.c
+++ b/fishd.c
@@ -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"
diff --git a/function.c b/function.c
index 8e77de3a..4cac79f0 100644
--- a/function.c
+++ b/function.c
@@ -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"
diff --git a/halloc.c b/halloc.c
index 996a4cb5..dbfbf8eb 100644
--- a/halloc.c
+++ b/halloc.c
@@ -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"
diff --git a/history.c b/history.c
index ae1da878..112e7cfe 100644
--- a/history.c
+++ b/history.c
@@ -12,7 +12,10 @@
#include "config.h"
+
+#include "fallback.h"
#include "util.h"
+
#include "wutil.h"
#include "history.h"
#include "common.h"
diff --git a/input.c b/input.c
index 0352766a..9c81fb80 100644
--- a/input.c
+++ b/input.c
@@ -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"
diff --git a/intern.c b/intern.c
index c52027f7..d54c69f9 100644
--- a/intern.c
+++ b/intern.c
@@ -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"
diff --git a/io.c b/io.c
index de36e56e..7d515b2e 100644
--- a/io.c
+++ b/io.c
@@ -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"
diff --git a/kill.c b/kill.c
index b4a2a7d7..32ed1dcf 100644
--- a/kill.c
+++ b/kill.c
@@ -18,7 +18,10 @@
#include "config.h"
+
+#include "fallback.h"
#include "util.h"
+
#include "wutil.h"
#include "kill.h"
#include "proc.h"
diff --git a/main.c b/main.c
index d65fc9ed..8e9dac8e 100644
--- a/main.c
+++ b/main.c
@@ -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"
diff --git a/mimedb.c b/mimedb.c
index c33ef059..19173c59 100644
--- a/mimedb.c
+++ b/mimedb.c
@@ -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
*/
diff --git a/output.c b/output.c
index 9c9c8713..dda4aa2e 100644
--- a/output.c
+++ b/output.c
@@ -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"
diff --git a/parser.c b/parser.c
index a5e61355..9ab8b5ca 100644
--- a/parser.c
+++ b/parser.c
@@ -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"
diff --git a/proc.c b/proc.c
index 6fe85395..5ea4f7e3 100644
--- a/proc.c
+++ b/proc.c
@@ -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"
diff --git a/reader.c b/reader.c
index 8e87b5d6..d654b9f7 100644
--- a/reader.c
+++ b/reader.c
@@ -59,7 +59,10 @@ commence.
#include <assert.h>
+
+#include "fallback.h"
#include "util.h"
+
#include "wutil.h"
#include "highlight.h"
#include "reader.h"
diff --git a/sanity.c b/sanity.c
index 1a342327..a20d1f50 100644
--- a/sanity.c
+++ b/sanity.c
@@ -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>
diff --git a/signal.c b/signal.c
index 108af53e..71ba0360 100644
--- a/signal.c
+++ b/signal.c
@@ -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
diff --git a/util.c b/util.c
index bf875370..608b9a3f 100644
--- a/util.c
+++ b/util.c
@@ -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"
diff --git a/wgetopt.c b/wgetopt.c
index c6bf2a6f..d63fc759 100644
--- a/wgetopt.c
+++ b/wgetopt.c
@@ -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.
diff --git a/wildcard.c b/wildcard.c
index 7c31f6a1..0c0243d6 100644
--- a/wildcard.c
+++ b/wildcard.c
@@ -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"
diff --git a/wutil.c b/wutil.c
index 42be8671..8cd1c316 100644
--- a/wutil.c
+++ b/wutil.c
@@ -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
-
diff --git a/wutil.h b/wutil.h
index b88c7822..6009af65 100644
--- a/wutil.h
+++ b/wutil.h
@@ -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