diff --git a/dlls/crtdll/console.c b/dlls/crtdll/console.c index 91df6455c2c..a278c6c15e8 100644 --- a/dlls/crtdll/console.c +++ b/dlls/crtdll/console.c @@ -16,12 +16,13 @@ */ #include "crtdll.h" #include "wincon.h" +#include DEFAULT_DEBUG_CHANNEL(crtdll); static HANDLE __CRTDLL_console_in = INVALID_HANDLE_VALUE; static HANDLE __CRTDLL_console_out = INVALID_HANDLE_VALUE; -static int __CRTDLL_console_buffer = EOF; +static int __CRTDLL_console_buffer = CRTDLL_EOF; /* INTERNAL: Initialise console handles */ @@ -66,7 +67,7 @@ LPSTR __cdecl CRTDLL__cgets(LPSTR str) /* FIXME: No editing of string supported */ do { - if (str[1] >= str[0] || (str[1]++, c = CRTDLL__getche()) == EOF || c == '\n') + if (str[1] >= str[0] || (str[1]++, c = CRTDLL__getche()) == CRTDLL_EOF || c == '\n') { *buf = '\0'; return str + 2; @@ -76,6 +77,24 @@ LPSTR __cdecl CRTDLL__cgets(LPSTR str) } +/********************************************************************* + * _cprintf (CRTDLL.064) + * + * Write a formatted string to CONOUT$. + */ +INT __cdecl CRTDLL__cprintf( LPCSTR format, ... ) +{ + va_list valist; + char buffer[2048]; + + va_start( valist, format ); + if (snprintf( buffer, sizeof(buffer), format, valist ) == -1) + ERR("Format too large for internal buffer!\n"); + va_end(valist); + return CRTDLL__cputs( buffer ); +} + + /********************************************************************* * _cputs (CRTDLL.065) * @@ -87,7 +106,133 @@ INT __cdecl CRTDLL__cputs(LPCSTR str) if (WriteConsoleA(__CRTDLL_console_out, str, strlen(str), &count, NULL) && count == 1) return 0; - return EOF; + return CRTDLL_EOF; +} + + +/********************************************************************* + * _cscanf (CRTDLL.067) + * + * Read formatted input from CONIN$. + */ +INT __cdecl CRTDLL__cscanf( LPCSTR format, ... ) +{ + /* NOTE: If you extend this function, extend CRTDLL_fscanf in file.c too */ + INT rd = 0; + int nch; + va_list ap; + if (!*format) return 0; + WARN("\"%s\": semi-stub\n", format); + nch = CRTDLL__getch(); + va_start(ap, format); + while (*format) { + if (*format == ' ') { + /* skip whitespace */ + while ((nch!=CRTDLL_EOF) && isspace(nch)) + nch = CRTDLL__getch(); + } + else if (*format == '%') { + int st = 0; + format++; + switch(*format) { + case 'd': { /* read an integer */ + int*val = va_arg(ap, int*); + int cur = 0; + /* skip initial whitespace */ + while ((nch!=CRTDLL_EOF) && isspace(nch)) + nch = CRTDLL__getch(); + /* get sign and first digit */ + if (nch == '-') { + nch = CRTDLL__getch(); + if (isdigit(nch)) + cur = -(nch - '0'); + else break; + } else { + if (isdigit(nch)) + cur = nch - '0'; + else break; + } + nch = CRTDLL__getch(); + /* read until no more digits */ + while ((nch!=CRTDLL_EOF) && isdigit(nch)) { + cur = cur*10 + (nch - '0'); + nch = CRTDLL__getch(); + } + st = 1; + *val = cur; + } + break; + case 'f': { /* read a float */ + float*val = va_arg(ap, float*); + float cur = 0; + /* skip initial whitespace */ + while ((nch!=CRTDLL_EOF) && isspace(nch)) + nch = CRTDLL__getch(); + /* get sign and first digit */ + if (nch == '-') { + nch = CRTDLL__getch(); + if (isdigit(nch)) + cur = -(nch - '0'); + else break; + } else { + if (isdigit(nch)) + cur = nch - '0'; + else break; + } + /* read until no more digits */ + while ((nch!=CRTDLL_EOF) && isdigit(nch)) { + cur = cur*10 + (nch - '0'); + nch = CRTDLL__getch(); + } + if (nch == '.') { + /* handle decimals */ + float dec = 1; + nch = CRTDLL__getch(); + while ((nch!=CRTDLL_EOF) && isdigit(nch)) { + dec /= 10; + cur += dec * (nch - '0'); + nch = CRTDLL__getch(); + } + } + st = 1; + *val = cur; + } + break; + case 's': { /* read a word */ + char*str = va_arg(ap, char*); + char*sptr = str; + /* skip initial whitespace */ + while ((nch!=CRTDLL_EOF) && isspace(nch)) + nch = CRTDLL__getch(); + /* read until whitespace */ + while ((nch!=CRTDLL_EOF) && !isspace(nch)) { + *sptr++ = nch; st++; + nch = CRTDLL__getch(); + } + /* terminate */ + *sptr = 0; + TRACE("read word: %s\n", str); + } + break; + default: FIXME("unhandled: %%%c\n", *format); + } + if (st) rd++; + else break; + } + else { + /* check for character match */ + if (nch == *format) + nch = CRTDLL__getch(); + else break; + } + format++; + } + va_end(ap); + if (nch != CRTDLL_EOF) + CRTDLL__ungetch(nch); + + TRACE("returning %d\n", rd); + return rd; } @@ -98,10 +243,10 @@ INT __cdecl CRTDLL__cputs(LPCSTR str) */ INT __cdecl CRTDLL__getch(VOID) { - if (__CRTDLL_console_buffer != EOF) + if (__CRTDLL_console_buffer != CRTDLL_EOF) { INT retVal = __CRTDLL_console_buffer; - __CRTDLL_console_buffer = EOF; + __CRTDLL_console_buffer = CRTDLL_EOF; return retVal; } else @@ -130,7 +275,7 @@ INT __cdecl CRTDLL__getch(VOID) } while(1); if (mode) SetConsoleMode(__CRTDLL_console_in, mode); } - return EOF; + return CRTDLL_EOF; } @@ -142,9 +287,9 @@ INT __cdecl CRTDLL__getch(VOID) INT __cdecl CRTDLL__getche(VOID) { INT res = CRTDLL__getch(); - if (res != EOF && CRTDLL__putch(res) != EOF) + if (res != CRTDLL_EOF && CRTDLL__putch(res) != CRTDLL_EOF) return res; - return EOF; + return CRTDLL_EOF; } @@ -155,7 +300,7 @@ INT __cdecl CRTDLL__getche(VOID) */ INT __cdecl CRTDLL__kbhit(VOID) { - if (__CRTDLL_console_buffer != EOF) + if (__CRTDLL_console_buffer != CRTDLL_EOF) return 1; else { @@ -201,7 +346,7 @@ INT __cdecl CRTDLL__putch(INT c) if (WriteConsoleA(__CRTDLL_console_out, &c, 1, &count, NULL) && count == 1) return c; - return EOF; + return CRTDLL_EOF; } @@ -212,8 +357,8 @@ INT __cdecl CRTDLL__putch(INT c) */ INT __cdecl CRTDLL__ungetch(INT c) { - if (c == EOF || __CRTDLL_console_buffer != EOF) - return EOF; + if (c == CRTDLL_EOF || __CRTDLL_console_buffer != CRTDLL_EOF) + return CRTDLL_EOF; return __CRTDLL_console_buffer = c; } diff --git a/dlls/crtdll/crtdll.h b/dlls/crtdll/crtdll.h index 45d5525b09a..9dee9a66884 100644 --- a/dlls/crtdll/crtdll.h +++ b/dlls/crtdll/crtdll.h @@ -157,7 +157,8 @@ typedef struct _crtfile #define SEEK_CUR 1 #define SEEK_END 2 -#define EOF -1 +#define CRTDLL_EOF -1 +#define CRTDLL_WEOF (WCHAR)(0xFFFF) extern CRTDLL_FILE __CRTDLL_iob[3]; @@ -281,14 +282,16 @@ LPSTR __cdecl CRTDLL__mktemp( LPSTR pattern ); CRTDLL_FILE* __cdecl CRTDLL_fopen( LPCSTR path, LPCSTR mode ); CRTDLL_FILE* __cdecl CRTDLL_freopen( LPCSTR path,LPCSTR mode,CRTDLL_FILE* f ); CRTDLL_FILE* __cdecl CRTDLL_tmpfile( void ); +WCHAR __cdecl CRTDLL__fgetwchar( VOID ); INT __cdecl CRTDLL__fgetchar( VOID ); DWORD __cdecl CRTDLL_fread( LPVOID ptr,INT size,INT nmemb,CRTDLL_FILE* file ); -INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* stream, LPSTR format, ... ); +INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* stream, LPCSTR format, ... ); INT __cdecl CRTDLL__filbuf( CRTDLL_FILE* file ); LONG __cdecl CRTDLL__filelength( INT fd ); INT __cdecl CRTDLL__fileno( CRTDLL_FILE* file ); INT __cdecl CRTDLL__flsbuf( INT c, CRTDLL_FILE* file ); INT __cdecl CRTDLL__fputchar( INT c ); +WCHAR __cdecl CRTDLL__fputwchar( WCHAR wc ); INT __cdecl CRTDLL__flushall( VOID ); INT __cdecl CRTDLL__fcloseall( VOID ); LONG __cdecl CRTDLL__lseek( INT fd, LONG offset, INT whence ); @@ -315,6 +318,8 @@ INT __cdecl CRTDLL_putc( INT c, CRTDLL_FILE* file ); INT __cdecl CRTDLL_fgetc( CRTDLL_FILE* file ); INT __cdecl CRTDLL_getchar( VOID ); INT __cdecl CRTDLL_getc( CRTDLL_FILE* file ); +WCHAR __cdecl CRTDLL_fgetwc( CRTDLL_FILE* file ); +WCHAR __cdecl CRTDLL_fputwc( WCHAR wc, CRTDLL_FILE* file ); CHAR* __cdecl CRTDLL_fgets( LPSTR s, INT size, CRTDLL_FILE* file ); LPSTR __cdecl CRTDLL_gets( LPSTR buf ); INT __cdecl CRTDLL_fclose( CRTDLL_FILE* file ); @@ -324,6 +329,7 @@ LONG __cdecl CRTDLL__tell(INT fd); INT __cdecl CRTDLL__umask(INT umask); INT __cdecl CRTDLL__utime( LPCSTR path, struct _utimbuf *t ); INT __cdecl CRTDLL__unlink( LPCSTR pathname ); +INT __cdecl CRTDLL_scanf( LPCSTR format, ... ); INT __cdecl CRTDLL_rename( LPCSTR oldpath,LPCSTR newpath ); int __cdecl CRTDLL__stat( LPCSTR filename, struct _stat * buf ); INT __cdecl CRTDLL__open( LPCSTR path,INT flags ); @@ -359,8 +365,8 @@ VOID __cdecl CRTDLL_longjmp( jmp_buf env, int val ); LPSTR __cdecl CRTDLL_setlocale( INT category,LPCSTR locale ); INT __cdecl CRTDLL__isctype( INT c, UINT type ); LPSTR __cdecl CRTDLL__fullpath( LPSTR buf, LPCSTR name, INT size ); -VOID __cdecl CRTDLL__splitpath( LPCSTR path, LPSTR drive, LPSTR directory, - LPSTR filename, LPSTR extension ); +VOID __cdecl CRTDLL__splitpath(LPCSTR inpath, LPSTR drv, LPSTR dir, + LPSTR fname, LPSTR ext ); INT __cdecl CRTDLL__matherr( struct _exception *e ); VOID __cdecl CRTDLL__makepath( LPSTR path, LPCSTR drive, LPCSTR directory, LPCSTR filename, @@ -388,6 +394,7 @@ INT __cdecl CRTDLL_ispunct( INT c); INT __cdecl CRTDLL_isspace( INT c); INT __cdecl CRTDLL_isupper( INT c); INT __cdecl CRTDLL_isxdigit( INT c ); +INT __cdecl CRTDLL_isleadbyte( UCHAR c ); double __cdecl CRTDLL_ldexp( double x, LONG y ); LPSTR __cdecl CRTDLL__mbsrchr( LPSTR s,CHAR x ); VOID __cdecl CRTDLL___dllonexit ( VOID ); @@ -444,7 +451,7 @@ HANDLE __cdecl CRTDLL__spawnve( INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *en HANDLE __cdecl CRTDLL__spawnvp( INT flags, LPCSTR name, LPCSTR *argv); HANDLE __cdecl CRTDLL__spawnvpe( INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv); INT __cdecl CRTDLL_system( LPCSTR cmd ); -INT __cdecl CRTDLL__cwait( PINT status, INT pid, INT action ); +INT __cdecl CRTDLL__cwait( LPINT status, INT pid, INT action ); /* str.c */ LPSTR __cdecl CRTDLL__strdec( LPSTR str1, LPSTR str2 ); @@ -494,7 +501,9 @@ INT __cdecl CRTDLL_iswxdigit( WCHAR wc ); /* console.c */ LPSTR __cdecl CRTDLL__cgets( LPSTR str ); +INT __cdecl CRTDLL__cfprintf( LPCSTR format, ... ); INT __cdecl CRTDLL__cputs( LPCSTR str ); +INT __cdecl CRTDLL__cscanf( LPCSTR format, ... ); INT __cdecl CRTDLL__getch( VOID ); INT __cdecl CRTDLL__getche( VOID ); INT __cdecl CRTDLL__kbhit( VOID ); diff --git a/dlls/crtdll/crtdll.spec b/dlls/crtdll/crtdll.spec index 6cac3e142c0..91f86996dd5 100644 --- a/dlls/crtdll/crtdll.spec +++ b/dlls/crtdll/crtdll.spec @@ -70,11 +70,11 @@ debug_channels (crtdll) @ cdecl _control87(long long) CRTDLL__control87 @ cdecl _controlfp(long long) CRTDLL__controlfp @ cdecl _copysign(double double) CRTDLL__copysign -@ stub _cprintf +@ varargs _cprintf(str) CRTDLL__cprintf @ stub _cpumode_dll @ cdecl _cputs(str) CRTDLL__cputs @ cdecl _creat(str long) CRTDLL__creat -@ stub _cscanf +@ varargs _cscanf(str) CRTDLL__cscanf @ extern _ctype CRTDLL_ctype @ cdecl _cwait(ptr long long) CRTDLL__cwait @ stub _daylight_dll @@ -100,7 +100,7 @@ debug_channels (crtdll) @ cdecl _fcvt(double long ptr ptr) fcvt @ cdecl _fdopen(long ptr) CRTDLL__fdopen @ cdecl _fgetchar() CRTDLL__fgetchar -@ stub _fgetwchar +@ cdecl _fgetwchar() CRTDLL__fgetwchar @ cdecl _filbuf(ptr) CRTDLL__filbuf @ stub _fileinfo_dll @ cdecl _filelength(long) CRTDLL__filelength @@ -116,7 +116,7 @@ debug_channels (crtdll) @ stub _fpieee_flt @ cdecl _fpreset() CRTDLL__fpreset @ cdecl _fputchar(long) CRTDLL__fputchar -@ stub _fputwchar +@ cdecl _fputwchar(long) CRTDLL__fputwchar @ cdecl _fsopen(str str long) CRTDLL__fsopen @ cdecl _fstat(long ptr) CRTDLL__fstat @ cdecl _ftime(ptr) CRTDLL__ftime @@ -313,7 +313,7 @@ debug_channels (crtdll) @ extern _sys_nerr_dll CRTDLL__sys_nerr @ cdecl _tell(long) CRTDLL__tell @ cdecl _tempnam(str ptr) CRTDLL__tempnam -@ stub _timezone_dll +@ extern _timezone_dll CRTDLL_timezone_dll @ cdecl _tolower(long) CRTDLL__toupper @ cdecl _toupper(long) CRTDLL__tolower @ stub _tzname @@ -340,8 +340,8 @@ debug_channels (crtdll) @ extern _winminor_dll CRTDLL_winminor_dll @ extern _winver_dll CRTDLL_winver_dll @ cdecl _write(long ptr long) CRTDLL__write -@ stub _wtoi -@ stub _wtol +@ forward _wtoi NTDLL._wtoi +@ forward _wtol NTDLL._wtol @ cdecl _y0(double) CRTDLL__y0 @ cdecl _y1(double) CRTDLL__y1 @ cdecl _yn(long double) CRTDLL__yn @@ -376,14 +376,14 @@ debug_channels (crtdll) @ cdecl fgetc(ptr) CRTDLL_fgetc @ cdecl fgetpos(ptr ptr) CRTDLL_fgetpos @ cdecl fgets(ptr long ptr) CRTDLL_fgets -@ stub fgetwc +@ cdecl fgetwc(ptr) CRTDLL_fgetwc @ cdecl floor(double) floor @ cdecl fmod(double double) fmod @ cdecl fopen(str str) CRTDLL_fopen @ varargs fprintf(ptr str) CRTDLL_fprintf @ cdecl fputc(long ptr) CRTDLL_fputc @ cdecl fputs(str ptr) CRTDLL_fputs -@ stub fputwc +@ cdecl fputwc(long ptr) CRTDLL_fputwc @ cdecl fread(ptr long long ptr) CRTDLL_fread @ cdecl free(ptr) CRTDLL_free @ cdecl freopen(str str ptr) CRTDLL_freopen @@ -458,7 +458,7 @@ debug_channels (crtdll) @ cdecl remove(str) CRTDLL_remove @ cdecl rename(str str) CRTDLL_rename @ cdecl rewind(ptr) CRTDLL_rewind -@ stub scanf +@ varargs scanf(str) CRTDLL_scanf @ cdecl setbuf(ptr ptr) CRTDLL_setbuf @ cdecl setlocale(long ptr) CRTDLL_setlocale @ stub setvbuf diff --git a/dlls/crtdll/crtdll_main.c b/dlls/crtdll/crtdll_main.c index 01a7dbeebdd..b3fbc72d388 100644 --- a/dlls/crtdll/crtdll_main.c +++ b/dlls/crtdll/crtdll_main.c @@ -67,6 +67,7 @@ UINT CRTDLL_osminor_dll; /* CRTDLL.242 */ UINT CRTDLL_osmode_dll; /* CRTDLL.243 */ UINT CRTDLL_osver_dll; /* CRTDLL.244 */ UINT CRTDLL_osversion_dll; /* CRTDLL.245 */ +LONG CRTDLL_timezone_dll = 1; /* CRTDLL.245 */ UINT CRTDLL_winmajor_dll; /* CRTDLL.329 */ UINT CRTDLL_winminor_dll; /* CRTDLL.330 */ UINT CRTDLL_winver_dll; /* CRTDLL.331 */ @@ -687,78 +688,262 @@ INT __cdecl CRTDLL__isctype(INT c, UINT type) } -/********************************************************************* - * _fullpath (CRTDLL.114) - */ -LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT size) +/* INTERNAL: Helper for _fullpath. Modified PD code from 'snippets'. */ +static void fln_fix(char *path) { - if (!buf) + int dir_flag = 0, root_flag = 0; + char *r, *p, *q, *s; + + /* Skip drive */ + if (NULL == (r = strrchr(path, ':'))) + r = path; + else + ++r; + + /* Ignore leading slashes */ + while ('\\' == *r) + if ('\\' == r[1]) + strcpy(r, &r[1]); + else + { + root_flag = 1; + ++r; + } + + p = r; /* Change "\\" to "\" */ + while (NULL != (p = strchr(p, '\\'))) + if ('\\' == p[1]) + strcpy(p, &p[1]); + else + ++p; + + while ('.' == *r) /* Scrunch leading ".\" */ { - size = 256; - if(!(buf = CRTDLL_malloc(size))) return NULL; + if ('.' == r[1]) + { + /* Ignore leading ".." */ + for (p = (r += 2); *p && (*p != '\\'); ++p) + ; + } + else + { + for (p = r + 1 ;*p && (*p != '\\'); ++p) + ; + } + strcpy(r, p + ((*p) ? 1 : 0)); } - if (!GetFullPathNameA( name, size, buf, NULL )) return NULL; - TRACE("CRTDLL_fullpath got %s\n",buf); - return buf; + + while ('\\' == path[strlen(path)-1]) /* Strip last '\\' */ + { + dir_flag = 1; + path[strlen(path)-1] = '\0'; + } + + s = r; + + /* Look for "\." in path */ + + while (NULL != (p = strstr(s, "\\."))) + { + if ('.' == p[2]) + { + /* Execute this section if ".." found */ + q = p - 1; + while (q > r) /* Backup one level */ + { + if (*q == '\\') + break; + --q; + } + if (q > r) + { + strcpy(q, p + 3); + s = q; + } + else if ('.' != *q) + { + strcpy(q + ((*q == '\\') ? 1 : 0), + p + 3 + ((*(p + 3)) ? 1 : 0)); + s = q; + } + else s = ++p; + } + else + { + /* Execute this section if "." found */ + q = p + 2; + for ( ;*q && (*q != '\\'); ++q) + ; + strcpy (p, q); + } + } + + if (root_flag) /* Embedded ".." could have bubbled up to root */ + { + for (p = r; *p && ('.' == *p || '\\' == *p); ++p) + ; + if (r != p) + strcpy(r, p); + } + + if (dir_flag) + strcat(path, "\\"); +} + + +/********************************************************************* + * _fullpath + * + * Convert a partial path into a complete, normalised path. + */ +LPSTR __cdecl CRTDLL__fullpath(LPSTR absPath, LPCSTR relPath, INT size) +{ + char drive[5],dir[MAX_PATH],file[MAX_PATH],ext[MAX_PATH]; + char res[MAX_PATH]; + size_t len; + + res[0] = '\0'; + + if (!relPath || !*relPath) + return CRTDLL__getcwd(absPath, size); + + if (size < 4) + { + CRTDLL_errno = ERANGE; + return NULL; + } + + TRACE(":resolving relative path '%s'\n",relPath); + + CRTDLL__splitpath(relPath, drive, dir, file, ext); + + /* Get Directory and drive into 'res' */ + if (!dir[0] || (dir[0] != '/' && dir[0] != '\\')) + { + /* Relative or no directory given */ + CRTDLL__getdcwd(drive[0] ? toupper(drive[0]) - 'A' + 1 : 0, res, MAX_PATH); + strcat(res,"\\"); + if (dir[0]) + strcat(res,dir); + if (drive[0]) + res[0] = drive[0]; /* If given a drive, preserve the letter case */ + } + else + { + strcpy(res,drive); + strcat(res,dir); + } + + strcat(res,"\\"); + strcat(res, file); + strcat(res, ext); + fln_fix(res); + + len = strlen(res); + if (len >= MAX_PATH || len >= size) + return NULL; /* FIXME: errno? */ + + if (!absPath) + return CRTDLL__strdup(res); + strcpy(absPath,res); + return absPath; } /********************************************************************* * _splitpath (CRTDLL.279) + * + * Split a path string into components. + * + * PARAMETERS + * inpath [in] Path to split + * drive [out] "x:" or "" + * directory [out] "\dir", "\dir\", "/dir", "/dir/", "./" etc + * filename [out] filename, without dot or slashes + * extension [out] ".ext" or "" */ -VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension ) +VOID __cdecl CRTDLL__splitpath(LPCSTR inpath, LPSTR drv, LPSTR dir, + LPSTR fname, LPSTR ext ) { - /* drive includes : - directory includes leading and trailing (forward and backward slashes) - filename without dot and slashes - extension with leading dot - */ - char * drivechar,*dirchar,*namechar; + /* Modified PD code from 'snippets' collection. */ + char ch, *ptr, *p; + char pathbuff[MAX_PATH],*path=pathbuff; - TRACE("CRTDLL__splitpath got %s\n",path); + TRACE(":splitting path '%s'\n",path); + strcpy(pathbuff, inpath); - drivechar = strchr(path,':'); - dirchar = strrchr(path,'/'); - namechar = strrchr(path,'\\'); - dirchar = max(dirchar,namechar); - if (dirchar) - namechar = strrchr(dirchar,'.'); + /* convert slashes to backslashes for searching */ + for (ptr = (char*)path; *ptr; ++ptr) + if ('/' == *ptr) + *ptr = '\\'; + + /* look for drive spec */ + if ('\0' != (ptr = strchr(path, ':'))) + { + ++ptr; + if (drv) + { + strncpy(drv, path, ptr - path); + drv[ptr - path] = '\0'; + } + path = ptr; + } + else if (drv) + *drv = '\0'; + + /* find rightmost backslash or leftmost colon */ + if (NULL == (ptr = strrchr(path, '\\'))) + ptr = (strchr(path, ':')); + + if (!ptr) + { + ptr = (char *)path; /* no path */ + if (dir) + *dir = '\0'; + } else - namechar = strrchr(path,'.'); + { + ++ptr; /* skip the delimiter */ + if (dir) + { + ch = *ptr; + *ptr = '\0'; + strcpy(dir, path); + *ptr = ch; + } + } - if (drive) - { - *drive = 0x00; - if (drivechar) - { - strncat(drive,path,drivechar-path+1); - path = drivechar+1; - } - } - if (directory) - { - *directory = 0x00; - if (dirchar) - { - strncat(directory,path,dirchar-path+1); - path = dirchar+1; - } - } - if (filename) - { - *filename = 0x00; - if (namechar) - { - strncat(filename,path,namechar-path); - if (extension) - { - *extension = 0x00; - strcat(extension,namechar); - } - } - } + if (NULL == (p = strrchr(ptr, '.'))) + { + if (fname) + strcpy(fname, ptr); + if (ext) + *ext = '\0'; + } + else + { + *p = '\0'; + if (fname) + strcpy(fname, ptr); + *p = '.'; + if (ext) + strcpy(ext, p); + } - TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension); + /* Fix pathological case - Win returns ':' as part of the + * directory when no drive letter is given. + */ + if (drv && drv[0] == ':') + { + *drv = '\0'; + if (dir) + { + pathbuff[0] = ':'; + pathbuff[1] = '\0'; + strcat(pathbuff,dir); + strcpy(dir,pathbuff); + } + } } @@ -770,7 +955,8 @@ VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR INT __cdecl CRTDLL__matherr(struct _exception *e) { /* FIXME: Supposedly this can be user overridden, but - * currently it will never be called anyway. + * currently it will never be called anyway. User will + * need to use .spec ignore directive to override. */ FIXME(":Unhandled math error!\n"); return e == NULL ? 0 : 0; @@ -780,7 +966,6 @@ INT __cdecl CRTDLL__matherr(struct _exception *e) /********************************************************************* * _makepath (CRTDLL.182) */ - VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive, LPCSTR directory, LPCSTR filename, LPCSTR extension ) @@ -1016,7 +1201,7 @@ INT __cdecl CRTDLL_isgraph(INT c) /********************************************************************* * isleadbyte (CRTDLL.447) */ -INT __cdecl CRTDLL_isleadbyte(unsigned char c) +INT __cdecl CRTDLL_isleadbyte(UCHAR c) { return CRTDLL__isctype( c, CRTDLL_LEADBYTE ); } diff --git a/dlls/crtdll/dir.c b/dlls/crtdll/dir.c index 8fabdb17f7d..ff370c1cb4e 100644 --- a/dlls/crtdll/dir.c +++ b/dlls/crtdll/dir.c @@ -205,11 +205,13 @@ INT __cdecl CRTDLL__findnext(DWORD hand, find_t * ft) CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT size) { char dir[_MAX_PATH]; - int dir_len = GetCurrentDirectoryA(_MAX_PATH,dir); + int dir_len = GetCurrentDirectoryA(MAX_PATH,dir); if (dir_len < 1) return NULL; /* FIXME: Real return value untested */ + TRACE(":returning '%s'\n", dir); + if (!buf) { if (size < 0) @@ -232,10 +234,12 @@ CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT size) * Get the current directory on a drive. A: =1, B: =2, etc. * Passing drive 0 means the current drive. */ -CHAR* __cdecl CRTDLL__getdcwd(INT drive,LPSTR buf, INT size) +CHAR* __cdecl CRTDLL__getdcwd(INT drive, LPSTR buf, INT size) { static CHAR* dummy; + TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size); + if (!drive || drive == CRTDLL__getdrive()) return CRTDLL__getcwd(buf,size); /* current */ else @@ -258,6 +262,7 @@ CHAR* __cdecl CRTDLL__getdcwd(INT drive,LPSTR buf, INT size) return NULL; /* buf too small */ } + TRACE(":returning '%s'\n", dir); if (!buf) return CRTDLL__strdup(dir); /* allocate */ diff --git a/dlls/crtdll/file.c b/dlls/crtdll/file.c index 92d7808aa49..9bb4bc2ebd4 100644 --- a/dlls/crtdll/file.c +++ b/dlls/crtdll/file.c @@ -394,8 +394,21 @@ CRTDLL_FILE* __cdecl CRTDLL__fdopen(INT fd, LPCSTR mode) } +/********************************************************************* + * _fgetwchar (CRTDLL.062) + * + * Read a wide character from stdin. + */ +WCHAR __cdecl CRTDLL__fgetwchar( VOID ) +{ + return CRTDLL_fgetwc(CRTDLL_stdin); +} + + /********************************************************************* * _fgetchar (CRTDLL.092) + * + * Read a character from stdin. */ INT __cdecl CRTDLL__fgetchar( VOID ) { @@ -505,6 +518,17 @@ INT __cdecl CRTDLL__fputchar(INT c) } +/********************************************************************* + * _fputwchar (CRTDLL.109) + * + * Put a wide character to stdout. + */ +WCHAR __cdecl CRTDLL__fputwchar( WCHAR wc ) +{ + return CRTDLL_fputwc(wc, CRTDLL_stdout); +} + + /********************************************************************* * _fsopen (CRTDLL.110) * @@ -640,7 +664,7 @@ INT __cdecl CRTDLL__getw( CRTDLL_FILE* file ) { INT i; if (CRTDLL__read(file->_file, &i, sizeof(INT)) != 1) - return EOF; + return CRTDLL_EOF; return i; } @@ -853,7 +877,7 @@ INT __cdecl CRTDLL__open_osfhandle(HANDLE hand, INT flags) */ INT __cdecl CRTDLL__putw(INT val, CRTDLL_FILE* file) { - return CRTDLL__write(file->_file, &val, sizeof(val)) == 1? val : EOF; + return CRTDLL__write(file->_file, &val, sizeof(val)) == 1? val : CRTDLL_EOF; } @@ -1174,7 +1198,7 @@ INT __cdecl CRTDLL_fgetc( CRTDLL_FILE* file ) { char c; if (CRTDLL__read(file->_file,&c,1) != 1) - return EOF; + return CRTDLL_EOF; return c; } @@ -1204,14 +1228,14 @@ CHAR* __cdecl CRTDLL_fgets(LPSTR s, INT size, CRTDLL_FILE* file) * windows95's ftp.exe. * JG - Is this true now we use ReadFile() on stdin too? */ - for(cc = CRTDLL_fgetc(file); cc != EOF && cc != '\n'; + for(cc = CRTDLL_fgetc(file); cc != CRTDLL_EOF && cc != '\n'; cc = CRTDLL_fgetc(file)) if (cc != '\r') { if (--size <= 0) break; *s++ = (char)cc; } - if ((cc == EOF) && (s == buf_start)) /* If nothing read, return 0*/ + if ((cc == CRTDLL_EOF) && (s == buf_start)) /* If nothing read, return 0*/ { TRACE(":nothing read\n"); return 0; @@ -1225,6 +1249,33 @@ CHAR* __cdecl CRTDLL_fgets(LPSTR s, INT size, CRTDLL_FILE* file) } +/********************************************************************* + * fgetwc (CRTDLL.366) + * + * Read a wide character from a FILE*. + */ +WCHAR __cdecl CRTDLL_fgetwc( CRTDLL_FILE* file ) +{ + WCHAR wc; + if (CRTDLL__read(file->_file, &wc, sizeof(wc)) != sizeof(wc)) + return CRTDLL_WEOF; + return wc; +} + + +/********************************************************************* + * fputwc (CRTDLL.373) + * + * Write a wide character to a FILE*. + */ +WCHAR __cdecl CRTDLL_fputwc( WCHAR wc, CRTDLL_FILE* file) +{ + if (CRTDLL__write(file->_file, &wc, sizeof(wc)) != sizeof(wc)) + return CRTDLL_WEOF; + return wc; +} + + /********************************************************************* * fputs (CRTDLL.375) */ @@ -1318,7 +1369,7 @@ CRTDLL_FILE* __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode) */ INT __cdecl CRTDLL_fputc( INT c, CRTDLL_FILE* file ) { - return CRTDLL__write(file->_file, &c, 1) == 1? c : EOF; + return CRTDLL__write(file->_file, &c, 1) == 1? c : CRTDLL_EOF; } @@ -1393,8 +1444,9 @@ INT __cdecl CRTDLL_fsetpos( CRTDLL_FILE* file, CRTDLL_fpos_t *pos) /********************************************************************* * fscanf (CRTDLL.381) */ -INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) +INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPCSTR format, ... ) { + /* NOTE: If you extend this function, extend CRTDLL__cscanf in console.c too */ INT rd = 0; int nch; va_list ap; @@ -1405,7 +1457,7 @@ INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) while (*format) { if (*format == ' ') { /* skip whitespace */ - while ((nch!=EOF) && isspace(nch)) + while ((nch!=CRTDLL_EOF) && isspace(nch)) nch = CRTDLL_fgetc(file); } else if (*format == '%') { @@ -1416,7 +1468,7 @@ INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) int*val = va_arg(ap, int*); int cur = 0; /* skip initial whitespace */ - while ((nch!=EOF) && isspace(nch)) + while ((nch!=CRTDLL_EOF) && isspace(nch)) nch = CRTDLL_fgetc(file); /* get sign and first digit */ if (nch == '-') { @@ -1431,7 +1483,7 @@ INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) } nch = CRTDLL_fgetc(file); /* read until no more digits */ - while ((nch!=EOF) && isdigit(nch)) { + while ((nch!=CRTDLL_EOF) && isdigit(nch)) { cur = cur*10 + (nch - '0'); nch = CRTDLL_fgetc(file); } @@ -1443,7 +1495,7 @@ INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) float*val = va_arg(ap, float*); float cur = 0; /* skip initial whitespace */ - while ((nch!=EOF) && isspace(nch)) + while ((nch!=CRTDLL_EOF) && isspace(nch)) nch = CRTDLL_fgetc(file); /* get sign and first digit */ if (nch == '-') { @@ -1457,7 +1509,7 @@ INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) else break; } /* read until no more digits */ - while ((nch!=EOF) && isdigit(nch)) { + while ((nch!=CRTDLL_EOF) && isdigit(nch)) { cur = cur*10 + (nch - '0'); nch = CRTDLL_fgetc(file); } @@ -1465,7 +1517,7 @@ INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) /* handle decimals */ float dec = 1; nch = CRTDLL_fgetc(file); - while ((nch!=EOF) && isdigit(nch)) { + while ((nch!=CRTDLL_EOF) && isdigit(nch)) { dec /= 10; cur += dec * (nch - '0'); nch = CRTDLL_fgetc(file); @@ -1479,10 +1531,10 @@ INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) char*str = va_arg(ap, char*); char*sptr = str; /* skip initial whitespace */ - while ((nch!=EOF) && isspace(nch)) + while ((nch!=CRTDLL_EOF) && isspace(nch)) nch = CRTDLL_fgetc(file); /* read until whitespace */ - while ((nch!=EOF) && !isspace(nch)) { + while ((nch!=CRTDLL_EOF) && !isspace(nch)) { *sptr++ = nch; st++; nch = CRTDLL_fgetc(file); } @@ -1505,7 +1557,7 @@ INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... ) format++; } va_end(ap); - if (nch!=EOF) { + if (nch!=CRTDLL_EOF) { WARN("need ungetch\n"); } TRACE("returning %d\n", rd); @@ -1573,7 +1625,7 @@ LPSTR __cdecl CRTDLL_gets(LPSTR buf) * windows95's ftp.exe. * JG 19/9/00: Is this still true, now we are using ReadFile? */ - for(cc = CRTDLL_fgetc(CRTDLL_stdin); cc != EOF && cc != '\n'; + for(cc = CRTDLL_fgetc(CRTDLL_stdin); cc != CRTDLL_EOF && cc != '\n'; cc = CRTDLL_fgetc(CRTDLL_stdin)) if(cc != '\r') *buf++ = (char)cc; @@ -1611,6 +1663,20 @@ INT __cdecl CRTDLL_puts(LPCSTR s) } +/********************************************************************* + * remove (CRTDLL.445) + */ +INT __cdecl CRTDLL_remove(LPCSTR path) +{ + TRACE(":path (%s)\n",path); + if (DeleteFileA(path)) + return 0; + TRACE(":failed-last error (%ld)\n",GetLastError()); + __CRTDLL__set_errno(GetLastError()); + return -1; +} + + /********************************************************************* * rewind (CRTDLL.447) * @@ -1626,16 +1692,17 @@ VOID __cdecl CRTDLL_rewind(CRTDLL_FILE* file) /********************************************************************* - * remove (CRTDLL.448) + * scanf (CRTDLL.448) */ -INT __cdecl CRTDLL_remove(LPCSTR path) +INT __cdecl CRTDLL_scanf( LPCSTR format, ... ) { - TRACE(":path (%s)\n",path); - if (DeleteFileA(path)) - return 0; - TRACE(":failed-last error (%ld)\n",GetLastError()); - __CRTDLL__set_errno(GetLastError()); - return -1; + va_list valist; + INT res; + + va_start( valist, format ); + res = CRTDLL_fscanf(CRTDLL_stdin, format, valist); + va_end(va_list); + return res; } diff --git a/dlls/crtdll/locale.c b/dlls/crtdll/locale.c index b99c80ce7ee..2ae7f02e9b5 100644 --- a/dlls/crtdll/locale.c +++ b/dlls/crtdll/locale.c @@ -36,12 +36,15 @@ * a table for a supported Wine locale, mail it to me and * I will add the needed support (jon_p_griffiths@yahoo.com). */ + #include "crtdll.h" -#include + #include #include #include +#include "winnt.h" + DEFAULT_DEBUG_CHANNEL(crtdll); #define MAX_ELEM_LEN 64 /* Max length of country/language/CP string */ diff --git a/dlls/crtdll/spawn.c b/dlls/crtdll/spawn.c index c13c5ba0a7a..2bbb447d947 100644 --- a/dlls/crtdll/spawn.c +++ b/dlls/crtdll/spawn.c @@ -147,7 +147,7 @@ static LPSTR __CRTDLL__argvtos(LPCSTR *arg, CHAR delim) * * Wait for a spawned process to finish. */ -INT __cdecl CRTDLL__cwait(PINT status, INT pid, INT action) +INT __cdecl CRTDLL__cwait(LPINT status, INT pid, INT action) { HANDLE hPid = (HANDLE)pid;