Browse Source

Making libc wchar friendly.

Mark Sibly 8 years ago
parent
commit
5204391f53
3 changed files with 299 additions and 70 deletions
  1. 21 19
      modules/libc/libc.monkey2
  2. 195 51
      modules/libc/native/libc.cpp
  3. 83 0
      modules/libc/native/libc.h

+ 21 - 19
modules/libc/libc.monkey2

@@ -94,7 +94,7 @@ Const SEEK_SET:Int
 Const SEEK_CUR:Int
 Const SEEK_END:Int
 
-Function fopen:FILE Ptr( path:CString,mode:CString )
+Function fopen:FILE Ptr( path:CString,mode:CString )="fopen_utf8"
 
 Function rewind:Void( stream:FILE )
 Function ftell:Int( stream:FILE Ptr )
@@ -104,29 +104,31 @@ Function fread:Int( buf:Void Ptr,size:Int,count:Int,stream:FILE Ptr )
 Function fwrite:Int( buf:Void Ptr,size:Int,count:Int,stream:FILE Ptr )
 Function fflush:Int( stream:FILE Ptr )
 Function fclose:Int( stream:FILE Ptr )
-Function fputs:Int( str:CString,stream:FILE Ptr )
+Function fputs:Int( str:CString,stream:FILE Ptr )="fputs_utf8"
 
-Function remove:Int( path:CString )
-Function rename:Int( oldPath:CString,newPath:CString )
+Function remove:Int( path:CString )="remove_utf8"
+Function rename:Int( oldPath:CString,newPath:CString )="rename_utf8"
 
-Function puts:Int( str:CString )
+Function puts:Int( str:CString )="puts_utf8"
 
 '***** stdlib.h *****
 
 Function malloc:Void Ptr( size:Int )
 Function free:Void( mem:Void Ptr )
+	
 
 #If __TARGET__<>"ios"	'gone in ios11!
-Function system:Int( cmd:CString )="system_"
+Function system:Int( cmd:CString )="system_utf8"
 #endif
-Function setenv:Int( name:CString,value:CString,overwrite:Int )="setenv_"
-Function getenv:char_t ptr( name:CString )
+
+Function setenv:Int( name:CString,value:CString,overwrite:Int )="setenv_utf8"
+Function getenv:char_t Ptr( name:CString )="getenv_utf8"
 
 Function exit_:Void( status:Int )="exit"
 Function atexit:Int( func:Void() )="atexit" 
 Function abort:Void()
 	
-Function realpath:char_t Ptr( path:CString,resolved_path:char_t Ptr )
+Function realpath:char_t Ptr( path:CString,resolved_path:char_t Ptr )="realpath_utf8"
 
 '***** string.h *****
 
@@ -172,13 +174,13 @@ Function time:time_t( timer:time_t Ptr )
 Function localtime:tm_t Ptr( timer:time_t Ptr )
 Function gmtime:tm_t Ptr( timer:time_t Ptr )
 Function difftime:Double( endtime:time_t,starttime:time_t ) 
-Function gettimeofday:Int( tv:timeval Ptr )="gettimeofday_"
+Function gettimeofday:Int( tv:timeval Ptr )="gettimeofday_utf8"
 
 '***** unistd.h *****
 
-Function getcwd:char_t Ptr( buf:char_t Ptr,size:Int )
-Function chdir:Int( path:CString )
-Function rmdir:Int( path:CString )
+Function getcwd:char_t Ptr( buf:char_t Ptr,size:Int )="getcwd_utf8"
+Function chdir:Int( path:CString )="chdir_utf8"
+Function rmdir:Int( path:CString )="rmdir_utf8"
 
 '***** sys/stat.h *****
 
@@ -200,8 +202,8 @@ Struct stat_t
 	Field st_ctime:time_t	'status change
 End
 
-Function stat:Int( path:CString,buf:stat_t Ptr )
-Function mkdir:Int( path:CString,mode:Int )="mkdir_"
+Function stat:Int( path:CString,buf:stat_t Ptr )="stat_utf8"
+Function mkdir:Int( path:CString,mode:Int )="mkdir_utf8"
 
 '***** dirent.h *****
 
