aboutsummaryrefslogtreecommitdiffhomepage
path: root/wutil.c
diff options
context:
space:
mode:
authorGravatar axel <axel@liljencrantz.se>2006-02-28 23:17:16 +1000
committerGravatar axel <axel@liljencrantz.se>2006-02-28 23:17:16 +1000
commit2401a163fe418310a1ed015b0d4fc8402740ff79 (patch)
treeb30367f4988f169a3426489d9628e3d6873aa92e /wutil.c
parente8d802c5e184e069e783652fb60c9dec524acc93 (diff)
Move all fallbacks for standard and not-so-standard unix functions to fallback.c, in order to have a one-stop place to look for such functions
darcs-hash:20060228131716-ac50b-0832193dbcaf7191dcb24456dc40f2e861a1382e.gz
Diffstat (limited to 'wutil.c')
-rw-r--r--wutil.c831
1 files changed, 3 insertions, 828 deletions
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
-