4 * Implements C run-time functionality as known from UNIX.
6 * Copyright 1996,1998 Marcus Meissner
7 * Copyright 1996 Jukka Iivonen
8 * Copyright 1997,2000 Uwe Bonnes
9 * Copyright 2000 Jon Griffiths
13 Unresolved issues Uwe Bonnes 970904:
14 - tested with ftp://ftp.remcomp.com/pub/remcomp/lcc-win32.zip, a C-Compiler
15 for Win32, based on lcc, from Jacob Navia
17 - probably not thread safe
20 /* NOTE: This file also implements the wcs* functions. They _ARE_ in
21 * the newer Linux libcs, but use 4 byte wide characters, so are unusable,
22 * since we need 2 byte wide characters. - Marcus Meissner, 981031
27 #define __USE_ISOC9X 1 /* for isfinite */
36 DEFAULT_DEBUG_CHANNEL(crtdll);
39 UINT CRTDLL_argc_dll; /* CRTDLL.23 */
40 LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
41 LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
42 UINT CRTDLL_basemajor_dll; /* CRTDLL.42 */
43 UINT CRTDLL_baseminor_dll; /* CRTDLL.43 */
44 UINT CRTDLL_baseversion_dll; /* CRTDLL.44 */
45 UINT CRTDLL_commode_dll; /* CRTDLL.59 */
46 LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
47 UINT CRTDLL_fmode_dll; /* CRTDLL.104 */
48 UINT CRTDLL_osmajor_dll; /* CRTDLL.241 */
49 UINT CRTDLL_osminor_dll; /* CRTDLL.242 */
50 UINT CRTDLL_osmode_dll; /* CRTDLL.243 */
51 UINT CRTDLL_osver_dll; /* CRTDLL.244 */
52 UINT CRTDLL_osversion_dll; /* CRTDLL.245 */
53 UINT CRTDLL_winmajor_dll; /* CRTDLL.329 */
54 UINT CRTDLL_winminor_dll; /* CRTDLL.330 */
55 UINT CRTDLL_winver_dll; /* CRTDLL.331 */
56 INT CRTDLL_doserrno = 0;
58 const INT CRTDLL__sys_nerr = 43;
61 /*********************************************************************
62 * CRTDLL_MainInit (CRTDLL.init)
64 BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
66 TRACE("(0x%08x,%ld,%p)\n",hinstDLL,fdwReason,lpvReserved);
68 if (fdwReason == DLL_PROCESS_ATTACH) {
75 /* INTERNAL: Set the crt and dos errno's from the OS error given. */
76 void __CRTDLL__set_errno(ULONG err)
78 /* FIXME: not MT safe */
79 CRTDLL_doserrno = err;
83 #define ERR_CASE(oserr) case oserr:
84 #define ERR_MAPS(oserr,crterr) case oserr:CRTDLL_errno = crterr;break;
85 ERR_CASE(ERROR_ACCESS_DENIED)
86 ERR_CASE(ERROR_NETWORK_ACCESS_DENIED)
87 ERR_CASE(ERROR_CANNOT_MAKE)
88 ERR_CASE(ERROR_SEEK_ON_DEVICE)
89 ERR_CASE(ERROR_LOCK_FAILED)
90 ERR_CASE(ERROR_FAIL_I24)
91 ERR_CASE(ERROR_CURRENT_DIRECTORY)
92 ERR_CASE(ERROR_DRIVE_LOCKED)
93 ERR_CASE(ERROR_NOT_LOCKED)
94 ERR_CASE(ERROR_INVALID_ACCESS)
95 ERR_MAPS(ERROR_LOCK_VIOLATION, EACCES);
96 ERR_CASE(ERROR_FILE_NOT_FOUND)
97 ERR_CASE(ERROR_NO_MORE_FILES)
98 ERR_CASE(ERROR_BAD_PATHNAME)
99 ERR_CASE(ERROR_BAD_NETPATH)
100 ERR_CASE(ERROR_INVALID_DRIVE)
101 ERR_CASE(ERROR_BAD_NET_NAME)
102 ERR_CASE(ERROR_FILENAME_EXCED_RANGE)
103 ERR_MAPS(ERROR_PATH_NOT_FOUND, ENOENT);
104 ERR_MAPS(ERROR_IO_DEVICE, EIO);
105 ERR_MAPS(ERROR_BAD_FORMAT, ENOEXEC);
106 ERR_MAPS(ERROR_INVALID_HANDLE, EBADF);
107 ERR_CASE(ERROR_OUTOFMEMORY)
108 ERR_CASE(ERROR_INVALID_BLOCK)
109 ERR_CASE(ERROR_NOT_ENOUGH_QUOTA);
110 ERR_MAPS(ERROR_ARENA_TRASHED, ENOMEM);
111 ERR_MAPS(ERROR_BUSY, EBUSY);
112 ERR_CASE(ERROR_ALREADY_EXISTS)
113 ERR_MAPS(ERROR_FILE_EXISTS, EEXIST);
114 ERR_MAPS(ERROR_BAD_DEVICE, ENODEV);
115 ERR_MAPS(ERROR_TOO_MANY_OPEN_FILES, EMFILE);
116 ERR_MAPS(ERROR_DISK_FULL, ENOSPC);
117 ERR_MAPS(ERROR_BROKEN_PIPE, EPIPE);
118 ERR_MAPS(ERROR_POSSIBLE_DEADLOCK, EDEADLK);
119 ERR_MAPS(ERROR_DIR_NOT_EMPTY, ENOTEMPTY);
120 ERR_MAPS(ERROR_BAD_ENVIRONMENT, E2BIG);
121 ERR_CASE(ERROR_WAIT_NO_CHILDREN)
122 ERR_MAPS(ERROR_CHILD_NOT_COMPLETE, ECHILD);
123 ERR_CASE(ERROR_NO_PROC_SLOTS)
124 ERR_CASE(ERROR_MAX_THRDS_REACHED)
125 ERR_MAPS(ERROR_NESTING_NOT_ALLOWED, EAGAIN);
127 /* Remaining cases map to EINVAL */
128 /* FIXME: may be missing some errors above */
129 CRTDLL_errno = EINVAL;
133 #if defined(__GNUC__) && defined(__i386__)
134 #define FPU_DOUBLE(var) double var; \
135 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
136 #define FPU_DOUBLES(var1,var2) double var1,var2; \
137 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
138 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
140 #define FPU_DOUBLE(var) double var = quiet_nan(); \
141 FIXME(":not implemented\n");
142 #define FPU_DOUBLES(var1,var2) double var1,var2; \
143 var1=var2=quiet_nan(); FIXME(":not implemented\n")
146 /*********************************************************************
147 * _CIacos (CRTDLL.004)
149 double __cdecl CRTDLL__CIacos(void)
156 /*********************************************************************
157 * _CIasin (CRTDLL.005)
159 double __cdecl CRTDLL__CIasin(void)
166 /*********************************************************************
167 * _CIatan (CRTDLL.006)
169 double __cdecl CRTDLL__CIatan(void)
175 /*********************************************************************
176 * _CIatan2 (CRTDLL.007)
178 double __cdecl CRTDLL__CIatan2(void)
185 /*********************************************************************
186 * _CIcos (CRTDLL.008)
188 double __cdecl CRTDLL__CIcos(void)
194 /*********************************************************************
195 * _CIcosh (CRTDLL.009)
197 double __cdecl CRTDLL__CIcosh(void)
203 /*********************************************************************
204 * _CIexp (CRTDLL.010)
206 double __cdecl CRTDLL__CIexp(void)
212 /*********************************************************************
213 * _CIfmod (CRTDLL.011)
215 double __cdecl CRTDLL__CIfmod(void)
221 /*********************************************************************
222 * _CIlog (CRTDLL.012)
224 double __cdecl CRTDLL__CIlog(void)
230 /*********************************************************************
231 * _CIlog10 (CRTDLL.013)
233 double __cdecl CRTDLL__CIlog10(void)
239 /*********************************************************************
240 * _CIsin (CRTDLL.015)
242 double __cdecl CRTDLL__CIsin(void)
248 /*********************************************************************
249 * _CIsinh (CRTDLL.016)
251 double __cdecl CRTDLL__CIsinh(void)
257 /*********************************************************************
258 * _CIsqrt (CRTDLL.017)
260 double __cdecl CRTDLL__CIsqrt(void)
266 /*********************************************************************
267 * _CItan (CRTDLL.018)
269 double __cdecl CRTDLL__CItan(void)
275 /*********************************************************************
276 * _CItanh (CRTDLL.019)
278 double __cdecl CRTDLL__CItanh(void)
284 /*********************************************************************
285 * _GetMainArgs (CRTDLL.022)
287 LPSTR * __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
288 LPSTR *environ,DWORD flag)
292 int xargc,end,last_arg,afterlastspace;
295 TRACE("(%p,%p,%p,%ld).\n",
296 argc,argv,environ,flag
299 if (CRTDLL_acmdln_dll != NULL)
300 HeapFree(GetProcessHeap(), 0, CRTDLL_acmdln_dll);
302 CRTDLL_acmdln_dll = cmdline = CRTDLL__strdup( GetCommandLineA() );
303 TRACE("got '%s'\n", cmdline);
305 version = GetVersion();
306 CRTDLL_osver_dll = version >> 16;
307 CRTDLL_winminor_dll = version & 0xFF;
308 CRTDLL_winmajor_dll = (version>>8) & 0xFF;
309 CRTDLL_baseversion_dll = version >> 16;
310 CRTDLL_winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
311 CRTDLL_baseminor_dll = (version >> 16) & 0xFF;
312 CRTDLL_basemajor_dll = (version >> 24) & 0xFF;
313 CRTDLL_osversion_dll = version & 0xFFFF;
314 CRTDLL_osminor_dll = version & 0xFF;
315 CRTDLL_osmajor_dll = (version>>8) & 0xFF;
317 /* missing threading init */
319 end=0;last_arg=0;xargv=NULL;xargc=0;afterlastspace=0;
322 if ((cmdline[end]==' ') || (cmdline[end]=='\0'))
324 if (cmdline[end]=='\0')
328 /* alloc xargc + NULL entry */
329 xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
330 sizeof(char*)*(xargc+1));
331 if (strlen(cmdline+afterlastspace))
333 xargv[xargc] = CRTDLL__strdup(cmdline+afterlastspace);
335 if (!last_arg) /* need to seek to the next arg ? */
338 while (cmdline[end]==' ')
345 xargv[xargc] = NULL; /* the last entry is NULL */
352 CRTDLL_argc_dll = xargc;
354 CRTDLL_argv_dll = xargv;
357 TRACE("found %d arguments\n",
359 CRTDLL_environ_dll = *environ = GetEnvironmentStringsA();
364 /*********************************************************************
365 * _fpclass (CRTDLL.105)
367 * Return the FP classification of d.
369 INT __cdecl CRTDLL__fpclass(double d)
371 switch (fpclassify( d ))
373 case FP_NAN: return _FPCLASS_QNAN;
376 return _FPCLASS_NINF;
377 return _FPCLASS_PINF;
395 /*********************************************************************
396 * _initterm (CRTDLL.135)
398 DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
400 _INITTERMFUN *current;
402 TRACE("(%p,%p)\n",start,end);
404 while (current<end) {
405 if (*current) (*current)();
412 /*******************************************************************
413 * _global_unwind2 (CRTDLL.129)
415 void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
417 RtlUnwind( frame, 0, NULL, 0 );
421 /*******************************************************************
422 * _local_unwind2 (CRTDLL.173)
424 void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
426 TRACE("(%p,%ld)\n",endframe,nr);
430 /*******************************************************************
431 * _setjmp (CRTDLL.264)
433 INT __cdecl CRTDLL__setjmp(LPDWORD *jmpbuf)
435 FIXME(":(%p): stub\n",jmpbuf);
440 /*********************************************************************
443 * Output a tone using the PC speaker.
446 * freq [in] Frequency of the tone
448 * duration [in] Length of time the tone should sound
453 void __cdecl CRTDLL__beep( UINT freq, UINT duration)
455 TRACE(":Freq %d, Duration %d\n",freq,duration);
456 Beep(freq, duration);
460 /*********************************************************************
463 INT __cdecl CRTDLL_rand()
465 return (rand() & CRTDLL_RAND_MAX);
469 /*********************************************************************
472 UINT __cdecl CRTDLL__rotl(UINT x,INT shift)
475 return (x << shift) | (x >> (32-shift));
479 /*********************************************************************
480 * _lrotl (CRTDLL.175)
482 DWORD __cdecl CRTDLL__lrotl(DWORD x,INT shift)
485 return (x << shift) | (x >> (32-shift));
489 /*********************************************************************
490 * _lrotr (CRTDLL.176)
492 DWORD __cdecl CRTDLL__lrotr(DWORD x,INT shift)
495 return (x >> shift) | (x << (32-shift));
499 /*********************************************************************
502 DWORD __cdecl CRTDLL__rotr(UINT x,INT shift)
505 return (x >> shift) | (x << (32-shift));
509 /*********************************************************************
510 * _scalb (CRTDLL.259)
514 double __cdecl CRTDLL__scalb(double x, LONG y)
516 /* Note - Can't forward directly as libc expects y as double */
517 double y2 = (double)y;
518 return scalb( x, y2 );
522 /*********************************************************************
523 * vswprintf (CRTDLL.501)
525 INT __cdecl CRTDLL_vswprintf( LPWSTR buffer, LPCWSTR spec, va_list args )
527 return wvsprintfW( buffer, spec, args );
531 /*********************************************************************
532 * longjmp (CRTDLL.426)
534 VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
536 FIXME("CRTDLL_longjmp semistup, expect crash\n");
541 /*********************************************************************
542 * setlocale (CRTDLL.453)
544 LPSTR __cdecl CRTDLL_setlocale(INT category,LPCSTR locale)
549 case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
550 case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
551 case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
552 case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
553 case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
554 case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
555 default: categorystr = "UNKNOWN?";break;
557 FIXME("(%s,%s),stub!\n",categorystr,locale);
562 /*********************************************************************
563 * _isctype (CRTDLL.138)
565 BOOL __cdecl CRTDLL__isctype(CHAR x,CHAR type)
567 if ((type & CRTDLL_SPACE) && isspace(x))
569 if ((type & CRTDLL_PUNCT) && ispunct(x))
571 if ((type & CRTDLL_LOWER) && islower(x))
573 if ((type & CRTDLL_UPPER) && isupper(x))
575 if ((type & CRTDLL_ALPHA) && isalpha(x))
577 if ((type & CRTDLL_DIGIT) && isdigit(x))
579 if ((type & CRTDLL_CONTROL) && iscntrl(x))
581 /* check CRTDLL_LEADBYTE */
586 /*********************************************************************
587 * _fullpath (CRTDLL.114)
589 LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT size)
594 if(!(buf = CRTDLL_malloc(size))) return NULL;
596 if (!GetFullPathNameA( name, size, buf, NULL )) return NULL;
597 TRACE("CRTDLL_fullpath got %s\n",buf);
602 /*********************************************************************
603 * _splitpath (CRTDLL.279)
605 VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
608 directory includes leading and trailing (forward and backward slashes)
609 filename without dot and slashes
610 extension with leading dot
612 char * drivechar,*dirchar,*namechar;
614 TRACE("CRTDLL__splitpath got %s\n",path);
616 drivechar = strchr(path,':');
617 dirchar = strrchr(path,'/');
618 namechar = strrchr(path,'\\');
619 dirchar = max(dirchar,namechar);
621 namechar = strrchr(dirchar,'.');
623 namechar = strrchr(path,'.');
630 strncat(drive,path,drivechar-path+1);
639 strncat(directory,path,dirchar-path+1);
648 strncat(filename,path,namechar-path);
652 strcat(extension,namechar);
657 TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
661 /*********************************************************************
662 * _makepath (CRTDLL.182)
665 VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive,
666 LPCSTR directory, LPCSTR filename,
670 TRACE("CRTDLL__makepath got %s %s %s %s\n", drive, directory,
671 filename, extension);
677 if (drive && drive[0])
683 if (directory && directory[0])
685 strcat(path, directory);
686 ch = path[strlen(path)-1];
687 if (ch != '/' && ch != '\\')
690 if (filename && filename[0])
692 strcat(path, filename);
693 if (extension && extension[0])
695 if ( extension[0] != '.' ) {
698 strcat(path,extension);
702 TRACE("CRTDLL__makepath returns %s\n",path);
706 /*********************************************************************
708 * Return the address of the CRT errno (Not the libc errno).
713 LPINT __cdecl CRTDLL__errno( VOID )
715 return &CRTDLL_errno;
719 /*********************************************************************
720 * __doserrno (CRTDLL.26)
722 * Return the address of the DOS errno (holding the last OS error).
727 LPINT __cdecl CRTDLL___doserrno( VOID )
729 return &CRTDLL_doserrno;
733 /**********************************************************************
734 * _strerror (CRTDLL.284)
736 * Return a formatted system error message.
739 * The caller does not own the string returned.
741 extern int sprintf(char *str, const char *format, ...);
743 LPSTR __cdecl CRTDLL__strerror (LPCSTR err)
745 static char strerrbuff[256];
746 sprintf(strerrbuff,"%s: %s\n",err,CRTDLL_strerror(CRTDLL_errno));
751 /*********************************************************************
752 * perror (CRTDLL.435)
754 * Print a formatted system error message to stderr.
756 VOID __cdecl CRTDLL_perror (LPCSTR err)
758 char *err_str = CRTDLL_strerror(CRTDLL_errno);
759 CRTDLL_fprintf(CRTDLL_stderr,"%s: %s\n",err,err_str);
760 CRTDLL_free(err_str);
764 /*********************************************************************
765 * strerror (CRTDLL.465)
767 * Return the text of an error.
770 * The caller does not own the string returned.
772 extern char *strerror(int errnum);
774 LPSTR __cdecl CRTDLL_strerror (INT err)
776 return strerror(err);
780 /*********************************************************************
781 * signal (CRTDLL.455)
783 LPVOID __cdecl CRTDLL_signal(INT sig, sig_handler_type ptr)
785 FIXME("(%d %p):stub.\n", sig, ptr);
790 /*********************************************************************
791 * _sleep (CRTDLL.267)
793 VOID __cdecl CRTDLL__sleep(ULONG timeout)
795 TRACE("CRTDLL__sleep for %ld milliseconds\n",timeout);
796 Sleep((timeout)?timeout:1);
800 /*********************************************************************
801 * getenv (CRTDLL.437)
803 LPSTR __cdecl CRTDLL_getenv(LPCSTR name)
805 LPSTR environ = GetEnvironmentStringsA();
809 for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
816 if (!strncmp(pp,name,length)) break;
821 TRACE("got %s\n",pp);
823 FreeEnvironmentStringsA( environ );
828 /*********************************************************************
829 * _except_handler2 (CRTDLL.78)
831 INT __cdecl CRTDLL__except_handler2 (
832 PEXCEPTION_RECORD rec,
833 PEXCEPTION_FRAME frame,
835 PEXCEPTION_FRAME *dispatcher)
837 FIXME ("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
838 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
839 frame->Handler, context, dispatcher);
840 return ExceptionContinueSearch;
844 /*********************************************************************
845 * __isascii (CRTDLL.028)
848 INT __cdecl CRTDLL___isascii(INT c)
854 /*********************************************************************
855 * __toascii (CRTDLL.035)
858 INT __cdecl CRTDLL___toascii(INT c)
864 /*********************************************************************
865 * iswascii (CRTDLL.404)
868 INT __cdecl CRTDLL_iswascii(LONG c)
870 return ((unsigned)c < 0x80);
874 /*********************************************************************
875 * __iscsym (CRTDLL.029)
877 * Is a character valid in a C identifier (a-Z,0-9,_).
880 * c [I]: Character to check
883 * Non zero if c is valid as t a C identifier.
885 INT __cdecl CRTDLL___iscsym(LONG c)
887 return (isalnum(c) || c == '_');
891 /*********************************************************************
892 * __iscsymf (CRTDLL.030)
894 * Is a character valid as the first letter in a C identifier (a-Z,_).
897 * c [in] Character to check
900 * Non zero if c is valid as the first letter in a C identifier.
902 INT __cdecl CRTDLL___iscsymf(LONG c)
904 return (isalpha(c) || c == '_');
908 /*********************************************************************
909 * _loaddll (CRTDLL.171)
911 * Get a handle to a DLL in memory. The DLL is loaded if it is not already.
914 * dll [in] Name of DLL to load.
917 * Success: A handle to the loaded DLL.
921 INT __cdecl CRTDLL__loaddll(LPSTR dllname)
923 return LoadLibraryA(dllname);
927 /*********************************************************************
928 * _unloaddll (CRTDLL.313)
930 * Free reference to a DLL handle from loaddll().
933 * dll [in] Handle to free.
938 * Failure: Error number.
940 INT __cdecl CRTDLL__unloaddll(HANDLE dll)
943 if (FreeLibrary(dll))
945 err = GetLastError();
946 __CRTDLL__set_errno(err);
951 /*********************************************************************
952 * _lsearch (CRTDLL.177)
954 * Linear search of an array of elements. Adds the item to the array if
958 * match [in] Pointer to element to match
959 * start [in] Pointer to start of search memory
960 * array_size [in] Length of search array (element count)
961 * elem_size [in] Size of each element in memory
962 * comp_func [in] Pointer to comparason function (like qsort()).
965 * Pointer to the location where element was found or added.
967 LPVOID __cdecl CRTDLL__lsearch(LPVOID match,LPVOID start, LPUINT array_size,
968 UINT elem_size, comp_func cf)
970 UINT size = *array_size;
974 if (cf(match, start) == 0)
975 return start; /* found */
979 /* not found, add to end */
980 memcpy(start, match, elem_size);
986 /*********************************************************************
989 * Convert an integer to a wide char string.
991 extern LPSTR __cdecl _itoa( long , LPSTR , INT); /* ntdll */
993 WCHAR* __cdecl CRTDLL__itow(INT value,WCHAR* out,INT base)
995 char buff[64]; /* FIXME: Whats the maximum buffer size for INT_MAX? */
997 _itoa(value, buff, base);
998 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1003 /*********************************************************************
1006 * Convert a long to a wide char string.
1008 extern LPSTR __cdecl _ltoa( long , LPSTR , INT); /* ntdll */
1010 WCHAR* __cdecl CRTDLL__ltow(LONG value,WCHAR* out,INT base)
1012 char buff[64]; /* FIXME: Whats the maximum buffer size for LONG_MAX? */
1014 _ltoa(value, buff, base);
1015 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1020 /*********************************************************************
1021 * _ultow (CRTDLL.??)
1023 * Convert an unsigned long to a wide char string.
1025 extern LPSTR __cdecl _ultoa( long , LPSTR , INT); /* ntdll */
1027 WCHAR* __cdecl CRTDLL__ultow(ULONG value,WCHAR* out,INT base)
1029 char buff[64]; /* FIXME: Whats the maximum buffer size for ULONG_MAX? */
1031 _ultoa(value, buff, base);
1032 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1037 /*********************************************************************
1038 * _toupper (CRTDLL.489)
1040 CHAR __cdecl CRTDLL__toupper(CHAR c)
1046 /*********************************************************************
1047 * _tolower (CRTDLL.490)
1049 CHAR __cdecl CRTDLL__tolower(CHAR c)
1057 /*********************************************************************
1058 * _cabs (CRTDLL.048)
1060 * Return the absolue value of a complex number.
1063 * c [in] Structure containing real and imaginary parts of complex number.
1066 * Absolute value of complex number (always a positive real number).
1068 double __cdecl CRTDLL__cabs(struct complex c)
1070 return sqrt(c.real * c.real + c.imaginary * c.imaginary);
1074 /*********************************************************************
1075 * _chgsign (CRTDLL.053)
1077 * Change the sign of an IEEE double.
1080 * d [in] Number to invert.
1083 * Number with sign inverted.
1085 double __cdecl CRTDLL__chgsign(double d)
1087 /* FIXME: +-infinity,Nan not tested */
1092 /*********************************************************************
1093 * _control87 (CRTDLL.060)
1095 * Unimplemented. Obsolete. Give it up. Use controlfp(), if you must.
1098 UINT __cdecl CRTDLL__control87(UINT x, UINT y)
1100 /* Will never be supported, no possible targets have an 87/287 FP unit */
1101 WARN(":Ignoring control87 call, dont trust any FP results!\n");
1106 /*********************************************************************
1107 * _controlfp (CRTDLL.061)
1109 * Set the state of the floating point unit.
1120 UINT __cdecl CRTDLL__controlfp( UINT x, UINT y)
1127 /*********************************************************************
1128 * _copysign (CRTDLL.062)
1130 * Return the number x with the sign of y.
1132 double __cdecl CRTDLL__copysign(double x, double y)
1134 /* FIXME: Behaviour for Nan/Inf etc? */
1136 return x < 0.0 ? x : -x;
1138 return x < 0.0 ? -x : x;
1142 /*********************************************************************
1143 * _finite (CRTDLL.101)
1145 * Determine if an IEEE double is finite (i.e. not +/- Infinity).
1148 * d [in] Number to check.
1151 * Non zero if number is finite.
1153 INT __cdecl CRTDLL__finite(double d)
1155 return (isfinite(d)?1:0); /* See comment for CRTDLL__isnan() */
1159 /*********************************************************************
1160 * _fpreset (CRTDLL.107)
1162 * Reset the state of the floating point processor.
1173 VOID __cdecl CRTDLL__fpreset(void)
1179 /*********************************************************************
1180 * _isnan (CRTDLL.164)
1182 * Determine if an IEEE double is unrepresentable (NaN).
1185 * d [in] Number to check.
1188 * Non zero if number is NaN.
1190 INT __cdecl CRTDLL__isnan(double d)
1192 /* some implementations return -1 for true(glibc), crtdll returns 1.
1193 * Do the same, as the result may be used in calculations.
1195 return isnan(d)?1:0;
1199 /*********************************************************************
1200 * _purecall (CRTDLL.249)
1202 * Abort program after pure virtual function call.
1204 VOID __cdecl CRTDLL__purecall(VOID)
1206 CRTDLL__amsg_exit( 6025 );