@@ -209,9 +211,9 @@ Struct DIR
 End
 
 Struct dirent
-	Field d_name:Void Ptr
+	Field d_name:CString
 End
 
-Function opendir:DIR Ptr( path:CString )
-Function readdir:dirent Ptr( dir:DIR Ptr )
-Function closedir( dir:DIR Ptr )
+Function opendir:DIR Ptr( path:CString )="opendir_utf8"
+Function readdir:dirent Ptr( dir:DIR Ptr )="readdir_utf8"
+Function closedir( dir:DIR Ptr )="closedir_utf8"

+ 195 - 51
modules/libc/native/libc.cpp

@@ -1,6 +1,7 @@
 
 #include "libc.h"
 
+/*
 #if _WIN32
 #include <windows.h>
 #include <bbstring.h>
@@ -10,32 +11,121 @@
 #elif __APPLE__
 #include <TargetConditionals.h>
 #endif
-
-void setenv_( const char *name,const char *value,int overwrite ){
+*/
 
 #if _WIN32
 
-	if( !overwrite && getenv( name ) ) return;
+struct DIR{
+	WIN32_FIND_DATAW ffd;
+	HANDLE hfind;
+	dirent entry;
+};
 
-	bbString tmp=bbString( name )+BB_T( "=" )+bbString( value );
-	putenv( tmp.c_str() );
+static void *tmps[32];
+static int tmpsi;
 
-#else
-	setenv( name,value,overwrite );
-#endif
+static const WCHAR *widen( const char *p ){
+
+	int n=MultiByteToWideChar( CP_UTF8,0,p,-1,0,0 );
+
+	WCHAR *w=(WCHAR*)malloc( n*2 );
+	
+	MultiByteToWideChar( CP_UTF8,0,p,-1,w,n );
+	
+	free(tmps[tmpsi&31]);
+	tmps[(tmpsi++)&31]=w;
+	
+	return w;
 }
 
