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 */
28 #define __USE_ISOC99 1 /* for isfinite */
37 DEFAULT_DEBUG_CHANNEL(crtdll);
40 double CRTDLL_HUGE_dll; /* CRTDLL.20 */
41 UINT CRTDLL_argc_dll; /* CRTDLL.23 */
42 LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
43 LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
44 UINT CRTDLL_basemajor_dll; /* CRTDLL.42 */
45 UINT CRTDLL_baseminor_dll; /* CRTDLL.43 */
46 UINT CRTDLL_baseversion_dll; /* CRTDLL.44 */
47 UINT CRTDLL_commode_dll; /* CRTDLL.59 */
48 LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
49 UINT CRTDLL_fmode_dll; /* CRTDLL.104 */
50 UINT CRTDLL_osmajor_dll; /* CRTDLL.241 */
51 UINT CRTDLL_osminor_dll; /* CRTDLL.242 */
52 UINT CRTDLL_osmode_dll; /* CRTDLL.243 */
53 UINT CRTDLL_osver_dll; /* CRTDLL.244 */
54 UINT CRTDLL_osversion_dll; /* CRTDLL.245 */
55 UINT CRTDLL_winmajor_dll; /* CRTDLL.329 */
56 UINT CRTDLL_winminor_dll; /* CRTDLL.330 */
57 UINT CRTDLL_winver_dll; /* CRTDLL.331 */
58 INT CRTDLL_doserrno = 0;
60 const INT CRTDLL__sys_nerr = 43;
62 /* ASCII char classification flags - binary compatible */
63 #define _C_ CRTDLL_CONTROL
64 #define _S_ CRTDLL_SPACE
65 #define _P_ CRTDLL_PUNCT
66 #define _D_ CRTDLL_DIGIT
67 #define _H_ CRTDLL_HEX
68 #define _U_ CRTDLL_UPPER
69 #define _L_ CRTDLL_LOWER
71 WORD CRTDLL_ctype [257] = {
72 0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_,
73 _S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_,
74 _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|CRTDLL_BLANK,
75 _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_,
76 _P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_,
77 _D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_,
78 _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_,
79 _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_,
80 _U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_,
81 _L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_,
82 _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_,
83 _C_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
91 /*********************************************************************
92 * CRTDLL_MainInit (CRTDLL.init)
94 BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
96 TRACE("(0x%08x,%ld,%p)\n",hinstDLL,fdwReason,lpvReserved);
98 if (fdwReason == DLL_PROCESS_ATTACH) {
100 CRTDLL_HUGE_dll = HUGE_VAL;
106 /* INTERNAL: Set the crt and dos errno's from the OS error given. */
107 void __CRTDLL__set_errno(ULONG err)
109 /* FIXME: not MT safe */
110 CRTDLL_doserrno = err;
114 #define ERR_CASE(oserr) case oserr:
115 #define ERR_MAPS(oserr,crterr) case oserr:CRTDLL_errno = crterr;break;
116 ERR_CASE(ERROR_ACCESS_DENIED)
117 ERR_CASE(ERROR_NETWORK_ACCESS_DENIED)
118 ERR_CASE(ERROR_CANNOT_MAKE)
119 ERR_CASE(ERROR_SEEK_ON_DEVICE)
120 ERR_CASE(ERROR_LOCK_FAILED)
121 ERR_CASE(ERROR_FAIL_I24)
122 ERR_CASE(ERROR_CURRENT_DIRECTORY)
123 ERR_CASE(ERROR_DRIVE_LOCKED)
124 ERR_CASE(ERROR_NOT_LOCKED)
125 ERR_CASE(ERROR_INVALID_ACCESS)
126 ERR_MAPS(ERROR_LOCK_VIOLATION, EACCES);
127 ERR_CASE(ERROR_FILE_NOT_FOUND)
128 ERR_CASE(ERROR_NO_MORE_FILES)
129 ERR_CASE(ERROR_BAD_PATHNAME)
130 ERR_CASE(ERROR_BAD_NETPATH)
131 ERR_CASE(ERROR_INVALID_DRIVE)
132 ERR_CASE(ERROR_BAD_NET_NAME)
133 ERR_CASE(ERROR_FILENAME_EXCED_RANGE)
134 ERR_MAPS(ERROR_PATH_NOT_FOUND, ENOENT);
135 ERR_MAPS(ERROR_IO_DEVICE, EIO);
136 ERR_MAPS(ERROR_BAD_FORMAT, ENOEXEC);
137 ERR_MAPS(ERROR_INVALID_HANDLE, EBADF);
138 ERR_CASE(ERROR_OUTOFMEMORY)
139 ERR_CASE(ERROR_INVALID_BLOCK)
140 ERR_CASE(ERROR_NOT_ENOUGH_QUOTA);
141 ERR_MAPS(ERROR_ARENA_TRASHED, ENOMEM);
142 ERR_MAPS(ERROR_BUSY, EBUSY);
143 ERR_CASE(ERROR_ALREADY_EXISTS)
144 ERR_MAPS(ERROR_FILE_EXISTS, EEXIST);
145 ERR_MAPS(ERROR_BAD_DEVICE, ENODEV);
146 ERR_MAPS(ERROR_TOO_MANY_OPEN_FILES, EMFILE);
147 ERR_MAPS(ERROR_DISK_FULL, ENOSPC);
148 ERR_MAPS(ERROR_BROKEN_PIPE, EPIPE);
149 ERR_MAPS(ERROR_POSSIBLE_DEADLOCK, EDEADLK);
150 ERR_MAPS(ERROR_DIR_NOT_EMPTY, ENOTEMPTY);
151 ERR_MAPS(ERROR_BAD_ENVIRONMENT, E2BIG);
152 ERR_CASE(ERROR_WAIT_NO_CHILDREN)
153 ERR_MAPS(ERROR_CHILD_NOT_COMPLETE, ECHILD);
154 ERR_CASE(ERROR_NO_PROC_SLOTS)
155 ERR_CASE(ERROR_MAX_THRDS_REACHED)
156 ERR_MAPS(ERROR_NESTING_NOT_ALLOWED, EAGAIN);
158 /* Remaining cases map to EINVAL */
159 /* FIXME: may be missing some errors above */
160 CRTDLL_errno = EINVAL;
164 #if defined(__GNUC__) && defined(__i386__)
165 #define FPU_DOUBLE(var) double var; \
166 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
167 #define FPU_DOUBLES(var1,var2) double var1,var2; \
168 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
169 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
171 #define FPU_DOUBLE(var) double var = quiet_nan(0); \
172 FIXME(":not implemented\n");
173 #define FPU_DOUBLES(var1,var2) double var1,var2; \
174 var1=var2=quiet_nan(0); FIXME(":not implemented\n")
177 /*********************************************************************
178 * _CIacos (CRTDLL.004)
180 double __cdecl CRTDLL__CIacos(void)
183 if (x < -1.0 || x > 1.0) CRTDLL_errno = EDOM;
188 /*********************************************************************
189 * _CIasin (CRTDLL.005)
191 double __cdecl CRTDLL__CIasin(void)
194 if (x < -1.0 || x > 1.0) CRTDLL_errno = EDOM;
199 /*********************************************************************
200 * _CIatan (CRTDLL.006)
202 double __cdecl CRTDLL__CIatan(void)
205 if (!isfinite(x)) CRTDLL_errno = EDOM;
209 /*********************************************************************
210 * _CIatan2 (CRTDLL.007)
212 double __cdecl CRTDLL__CIatan2(void)
215 if (!isfinite(x)) CRTDLL_errno = EDOM;
220 /*********************************************************************
221 * _CIcos (CRTDLL.008)
223 double __cdecl CRTDLL__CIcos(void)
226 if (!isfinite(x)) CRTDLL_errno = EDOM;
230 /*********************************************************************
231 * _CIcosh (CRTDLL.009)
233 double __cdecl CRTDLL__CIcosh(void)
236 if (!isfinite(x)) CRTDLL_errno = EDOM;
240 /*********************************************************************
241 * _CIexp (CRTDLL.010)
243 double __cdecl CRTDLL__CIexp(void)
246 if (!isfinite(x)) CRTDLL_errno = EDOM;
250 /*********************************************************************
251 * _CIfmod (CRTDLL.011)
253 double __cdecl CRTDLL__CIfmod(void)
256 if (!isfinite(x) | !isfinite(y)) CRTDLL_errno = EDOM;
260 /*********************************************************************
261 * _CIlog (CRTDLL.012)
263 double __cdecl CRTDLL__CIlog(void)
266 if (x < 0.0 || !isfinite(x)) CRTDLL_errno = EDOM;
267 if (x == 0.0) CRTDLL_errno = ERANGE;
271 /*********************************************************************
272 * _CIlog10 (CRTDLL.013)
274 double __cdecl CRTDLL__CIlog10(void)
277 if (x < 0.0 || !isfinite(x)) CRTDLL_errno = EDOM;
278 if (x == 0.0) CRTDLL_errno = ERANGE;
282 /*********************************************************************
283 * _CIpow (CRTDLL.014)
285 double __cdecl CRTDLL__CIpow(void)
289 /* FIXME: If x < 0 and y is not integral, set EDOM */
291 if (!isfinite(z)) CRTDLL_errno = EDOM;
295 /*********************************************************************
296 * _CIsin (CRTDLL.015)
298 double __cdecl CRTDLL__CIsin(void)
301 if (!isfinite(x)) CRTDLL_errno = EDOM;
305 /*********************************************************************
306 * _CIsinh (CRTDLL.016)
308 double __cdecl CRTDLL__CIsinh(void)
311 if (!isfinite(x)) CRTDLL_errno = EDOM;
315 /*********************************************************************
316 * _CIsqrt (CRTDLL.017)
318 double __cdecl CRTDLL__CIsqrt(void)
321 if (x < 0.0) CRTDLL_errno = EDOM;
325 /*********************************************************************
326 * _CItan (CRTDLL.018)
328 double __cdecl CRTDLL__CItan(void)
331 if (!isfinite(x)) CRTDLL_errno = EDOM;
335 /*********************************************************************
336 * _CItanh (CRTDLL.019)
338 double __cdecl CRTDLL__CItanh(void)
341 if (!isfinite(x)) CRTDLL_errno = EDOM;
345 /*********************************************************************
346 * _GetMainArgs (CRTDLL.022)
348 LPSTR * __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
349 LPSTR *environ,DWORD flag)
353 int xargc,end,last_arg,afterlastspace;
356 TRACE("(%p,%p,%p,%ld).\n",
357 argc,argv,environ,flag
360 if (CRTDLL_acmdln_dll != NULL)
361 HeapFree(GetProcessHeap(), 0, CRTDLL_acmdln_dll);
363 CRTDLL_acmdln_dll = cmdline = CRTDLL__strdup( GetCommandLineA() );
364 TRACE("got '%s'\n", cmdline);
366 version = GetVersion();
367 CRTDLL_osver_dll = version >> 16;
368 CRTDLL_winminor_dll = version & 0xFF;
369 CRTDLL_winmajor_dll = (version>>8) & 0xFF;
370 CRTDLL_baseversion_dll = version >> 16;
371 CRTDLL_winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
372 CRTDLL_baseminor_dll = (version >> 16) & 0xFF;
373 CRTDLL_basemajor_dll = (version >> 24) & 0xFF;
374 CRTDLL_osversion_dll = version & 0xFFFF;
375 CRTDLL_osminor_dll = version & 0xFF;
376 CRTDLL_osmajor_dll = (version>>8) & 0xFF;
378 /* missing threading init */
380 end=0;last_arg=0;xargv=NULL;xargc=0;afterlastspace=0;
383 if ((cmdline[end]==' ') || (cmdline[end]=='\0'))
385 if (cmdline[end]=='\0')
389 /* alloc xargc + NULL entry */
390 xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
391 sizeof(char*)*(xargc+1));
392 if (strlen(cmdline+afterlastspace))
394 xargv[xargc] = CRTDLL__strdup(cmdline+afterlastspace);
396 if (!last_arg) /* need to seek to the next arg ? */
399 while (cmdline[end]==' ')
406 xargv[xargc] = NULL; /* the last entry is NULL */
413 CRTDLL_argc_dll = xargc;
415 CRTDLL_argv_dll = xargv;
418 TRACE("found %d arguments\n",
420 CRTDLL_environ_dll = *environ = GetEnvironmentStringsA();
426 /*********************************************************************
427 * _clearfp (CRTDLL.056)
429 * Clear and return the previous FP status.
431 UINT __cdecl CRTDLL__clearfp( VOID )
433 UINT retVal = CRTDLL__statusfp();
434 #if defined(__GNUC__) && defined(__i386__)
435 __asm__ __volatile__( "fnclex" );
437 FIXME(":Not Implemented!\n");
442 /*********************************************************************
443 * _fpclass (CRTDLL.105)
445 * Return the FP classification of d.
447 INT __cdecl CRTDLL__fpclass(double d)
449 switch (fpclassify( d ))
451 case FP_NAN: return _FPCLASS_QNAN;
454 return _FPCLASS_NINF;
455 return _FPCLASS_PINF;
473 /*********************************************************************
474 * _initterm (CRTDLL.135)
476 DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
478 _INITTERMFUN *current;
480 TRACE("(%p,%p)\n",start,end);
482 while (current<end) {
483 if (*current) (*current)();
490 /*******************************************************************
491 * _global_unwind2 (CRTDLL.129)
493 void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
495 RtlUnwind( frame, 0, NULL, 0 );
499 /*******************************************************************
500 * _local_unwind2 (CRTDLL.173)
502 void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
504 TRACE("(%p,%ld)\n",endframe,nr);
508 /*******************************************************************
509 * _setjmp (CRTDLL.264)
511 INT __cdecl CRTDLL__setjmp(LPDWORD *jmpbuf)
513 FIXME(":(%p): stub\n",jmpbuf);
518 /*********************************************************************
521 * Output a tone using the PC speaker.
524 * freq [in] Frequency of the tone
526 * duration [in] Length of time the tone should sound
531 void __cdecl CRTDLL__beep( UINT freq, UINT duration)
533 TRACE(":Freq %d, Duration %d\n",freq,duration);
534 Beep(freq, duration);
538 /*********************************************************************
541 INT __cdecl CRTDLL_rand()
543 return (rand() & CRTDLL_RAND_MAX);
547 /*********************************************************************
550 UINT __cdecl CRTDLL__rotl(UINT x,INT shift)
553 return (x << shift) | (x >> (32-shift));
557 /*********************************************************************
558 * _lrotl (CRTDLL.175)
560 DWORD __cdecl CRTDLL__lrotl(DWORD x,INT shift)
563 return (x << shift) | (x >> (32-shift));
567 /*********************************************************************
568 * _lrotr (CRTDLL.176)
570 DWORD __cdecl CRTDLL__lrotr(DWORD x,INT shift)
573 return (x >> shift) | (x << (32-shift));
577 /*********************************************************************
580 DWORD __cdecl CRTDLL__rotr(UINT x,INT shift)
583 return (x >> shift) | (x << (32-shift));
587 /*********************************************************************
588 * _scalb (CRTDLL.259)
592 double __cdecl CRTDLL__scalb(double x, LONG y)
594 /* Note - Can't forward directly as libc expects y as double */
595 double y2 = (double)y;
596 return scalb( x, y2 );
600 /*********************************************************************
601 * longjmp (CRTDLL.426)
603 VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
605 FIXME("CRTDLL_longjmp semistup, expect crash\n");
610 /*********************************************************************
611 * setlocale (CRTDLL.453)
613 LPSTR __cdecl CRTDLL_setlocale(INT category,LPCSTR locale)
618 case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
619 case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
620 case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
621 case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
622 case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
623 case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
624 default: categorystr = "UNKNOWN?";break;
626 FIXME("(%s,%s),stub!\n",categorystr,locale);
631 /*********************************************************************
632 * _isctype (CRTDLL.138)
634 INT __cdecl CRTDLL__isctype(INT c,UINT type)
636 return CRTDLL_ctype[(UINT)c+1] & type;
640 /*********************************************************************
641 * _fullpath (CRTDLL.114)
643 LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT size)
648 if(!(buf = CRTDLL_malloc(size))) return NULL;
650 if (!GetFullPathNameA( name, size, buf, NULL )) return NULL;
651 TRACE("CRTDLL_fullpath got %s\n",buf);
656 /*********************************************************************
657 * _splitpath (CRTDLL.279)
659 VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
662 directory includes leading and trailing (forward and backward slashes)
663 filename without dot and slashes
664 extension with leading dot
666 char * drivechar,*dirchar,*namechar;
668 TRACE("CRTDLL__splitpath got %s\n",path);
670 drivechar = strchr(path,':');
671 dirchar = strrchr(path,'/');
672 namechar = strrchr(path,'\\');
673 dirchar = max(dirchar,namechar);
675 namechar = strrchr(dirchar,'.');
677 namechar = strrchr(path,'.');
684 strncat(drive,path,drivechar-path+1);
693 strncat(directory,path,dirchar-path+1);
702 strncat(filename,path,namechar-path);
706 strcat(extension,namechar);
711 TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
715 /*********************************************************************
716 * _matherr (CRTDLL.181)
718 * Default handler for math errors.
720 INT __cdecl CRTDLL__matherr(struct _exception *e)
722 /* FIXME: Supposedly this can be user overridden, but
723 * currently it will never be called anyway.
725 FIXME(":Unhandled math error!\n");
726 return e == NULL ? 0 : 0;
730 /*********************************************************************
731 * _makepath (CRTDLL.182)
734 VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive,
735 LPCSTR directory, LPCSTR filename,
739 TRACE("CRTDLL__makepath got %s %s %s %s\n", drive, directory,
740 filename, extension);
746 if (drive && drive[0])
752 if (directory && directory[0])
754 strcat(path, directory);
755 ch = path[strlen(path)-1];
756 if (ch != '/' && ch != '\\')
759 if (filename && filename[0])
761 strcat(path, filename);
762 if (extension && extension[0])
764 if ( extension[0] != '.' ) {
767 strcat(path,extension);
771 TRACE("CRTDLL__makepath returns %s\n",path);
775 /*********************************************************************
777 * Return the address of the CRT errno (Not the libc errno).
782 LPINT __cdecl CRTDLL__errno( VOID )
784 return &CRTDLL_errno;
788 /*********************************************************************
789 * __doserrno (CRTDLL.26)
791 * Return the address of the DOS errno (holding the last OS error).
796 LPINT __cdecl CRTDLL___doserrno( VOID )
798 return &CRTDLL_doserrno;
801 /**********************************************************************
802 * _statusfp (CRTDLL.279)
804 * Return the status of the FP control word.
806 UINT __cdecl CRTDLL__statusfp( VOID )
809 #if defined(__GNUC__) && defined(__i386__)
812 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
813 if (fpword & 0x1) retVal |= _SW_INVALID;
814 if (fpword & 0x2) retVal |= _SW_DENORMAL;
815 if (fpword & 0x4) retVal |= _SW_ZERODIVIDE;
816 if (fpword & 0x8) retVal |= _SW_OVERFLOW;
817 if (fpword & 0x10) retVal |= _SW_UNDERFLOW;
818 if (fpword & 0x20) retVal |= _SW_INEXACT;
820 FIXME(":Not implemented!\n");
826 /**********************************************************************
827 * _strerror (CRTDLL.284)
829 * Return a formatted system error message.
832 * The caller does not own the string returned.
834 extern int sprintf(char *str, const char *format, ...);
836 LPSTR __cdecl CRTDLL__strerror (LPCSTR err)
838 static char strerrbuff[256];
839 sprintf(strerrbuff,"%s: %s\n",err,CRTDLL_strerror(CRTDLL_errno));
844 /*********************************************************************
845 * perror (CRTDLL.435)
847 * Print a formatted system error message to stderr.
849 VOID __cdecl CRTDLL_perror (LPCSTR err)
851 char *err_str = CRTDLL_strerror(CRTDLL_errno);
852 CRTDLL_fprintf(CRTDLL_stderr,"%s: %s\n",err,err_str);
853 CRTDLL_free(err_str);
857 /*********************************************************************
858 * strerror (CRTDLL.465)
860 * Return the text of an error.
863 * The caller does not own the string returned.
865 extern char *strerror(int errnum);
867 LPSTR __cdecl CRTDLL_strerror (INT err)
869 return strerror(err);
873 /*********************************************************************
874 * signal (CRTDLL.455)
876 LPVOID __cdecl CRTDLL_signal(INT sig, sig_handler_type ptr)
878 FIXME("(%d %p):stub.\n", sig, ptr);
883 /*********************************************************************
884 * _sleep (CRTDLL.267)
886 VOID __cdecl CRTDLL__sleep(ULONG timeout)
888 TRACE("CRTDLL__sleep for %ld milliseconds\n",timeout);
889 Sleep((timeout)?timeout:1);
893 /*********************************************************************
894 * getenv (CRTDLL.437)
896 LPSTR __cdecl CRTDLL_getenv(LPCSTR name)
898 LPSTR environ = GetEnvironmentStringsA();
902 for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
909 if (!strncmp(pp,name,length)) break;
914 TRACE("got %s\n",pp);
916 FreeEnvironmentStringsA( environ );
921 /*********************************************************************
922 * isalnum (CRTDLL.442)
924 INT __cdecl CRTDLL_isalnum(INT c)
926 return CRTDLL__isctype( c,CRTDLL_ALPHA | CRTDLL_DIGIT );
930 /*********************************************************************
931 * isalpha (CRTDLL.443)
933 INT __cdecl CRTDLL_isalpha(INT c)
935 return CRTDLL__isctype( c, CRTDLL_ALPHA );
939 /*********************************************************************
940 * iscntrl (CRTDLL.444)
942 INT __cdecl CRTDLL_iscntrl(INT c)
944 return CRTDLL__isctype( c, CRTDLL_CONTROL );
948 /*********************************************************************
949 * isdigit (CRTDLL.445)
951 INT __cdecl CRTDLL_isdigit(INT c)
953 return CRTDLL__isctype( c, CRTDLL_DIGIT );
957 /*********************************************************************
958 * isgraph (CRTDLL.446)
960 INT __cdecl CRTDLL_isgraph(INT c)
962 return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT | CRTDLL_PUNCT );
966 /*********************************************************************
967 * islower (CRTDLL.447)
969 INT __cdecl CRTDLL_islower(INT c)
971 return CRTDLL__isctype( c, CRTDLL_LOWER );
975 /*********************************************************************
976 * isprint (CRTDLL.448)
978 INT __cdecl CRTDLL_isprint(INT c)
980 return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT |
981 CRTDLL_BLANK | CRTDLL_PUNCT );
985 /*********************************************************************
986 * ispunct (CRTDLL.449)
988 INT __cdecl CRTDLL_ispunct(INT c)
990 return CRTDLL__isctype( c, CRTDLL_PUNCT );
994 /*********************************************************************
995 * isspace (CRTDLL.450)
997 INT __cdecl CRTDLL_isspace(INT c)
999 return CRTDLL__isctype( c, CRTDLL_SPACE );
1003 /*********************************************************************
1004 * isupper (CRTDLL.451)
1006 INT __cdecl CRTDLL_isupper(INT c)
1008 return CRTDLL__isctype( c, CRTDLL_UPPER );
1012 /*********************************************************************
1013 * isxdigit (CRTDLL.452)
1015 INT __cdecl CRTDLL_isxdigit(INT c)
1017 return CRTDLL__isctype( c, CRTDLL_HEX );
1021 /*********************************************************************
1022 * ldexp (CRTDLL.454)
1024 double __cdecl CRTDLL_ldexp(double x, LONG y)
1028 /* FIXME: MS doesn't return -0 or very large/small (e=298+) numbers */
1029 if (!isfinite(z)) CRTDLL_errno = ERANGE;
1033 /*********************************************************************
1034 * _except_handler2 (CRTDLL.78)
1036 INT __cdecl CRTDLL__except_handler2 (
1037 PEXCEPTION_RECORD rec,
1038 PEXCEPTION_FRAME frame,
1040 PEXCEPTION_FRAME *dispatcher)
1042 FIXME ("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
1043 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
1044 frame->Handler, context, dispatcher);
1045 return ExceptionContinueSearch;
1049 /*********************************************************************
1050 * __isascii (CRTDLL.028)
1053 INT __cdecl CRTDLL___isascii(INT c)
1055 return isascii((unsigned)c);
1059 /*********************************************************************
1060 * __toascii (CRTDLL.035)
1063 INT __cdecl CRTDLL___toascii(INT c)
1065 return (unsigned)c & 0x7f;
1069 /*********************************************************************
1070 * iswascii (CRTDLL.404)
1073 INT __cdecl CRTDLL_iswascii(LONG c)
1075 return ((unsigned)c < 0x80);
1079 /*********************************************************************
1080 * __iscsym (CRTDLL.029)
1082 * Is a character valid in a C identifier (a-Z,0-9,_).
1085 * c [I]: Character to check
1088 * Non zero if c is valid as t a C identifier.
1090 INT __cdecl CRTDLL___iscsym(UCHAR c)
1092 return (c < 127 && (isalnum(c) || c == '_'));
1096 /*********************************************************************
1097 * __iscsymf (CRTDLL.030)
1099 * Is a character valid as the first letter in a C identifier (a-Z,_).
1102 * c [in] Character to check
1105 * Non zero if c is valid as the first letter in a C identifier.
1107 INT __cdecl CRTDLL___iscsymf(UCHAR c)
1109 return (c < 127 && (isalpha(c) || c == '_'));
1113 /*********************************************************************
1114 * _lfind (CRTDLL.170)
1116 * Perform a linear search of an array for an element.
1118 LPVOID __cdecl CRTDLL__lfind(LPCVOID match, LPCVOID start, LPUINT array_size,
1119 UINT elem_size, comp_func cf)
1121 UINT size = *array_size;
1125 if (cf(match, start) == 0)
1126 return (LPVOID)start; /* found */
1133 /*********************************************************************
1134 * _loaddll (CRTDLL.171)
1136 * Get a handle to a DLL in memory. The DLL is loaded if it is not already.
1139 * dll [in] Name of DLL to load.
1142 * Success: A handle to the loaded DLL.
1146 INT __cdecl CRTDLL__loaddll(LPSTR dllname)
1148 return LoadLibraryA(dllname);
1152 /*********************************************************************
1153 * _unloaddll (CRTDLL.313)
1155 * Free reference to a DLL handle from loaddll().
1158 * dll [in] Handle to free.
1163 * Failure: Error number.
1165 INT __cdecl CRTDLL__unloaddll(HANDLE dll)
1168 if (FreeLibrary(dll))
1170 err = GetLastError();
1171 __CRTDLL__set_errno(err);
1176 /*********************************************************************
1177 * _lsearch (CRTDLL.177)
1179 * Linear search of an array of elements. Adds the item to the array if
1183 * match [in] Pointer to element to match
1184 * start [in] Pointer to start of search memory
1185 * array_size [in] Length of search array (element count)
1186 * elem_size [in] Size of each element in memory
1187 * cf [in] Pointer to comparison function (like qsort()).
1190 * Pointer to the location where element was found or added.
1192 LPVOID __cdecl CRTDLL__lsearch(LPVOID match,LPVOID start, LPUINT array_size,
1193 UINT elem_size, comp_func cf)
1195 UINT size = *array_size;
1199 if (cf(match, start) == 0)
1200 return start; /* found */
1204 /* not found, add to end */
1205 memcpy(start, match, elem_size);
1211 /*********************************************************************
1212 * _itow (CRTDLL.164)
1214 * Convert an integer to a wide char string.
1216 extern LPSTR __cdecl _itoa( long , LPSTR , INT); /* ntdll */
1218 WCHAR* __cdecl CRTDLL__itow(INT value,WCHAR* out,INT base)
1220 char buff[64]; /* FIXME: Whats the maximum buffer size for INT_MAX? */
1222 _itoa(value, buff, base);
1223 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1228 /*********************************************************************
1231 * Convert a long to a wide char string.
1233 extern LPSTR __cdecl _ltoa( long , LPSTR , INT); /* ntdll */
1235 WCHAR* __cdecl CRTDLL__ltow(LONG value,WCHAR* out,INT base)
1237 char buff[64]; /* FIXME: Whats the maximum buffer size for LONG_MAX? */
1239 _ltoa(value, buff, base);
1240 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1245 /*********************************************************************
1246 * _ultow (CRTDLL.??)
1248 * Convert an unsigned long to a wide char string.
1250 extern LPSTR __cdecl _ultoa( long , LPSTR , INT); /* ntdll */
1252 WCHAR* __cdecl CRTDLL__ultow(ULONG value,WCHAR* out,INT base)
1254 char buff[64]; /* FIXME: Whats the maximum buffer size for ULONG_MAX? */
1256 _ultoa(value, buff, base);
1257 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1262 /*********************************************************************
1263 * _toupper (CRTDLL.489)
1265 CHAR __cdecl CRTDLL__toupper(CHAR c)
1271 /*********************************************************************
1272 * _tolower (CRTDLL.490)
1274 CHAR __cdecl CRTDLL__tolower(CHAR c)
1282 /*********************************************************************
1283 * _cabs (CRTDLL.048)
1285 * Return the absolue value of a complex number.
1288 * c [in] Structure containing real and imaginary parts of complex number.
1291 * Absolute value of complex number (always a positive real number).
1293 double __cdecl CRTDLL__cabs(struct complex c)
1295 return sqrt(c.real * c.real + c.imaginary * c.imaginary);
1299 /*********************************************************************
1300 * _chgsign (CRTDLL.053)
1302 * Change the sign of an IEEE double.
1305 * d [in] Number to invert.
1308 * Number with sign inverted.
1310 double __cdecl CRTDLL__chgsign(double d)
1312 /* FIXME: +-infinity,Nan not tested */
1317 /*********************************************************************
1318 * _control87 (CRTDLL.060)
1320 * X86 implementation of _controlfp.
1323 UINT __cdecl CRTDLL__control87(UINT newVal, UINT mask)
1325 #if defined(__GNUC__) && defined(__i386__)
1326 UINT fpword, flags = 0;
1328 /* Get fp control word */
1329 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
1331 /* Convert into mask constants */
1332 if (fpword & 0x1) flags |= _EM_INVALID;
1333 if (fpword & 0x2) flags |= _EM_DENORMAL;
1334 if (fpword & 0x4) flags |= _EM_ZERODIVIDE;
1335 if (fpword & 0x8) flags |= _EM_OVERFLOW;
1336 if (fpword & 0x10) flags |= _EM_UNDERFLOW;
1337 if (fpword & 0x20) flags |= _EM_INEXACT;
1338 switch(fpword & 0xC00) {
1339 case 0xC00: flags |= _RC_UP|_RC_DOWN; break;
1340 case 0x800: flags |= _RC_UP; break;
1341 case 0x400: flags |= _RC_DOWN; break;
1343 switch(fpword & 0x300) {
1344 case 0x0: flags |= _PC_24; break;
1345 case 0x200: flags |= _PC_53; break;
1346 case 0x300: flags |= _PC_64; break;
1348 if (fpword & 0x1000) flags |= _IC_AFFINE;
1350 /* Mask with parameters */
1351 flags = (flags & ~mask) | (newVal & mask);
1353 /* Convert (masked) value back to fp word */
1355 if (flags & _EM_INVALID) fpword |= 0x1;
1356 if (flags & _EM_DENORMAL) fpword |= 0x2;
1357 if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
1358 if (flags & _EM_OVERFLOW) fpword |= 0x8;
1359 if (flags & _EM_UNDERFLOW) fpword |= 0x10;
1360 if (flags & _EM_INEXACT) fpword |= 0x20;
1361 switch(flags & (_RC_UP | _RC_DOWN)) {
1362 case _RC_UP|_RC_DOWN: fpword |= 0xC00; break;
1363 case _RC_UP: fpword |= 0x800; break;
1364 case _RC_DOWN: fpword |= 0x400; break;
1366 switch (flags & (_PC_24 | _PC_53)) {
1367 case _PC_64: fpword |= 0x300; break;
1368 case _PC_53: fpword |= 0x200; break;
1369 case _PC_24: fpword |= 0x0; break;
1371 if (!(flags & _IC_AFFINE)) fpword |= 0x1000;
1373 /* Put fp control word */
1374 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1377 return CRTDLL__controlfp( newVal, mask );
1382 /*********************************************************************
1383 * _controlfp (CRTDLL.061)
1385 * Set the state of the floating point unit.
1387 UINT __cdecl CRTDLL__controlfp( UINT newVal, UINT mask)
1389 #if defined(__GNUC__) && defined(__i386__)
1390 return CRTDLL__control87( newVal, mask );
1392 FIXME(":Not Implemented!\n");
1398 /*********************************************************************
1399 * _copysign (CRTDLL.062)
1401 * Return the number x with the sign of y.
1403 double __cdecl CRTDLL__copysign(double x, double y)
1405 /* FIXME: Behaviour for Nan/Inf etc? */
1407 return x < 0.0 ? x : -x;
1409 return x < 0.0 ? -x : x;
1413 /*********************************************************************
1414 * _finite (CRTDLL.101)
1416 * Determine if an IEEE double is finite (i.e. not +/- Infinity).
1419 * d [in] Number to check.
1422 * Non zero if number is finite.
1424 INT __cdecl CRTDLL__finite(double d)
1426 return (isfinite(d)?1:0); /* See comment for CRTDLL__isnan() */
1430 /*********************************************************************
1431 * _fpreset (CRTDLL.107)
1433 * Reset the state of the floating point processor.
1435 VOID __cdecl CRTDLL__fpreset(void)
1437 #if defined(__GNUC__) && defined(__i386__)
1438 __asm__ __volatile__( "fninit" );
1440 FIXME(":Not Implemented!\n");
1445 /*********************************************************************
1446 * _isnan (CRTDLL.164)
1448 * Determine if an IEEE double is unrepresentable (NaN).
1451 * d [in] Number to check.
1454 * Non zero if number is NaN.
1456 INT __cdecl CRTDLL__isnan(double d)
1458 /* some implementations return -1 for true(glibc), crtdll returns 1.
1459 * Do the same, as the result may be used in calculations.
1461 return isnan(d)?1:0;
1465 /*********************************************************************
1466 * _purecall (CRTDLL.249)
1468 * Abort program after pure virtual function call.
1470 VOID __cdecl CRTDLL__purecall(VOID)
1472 CRTDLL__amsg_exit( 6025 );
1476 /*********************************************************************
1479 * Return the quotient and remainder of long integer division.
1482 /* Windows binary compatible - returns the struct in eax/edx. */
1483 LONGLONG __cdecl CRTDLL_div(int x, int y)
1486 div_t dt = div(x,y);
1487 retVal = ((LONGLONG)dt.rem << 32) | dt.quot;
1491 /* Non-x86 cant run win32 apps so dont need binary compatibility */
1492 div_t __cdecl CRTDLL_div(int x, int y)
1496 #endif /* __i386__ */
1499 /*********************************************************************
1500 * _ldiv (CRTDLL.249)
1502 * Return the quotient and remainder of long integer division.
1505 /* Windows binary compatible - returns the struct in eax/edx. */
1506 LONGLONG __cdecl CRTDLL_ldiv(long x, long y)
1509 ldiv_t ldt = ldiv(x,y);
1510 retVal = ((LONGLONG)ldt.rem << 32) | ldt.quot;
1514 /* Non-x86 cant run win32 apps so dont need binary compatibility */
1515 ldiv_t __cdecl CRTDLL_ldiv(long x, long y)
1519 #endif /* __i386__ */