-int system_( const char *cmd ){
+static const char *narrow( const WCHAR *w ){
 
-#if _WIN32
+	int n=WideCharToMultiByte( CP_UTF8,0,w,-1,0,0,0,0 );
+	
+	char *p=(char*)malloc( n );
+	
+	WideCharToMultiByte( CP_UTF8,0,w,-1,p,n,0,0 );
+	
+	free(tmps[tmpsi&31]);
+	tmps[(tmpsi++)&31]=p;
+	
+	return p;	
+}
+
+const wchar_t *widen_utf8( const char *p ){
+
+	return widen( p );
+}
+
+const char *narrow_utf8( const wchar_t *w ){
+
+	return narrow( w );
+}
+
+FILE *fopen_utf8( const char *filename,const char *mode ){
+
+	return _wfopen( widen( filename ),widen( mode ) );
+}
+
+int fputs_utf8( const char *str,FILE *stream ){
+	
+	return fputws( widen( str ),stream );
+}
+
+int remove_utf8( const char *path ){
+
+	return _wremove( widen( path ) );
+}
+
+int rename_utf8( const char *oldpath,const char *newpath ){
+
+	return _wrename( widen( oldpath ),widen( newpath ) );
+}
+
+int puts_utf8( const char *str ){
+
+	return _putws( widen( str ) );
+}
+
+int setenv_utf8( const char *name,const char *value,int overwrite ){
+
+	const WCHAR *wname=widen( name );
+
+	if( !overwrite && _wgetenv( wname ) ) return -1;
+	
+	WCHAR *wbuf=(WCHAR*)malloc( (strlen(name)+strlen(value)+2)*2 );
+	
+	wcscpy( wbuf,wname );
+	wcscat( wbuf,L"=" );
+	wcscat( wbuf,widen( value ) );
+	
+	int n=_wputenv( wbuf );
+	
+	return n;
+}
+
+char *getenv_utf8( const char *name ){
+
+	static char *p;
+
+	const WCHAR *wname=widen( name );
+	
+	WCHAR *w=_wgetenv( wname );
+	if( !w ) return 0;
+	
+	free( p );
+	p=strdup( narrow( w ) );
+	
+	return p;
+}
+
+int system_utf8( const char *cmd ){
 
 	bool inherit=false;
 	DWORD flags=CREATE_NO_WINDOW;
-	STARTUPINFOA si={sizeof(si)};
+	STARTUPINFOW si={sizeof(si)};
 	PROCESS_INFORMATION pi={0};
 	
-	bbString tmp=BB_T( "cmd /S /C\"" )+BB_T( cmd )+BB_T( "\"" );
-	
 	if( GetStdHandle( STD_OUTPUT_HANDLE ) ){
 	
 		inherit=true;
@@ -49,8 +139,19 @@ int system_( const char *cmd ){
 
 		flags=0;
 	}
+
+//	bbString tmp=BB_T( "cmd /S /C\"" )+BB_T( cmd )+BB_T( "\"" );
+	
+	const WCHAR *wopts=L"cmd /S /C\"";
+	const WCHAR *wcmd=widen( cmd );
 	
-	if( !CreateProcessA( 0,(LPSTR)tmp.c_str(),0,0,inherit,flags,0,0,&si,&pi ) ) return -1;
+	WCHAR *wtmp=(WCHAR*)malloc( (wcslen( wopts )+wcslen( wcmd )+2)*2 );
+	
+	wcscpy( wtmp,wopts );
+	wcscat( wtmp,wcmd );
+	wcscat( wtmp,L"\"" );
+	
+	if( !CreateProcessW( 0,wtmp,0,0,inherit,flags,0,0,&si,&pi ) ) return -1;
 
 	WaitForSingleObject( pi.hProcess,INFINITE );
 	
@@ -60,61 +161,104 @@ int system_( const char *cmd ){
 	CloseHandle( pi.hThread );
 
 	return res;
+}
+
+char *realpath_utf8( const char *path,char *rpath ){
+
+	if( !rpath ){
+		rpath=(char*)malloc( PATH_MAX );
+		if( realpath_utf8( path,rpath ) ) return rpath;
+		free( rpath );
+		return 0;
+	}
 	
-#elif __APPLE__
+	WCHAR wbuf[PATH_MAX];
+	
+	if( !GetFullPathNameW( widen( path ),PATH_MAX,wbuf,0 ) ) return 0;
+	
+	WideCharToMultiByte( CP_UTF8,0,wbuf,-1,rpath,PATH_MAX,0,0 );
+		
+	return rpath;
+}
 
-#if !TARGET_OS_IPHONE
-	return system( cmd );
-#endif
+int mkdir_utf8( const char *path,int mode ){
 
-#else
+	return _wmkdir( widen( path ) );
+}
 
-	return system( cmd );
+char *getcwd_utf8( char *buf,int size ){
 
-#endif
+	WCHAR wbuf[PATH_MAX];
+	
+	if( !GetCurrentDirectoryW( size,wbuf ) ) return 0;
+	
+	WideCharToMultiByte( CP_UTF8,0,wbuf,-1,buf,size,0,0 );
+	
+	return buf;
+}
 
-	return -1;
+int chdir_utf8( const char *path ){
 
+	return SetCurrentDirectoryW( widen( path ) ) ? 0 : -1;
 }
 
-int mkdir_( const char *path,int mode ){
-#if _WIN32
+int rmdir_utf8( const char *path ){
+
+	return _wrmdir( widen( path ) );
+}
+
+int stat_utf8( const char *path,stat_t *buf ){
+
+	return _wstat( widen( path ),buf );
+}
 
-	return mkdir( path );
+DIR *opendir_utf8( const char *path ){
+
+	const WCHAR *wpath=widen( path );
+
+	WCHAR *wbuf=(WCHAR*)malloc( (wcslen(wpath)+3)*2 );
+	
+	wcscpy( wbuf,wpath );
+	wcscat( wbuf,L"\\*" );
 	
-#else
+	DIR *dir=(DIR*)malloc( sizeof( DIR ) );
+	memset( dir,0,sizeof(DIR) );
+	
+	dir->hfind=FindFirstFileW( wbuf,&dir->ffd );
 
-	return mkdir( path,0777 );
+	if( !dir->hfind ){
+		free( dir );
+		dir=0;
+	}
 	
-#endif
+	free( wbuf );
+	
+	return dir;
 }
 
-int gettimeofday_( timeval *tv ){
-#if _MSC_VER
-	
-	// https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
+dirent *readdir_utf8( DIR *dir ){
 
-    // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
-    // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC)
-    // until 00:00:00 January 1, 1970 
-    static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);
+	if( !dir->hfind ) return 0;
 
-    SYSTEMTIME  system_time;
-    FILETIME    file_time;
-    uint64_t    time;
+	const char *p=narrow( dir->ffd.cFileName );
+	free( dir->entry.d_name );
+	dir->entry.d_name=strdup( p );
+	
+	if( !FindNextFileW( dir->hfind,&dir->ffd ) ){
+		FindClose( dir->hfind );
+		dir->hfind=0;
+	}
+	
+	return &dir->entry;
+}
 
-    GetSystemTime( &system_time );
-    SystemTimeToFileTime( &system_time, &file_time );
-    time =  ((uint64_t)file_time.dwLowDateTime )      ;
-    time += ((uint64_t)file_time.dwHighDateTime) << 32;
+void closedir_utf8( DIR *dir ){
 
-    tv->tv_sec  = (long) ((time - EPOCH) / 10000000L);
-    tv->tv_usec = (long) (system_time.wMilliseconds * 1000);
-    return 0;
-    
-#else
+	if( dir->hfind ) FindClose( dir->hfind );
+
+	free( dir->entry.d_name );
+	free( dir );
+}
 
-	return gettimeofday( tv,0 );
-	
 #endif
-}
+

+ 83 - 0
modules/libc/native/libc.h

@@ -4,6 +4,86 @@
 #ifndef BB_LIB_C_H
 #define BB_LIB_C_H
 
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if _WIN32
+
+#include <windows.h>
+#include <wchar.h>
+//#include <winsock2.h>	//for struct timeval?!?
+
+#define PATH_MAX 260
+
+struct dirent{
+	char *d_name;
+};
+	
+struct DIR;
+
+typedef int mode_t;
+
+typedef struct tm tm_t;
+
+typedef struct _stat stat_t;
+
+const wchar_t *widen_utf8( const char *p );
+const char *narrow_utf8( const wchar_t *w );
+
+FILE *fopen_utf8( const char *path,char const *mode );
+int fputs_utf8( const char *str,FILE *stream );
+int remove_utf8( const char *path );
+int rename_utf8( const char *oldpath,const char *newpath );
+int puts_utf8( const char *str );
+int setenv_utf8( const char *name,const char *value,int overwrite );
+char *getenv_utf8( const char *name );
+int system_utf8( const char *cmd );
+char *realpath_utf8( const char *path,char *resolved_path );
+int mkdir_utf8( const char *path,int mode );
+int gettimeofday_utf8( timeval *tv );
+char *getcwd_utf8( char *buf,int size );
+int chdir_utf8( const char *path );
+int rmdir_utf8( const char *path );
+int stat_utf8( const char *path,stat_t *buf );
+DIR *opendir_utf8( const char *path );
+dirent *readdir_utf8( DIR *dir );
+void closedir_utf8( DIR *dir );
+
+#else
+
+typedef struct tm tm_t;
+
+typedef struct stat stat_t;
+
+#define fopen_utf8 fopen
+#define fputs_utf8 fputs
+#define remove_utf8 remove
+#define rename_utf8 rename
+#define puts_utf8 puts
+#define setenv_utf8 setenv
+#define getenv_utf8 getenv
+#define system_utf8 system
+#define realpath_utf8 realpath
+#define mkdir_utf8 mkdir
+#define gettimeofday_utf8 gettimeofday
+#define getcwd_utf8 getcwd
+#define chdir_utf8 chdir
+#define rmdir_utf8 rmdir
+#define stat_utf8 stat
+#define opendir_utf8 opendir
+#define readdir_utf8 readdir
+#define closedir_utf8 closedir
+
+#endif
+
+#endif
+
+/*
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -40,3 +120,6 @@ int mkdir_( const char *path,int mode );
 int gettimeofday_( timeval *tv );
 
 #endif
+
+*/
+