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
30 #define __USE_ISOC9X 1
31 #define __USE_ISOC99 1
40 #ifndef finite /* Could be macro */
42 #define finite(x) isfinite(x)
44 #define finite(x) (!isnan(x)) /* At least catch some cases */
53 DEFAULT_DEBUG_CHANNEL(crtdll);
55 double CRTDLL_HUGE_dll; /* CRTDLL.20 */
56 UINT CRTDLL_argc_dll; /* CRTDLL.23 */
57 LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
58 LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
59 UINT CRTDLL_basemajor_dll; /* CRTDLL.42 */
60 UINT CRTDLL_baseminor_dll; /* CRTDLL.43 */
61 UINT CRTDLL_baseversion_dll; /* CRTDLL.44 */
62 UINT CRTDLL_commode_dll; /* CRTDLL.59 */
63 LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
64 UINT CRTDLL_fmode_dll; /* CRTDLL.104 */
65 UINT CRTDLL_osmajor_dll; /* CRTDLL.241 */
66 UINT CRTDLL_osminor_dll; /* CRTDLL.242 */
67 UINT CRTDLL_osmode_dll; /* CRTDLL.243 */
68 UINT CRTDLL_osver_dll; /* CRTDLL.244 */
69 UINT CRTDLL_osversion_dll; /* CRTDLL.245 */
70 UINT CRTDLL_winmajor_dll; /* CRTDLL.329 */
71 UINT CRTDLL_winminor_dll; /* CRTDLL.330 */
72 UINT CRTDLL_winver_dll; /* CRTDLL.331 */
73 INT CRTDLL_doserrno = 0;
75 const INT CRTDLL__sys_nerr = 43;
77 /* ASCII char classification flags - binary compatible */
78 #define _C_ CRTDLL_CONTROL
79 #define _S_ CRTDLL_SPACE
80 #define _P_ CRTDLL_PUNCT
81 #define _D_ CRTDLL_DIGIT
82 #define _H_ CRTDLL_HEX
83 #define _U_ CRTDLL_UPPER
84 #define _L_ CRTDLL_LOWER
86 WORD CRTDLL_ctype [257] = {
87 0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_,
88 _S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_,
89 _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|CRTDLL_BLANK,
90 _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_,
91 _P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_,
92 _D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_,
93 _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_,
94 _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_,
95 _U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_,
96 _L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_,
97 _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_,
98 _C_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106 /*********************************************************************
107 * CRTDLL_MainInit (CRTDLL.init)
109 BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
111 TRACE("(0x%08x,%ld,%p)\n",hinstDLL,fdwReason,lpvReserved);
113 if (fdwReason == DLL_PROCESS_ATTACH) {
115 CRTDLL_HUGE_dll = HUGE_VAL;
121 /* INTERNAL: Set the crt and dos errno's from the OS error given. */
122 void __CRTDLL__set_errno(ULONG err)
124 /* FIXME: not MT safe */
125 CRTDLL_doserrno = err;
129 #define ERR_CASE(oserr) case oserr:
130 #define ERR_MAPS(oserr,crterr) case oserr:CRTDLL_errno = crterr;break;
131 ERR_CASE(ERROR_ACCESS_DENIED)
132 ERR_CASE(ERROR_NETWORK_ACCESS_DENIED)
133 ERR_CASE(ERROR_CANNOT_MAKE)
134 ERR_CASE(ERROR_SEEK_ON_DEVICE)
135 ERR_CASE(ERROR_LOCK_FAILED)
136 ERR_CASE(ERROR_FAIL_I24)
137 ERR_CASE(ERROR_CURRENT_DIRECTORY)
138 ERR_CASE(ERROR_DRIVE_LOCKED)
139 ERR_CASE(ERROR_NOT_LOCKED)
140 ERR_CASE(ERROR_INVALID_ACCESS)
141 ERR_MAPS(ERROR_LOCK_VIOLATION, EACCES);
142 ERR_CASE(ERROR_FILE_NOT_FOUND)
143 ERR_CASE(ERROR_NO_MORE_FILES)
144 ERR_CASE(ERROR_BAD_PATHNAME)
145 ERR_CASE(ERROR_BAD_NETPATH)
146 ERR_CASE(ERROR_INVALID_DRIVE)
147 ERR_CASE(ERROR_BAD_NET_NAME)
148 ERR_CASE(ERROR_FILENAME_EXCED_RANGE)
149 ERR_MAPS(ERROR_PATH_NOT_FOUND, ENOENT);
150 ERR_MAPS(ERROR_IO_DEVICE, EIO);
151 ERR_MAPS(ERROR_BAD_FORMAT, ENOEXEC);
152 ERR_MAPS(ERROR_INVALID_HANDLE, EBADF);
153 ERR_CASE(ERROR_OUTOFMEMORY)
154 ERR_CASE(ERROR_INVALID_BLOCK)
155 ERR_CASE(ERROR_NOT_ENOUGH_QUOTA);
156 ERR_MAPS(ERROR_ARENA_TRASHED, ENOMEM);
157 ERR_MAPS(ERROR_BUSY, EBUSY);
158 ERR_CASE(ERROR_ALREADY_EXISTS)
159 ERR_MAPS(ERROR_FILE_EXISTS, EEXIST);
160 ERR_MAPS(ERROR_BAD_DEVICE, ENODEV);
161 ERR_MAPS(ERROR_TOO_MANY_OPEN_FILES, EMFILE);
162 ERR_MAPS(ERROR_DISK_FULL, ENOSPC);
163 ERR_MAPS(ERROR_BROKEN_PIPE, EPIPE);
164 ERR_MAPS(ERROR_POSSIBLE_DEADLOCK, EDEADLK);
165 ERR_MAPS(ERROR_DIR_NOT_EMPTY, ENOTEMPTY);
166 ERR_MAPS(ERROR_BAD_ENVIRONMENT, E2BIG);
167 ERR_CASE(ERROR_WAIT_NO_CHILDREN)
168 ERR_MAPS(ERROR_CHILD_NOT_COMPLETE, ECHILD);
169 ERR_CASE(ERROR_NO_PROC_SLOTS)
170 ERR_CASE(ERROR_MAX_THRDS_REACHED)
171 ERR_MAPS(ERROR_NESTING_NOT_ALLOWED, EAGAIN);
173 /* Remaining cases map to EINVAL */
174 /* FIXME: may be missing some errors above */
175 CRTDLL_errno = EINVAL;
179 #if defined(__GNUC__) && defined(__i386__)
180 #define FPU_DOUBLE(var) double var; \
181 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
182 #define FPU_DOUBLES(var1,var2) double var1,var2; \
183 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
184 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
186 #define FPU_DOUBLE(var) double var = sqrt(-1); \
187 FIXME(":not implemented\n");
188 #define FPU_DOUBLES(var1,var2) double var1,var2; \
189 var1=var2=sqrt(-1); FIXME(":not implemented\n")
192 /*********************************************************************
193 * _CIacos (CRTDLL.004)
195 double __cdecl CRTDLL__CIacos(void)
198 if (x < -1.0 || x > 1.0 || !finite(x)) CRTDLL_errno = EDOM;
203 /*********************************************************************
204 * _CIasin (CRTDLL.005)
206 double __cdecl CRTDLL__CIasin(void)
209 if (x < -1.0 || x > 1.0 || !finite(x)) CRTDLL_errno = EDOM;
214 /*********************************************************************
215 * _CIatan (CRTDLL.006)
217 double __cdecl CRTDLL__CIatan(void)
220 if (!finite(x)) CRTDLL_errno = EDOM;
224 /*********************************************************************
225 * _CIatan2 (CRTDLL.007)
227 double __cdecl CRTDLL__CIatan2(void)
230 if (!finite(x)) CRTDLL_errno = EDOM;
235 /*********************************************************************
236 * _CIcos (CRTDLL.008)
238 double __cdecl CRTDLL__CIcos(void)
241 if (!finite(x)) CRTDLL_errno = EDOM;
245 /*********************************************************************
246 * _CIcosh (CRTDLL.009)
248 double __cdecl CRTDLL__CIcosh(void)
251 if (!finite(x)) CRTDLL_errno = EDOM;
255 /*********************************************************************
256 * _CIexp (CRTDLL.010)
258 double __cdecl CRTDLL__CIexp(void)
261 if (!finite(x)) CRTDLL_errno = EDOM;
265 /*********************************************************************
266 * _CIfmod (CRTDLL.011)
268 double __cdecl CRTDLL__CIfmod(void)
271 if (!finite(x) || !finite(y)) CRTDLL_errno = EDOM;
275 /*********************************************************************
276 * _CIlog (CRTDLL.012)
278 double __cdecl CRTDLL__CIlog(void)
281 if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
282 if (x == 0.0) CRTDLL_errno = ERANGE;
286 /*********************************************************************
287 * _CIlog10 (CRTDLL.013)
289 double __cdecl CRTDLL__CIlog10(void)
292 if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
293 if (x == 0.0) CRTDLL_errno = ERANGE;
297 /*********************************************************************
298 * _CIpow (CRTDLL.014)
300 double __cdecl CRTDLL__CIpow(void)
304 /* FIXME: If x < 0 and y is not integral, set EDOM */
306 if (!finite(z)) CRTDLL_errno = EDOM;
310 /*********************************************************************
311 * _CIsin (CRTDLL.015)
313 double __cdecl CRTDLL__CIsin(void)
316 if (!finite(x)) CRTDLL_errno = EDOM;
320 /*********************************************************************
321 * _CIsinh (CRTDLL.016)
323 double __cdecl CRTDLL__CIsinh(void)
326 if (!finite(x)) CRTDLL_errno = EDOM;
330 /*********************************************************************
331 * _CIsqrt (CRTDLL.017)
333 double __cdecl CRTDLL__CIsqrt(void)
336 if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
340 /*********************************************************************
341 * _CItan (CRTDLL.018)
343 double __cdecl CRTDLL__CItan(void)
346 if (!finite(x)) CRTDLL_errno = EDOM;
350 /*********************************************************************
351 * _CItanh (CRTDLL.019)
353 double __cdecl CRTDLL__CItanh(void)
356 if (!finite(x)) CRTDLL_errno = EDOM;
360 /*********************************************************************
361 * _GetMainArgs (CRTDLL.022)
363 LPSTR * __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
364 LPSTR *environ,DWORD flag)
368 int xargc,end,last_arg,afterlastspace;
371 TRACE("(%p,%p,%p,%ld).\n",
372 argc,argv,environ,flag
375 if (CRTDLL_acmdln_dll != NULL)
376 HeapFree(GetProcessHeap(), 0, CRTDLL_acmdln_dll);
378 CRTDLL_acmdln_dll = cmdline = CRTDLL__strdup( GetCommandLineA() );
379 TRACE("got '%s'\n", cmdline);
381 version = GetVersion();
382 CRTDLL_osver_dll = version >> 16;
383 CRTDLL_winminor_dll = version & 0xFF;
384 CRTDLL_winmajor_dll = (version>>8) & 0xFF;
385 CRTDLL_baseversion_dll = version >> 16;
386 CRTDLL_winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
387 CRTDLL_baseminor_dll = (version >> 16) & 0xFF;
388 CRTDLL_basemajor_dll = (version >> 24) & 0xFF;
389 CRTDLL_osversion_dll = version & 0xFFFF;
390 CRTDLL_osminor_dll = version & 0xFF;
391 CRTDLL_osmajor_dll = (version>>8) & 0xFF;
393 /* missing threading init */
395 end=0;last_arg=0;xargv=NULL;xargc=0;afterlastspace=0;
398 if ((cmdline[end]==' ') || (cmdline[end]=='\0'))
400 if (cmdline[end]=='\0')
404 /* alloc xargc + NULL entry */
405 xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
406 sizeof(char*)*(xargc+1));
407 if (strlen(cmdline+afterlastspace))
409 xargv[xargc] = CRTDLL__strdup(cmdline+afterlastspace);
411 if (!last_arg) /* need to seek to the next arg ? */
414 while (cmdline[end]==' ')
421 xargv[xargc] = NULL; /* the last entry is NULL */
428 CRTDLL_argc_dll = xargc;
430 CRTDLL_argv_dll = xargv;
433 TRACE("found %d arguments\n",
435 CRTDLL_environ_dll = *environ = GetEnvironmentStringsA();
441 /*********************************************************************
442 * _clearfp (CRTDLL.056)
444 * Clear and return the previous FP status.
446 UINT __cdecl CRTDLL__clearfp( VOID )
448 UINT retVal = CRTDLL__statusfp();
449 #if defined(__GNUC__) && defined(__i386__)
450 __asm__ __volatile__( "fnclex" );
452 FIXME(":Not Implemented!\n");
457 /*********************************************************************
458 * _fpclass (CRTDLL.105)
460 * Return the FP classification of d.
462 INT __cdecl CRTDLL__fpclass(double d)
464 #if defined(HAVE_FPCLASS) || defined(fpclass)
465 switch (fpclass( d ))
467 case FP_SNAN: return _FPCLASS_SNAN;
468 case FP_QNAN: return _FPCLASS_QNAN;
469 case FP_NINF: return _FPCLASS_NINF;
470 case FP_PINF: return _FPCLASS_PINF;
471 case FP_NDENORM: return _FPCLASS_ND;
472 case FP_PDENORM: return _FPCLASS_PD;
473 case FP_NZERO: return _FPCLASS_NZ;
474 case FP_PZERO: return _FPCLASS_PZ;
475 case FP_NNORM: return _FPCLASS_NN;
478 #elif defined (fpclassify)
479 switch (fpclassify( d ))
481 case FP_NAN: return _FPCLASS_QNAN;
482 case FP_INFINITE: return signbit(d) ? _FPCLASS_NINF : _FPCLASS_PINF;
483 case FP_SUBNORMAL: return signbit(d) ?_FPCLASS_ND : _FPCLASS_PD;
484 case FP_ZERO: return signbit(d) ? _FPCLASS_NZ : _FPCLASS_PZ;
486 return signbit(d) ? _FPCLASS_NN : _FPCLASS_PN;
489 return _FPCLASS_QNAN;
490 return d == 0.0 ? _FPCLASS_PZ : (d < 0 ? _FPCLASS_NN : _FPCLASS_PN);
495 /*********************************************************************
496 * _initterm (CRTDLL.135)
498 DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
500 _INITTERMFUN *current;
502 TRACE("(%p,%p)\n",start,end);
504 while (current<end) {
505 if (*current) (*current)();
512 /*******************************************************************
513 * _global_unwind2 (CRTDLL.129)
515 void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
517 RtlUnwind( frame, 0, NULL, 0 );
521 /*******************************************************************
522 * _local_unwind2 (CRTDLL.173)
524 void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
526 TRACE("(%p,%ld)\n",endframe,nr);
530 /*******************************************************************
531 * _setjmp (CRTDLL.264)
533 INT __cdecl CRTDLL__setjmp(LPDWORD *jmpbuf)
535 FIXME(":(%p): stub\n",jmpbuf);
540 /*********************************************************************
543 * Output a tone using the PC speaker.
546 * freq [in] Frequency of the tone
548 * duration [in] Length of time the tone should sound
553 void __cdecl CRTDLL__beep( UINT freq, UINT duration)
555 TRACE(":Freq %d, Duration %d\n",freq,duration);
556 Beep(freq, duration);
560 /*********************************************************************
563 INT __cdecl CRTDLL_rand()
565 return (rand() & CRTDLL_RAND_MAX);
569 /*********************************************************************
572 UINT __cdecl CRTDLL__rotl(UINT x,INT shift)
575 return (x << shift) | (x >> (32-shift));
579 /*********************************************************************
582 double __cdecl CRTDLL__logb(double x)
584 if (!finite(x)) CRTDLL_errno = EDOM;
589 /*********************************************************************
590 * _lrotl (CRTDLL.175)
592 DWORD __cdecl CRTDLL__lrotl(DWORD x,INT shift)
595 return (x << shift) | (x >> (32-shift));
599 /*********************************************************************
600 * _lrotr (CRTDLL.176)
602 DWORD __cdecl CRTDLL__lrotr(DWORD x,INT shift)
605 return (x >> shift) | (x << (32-shift));
609 /*********************************************************************
612 DWORD __cdecl CRTDLL__rotr(UINT x,INT shift)
615 return (x >> shift) | (x << (32-shift));
619 /*********************************************************************
620 * _scalb (CRTDLL.259)
624 double __cdecl CRTDLL__scalb(double x, LONG y)
626 /* Note - Can't forward directly as libc expects y as double */
627 double y2 = (double)y;
628 if (!finite(x)) CRTDLL_errno = EDOM;
629 return scalb( x, y2 );
633 /*********************************************************************
634 * longjmp (CRTDLL.426)
636 VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
638 FIXME("CRTDLL_longjmp semistup, expect crash\n");
643 /*********************************************************************
644 * setlocale (CRTDLL.453)
646 LPSTR __cdecl CRTDLL_setlocale(INT category,LPCSTR locale)
651 case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
652 case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
653 case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
654 case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
655 case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
656 case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
657 default: categorystr = "UNKNOWN?";break;
659 FIXME("(%s,%s),stub!\n",categorystr,locale);
664 /*********************************************************************
665 * _isctype (CRTDLL.138)
667 INT __cdecl CRTDLL__isctype(INT c,UINT type)
669 return CRTDLL_ctype[(UINT)c+1] & type;
673 /*********************************************************************
674 * _fullpath (CRTDLL.114)
676 LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT size)
681 if(!(buf = CRTDLL_malloc(size))) return NULL;
683 if (!GetFullPathNameA( name, size, buf, NULL )) return NULL;
684 TRACE("CRTDLL_fullpath got %s\n",buf);
689 /*********************************************************************
690 * _splitpath (CRTDLL.279)
692 VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
695 directory includes leading and trailing (forward and backward slashes)
696 filename without dot and slashes
697 extension with leading dot
699 char * drivechar,*dirchar,*namechar;
701 TRACE("CRTDLL__splitpath got %s\n",path);
703 drivechar = strchr(path,':');
704 dirchar = strrchr(path,'/');
705 namechar = strrchr(path,'\\');
706 dirchar = max(dirchar,namechar);
708 namechar = strrchr(dirchar,'.');
710 namechar = strrchr(path,'.');
717 strncat(drive,path,drivechar-path+1);
726 strncat(directory,path,dirchar-path+1);
735 strncat(filename,path,namechar-path);
739 strcat(extension,namechar);
744 TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
748 /*********************************************************************
749 * _matherr (CRTDLL.181)
751 * Default handler for math errors.
753 INT __cdecl CRTDLL__matherr(struct _exception *e)
755 /* FIXME: Supposedly this can be user overridden, but
756 * currently it will never be called anyway.
758 FIXME(":Unhandled math error!\n");
759 return e == NULL ? 0 : 0;
763 /*********************************************************************
764 * _makepath (CRTDLL.182)
767 VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive,
768 LPCSTR directory, LPCSTR filename,
772 TRACE("CRTDLL__makepath got %s %s %s %s\n", drive, directory,
773 filename, extension);
779 if (drive && drive[0])
785 if (directory && directory[0])
787 strcat(path, directory);
788 ch = path[strlen(path)-1];
789 if (ch != '/' && ch != '\\')
792 if (filename && filename[0])
794 strcat(path, filename);
795 if (extension && extension[0])
797 if ( extension[0] != '.' ) {
800 strcat(path,extension);
804 TRACE("CRTDLL__makepath returns %s\n",path);
808 /*********************************************************************
810 * Return the address of the CRT errno (Not the libc errno).
815 LPINT __cdecl CRTDLL__errno( VOID )
817 return &CRTDLL_errno;
821 /*********************************************************************
822 * __doserrno (CRTDLL.26)
824 * Return the address of the DOS errno (holding the last OS error).
829 LPINT __cdecl CRTDLL___doserrno( VOID )
831 return &CRTDLL_doserrno;
834 /**********************************************************************
835 * _statusfp (CRTDLL.279)
837 * Return the status of the FP control word.
839 UINT __cdecl CRTDLL__statusfp( VOID )
842 #if defined(__GNUC__) && defined(__i386__)
845 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
846 if (fpword & 0x1) retVal |= _SW_INVALID;
847 if (fpword & 0x2) retVal |= _SW_DENORMAL;
848 if (fpword & 0x4) retVal |= _SW_ZERODIVIDE;
849 if (fpword & 0x8) retVal |= _SW_OVERFLOW;
850 if (fpword & 0x10) retVal |= _SW_UNDERFLOW;
851 if (fpword & 0x20) retVal |= _SW_INEXACT;
853 FIXME(":Not implemented!\n");
859 /**********************************************************************
860 * _strerror (CRTDLL.284)
862 * Return a formatted system error message.
865 * The caller does not own the string returned.
867 extern int sprintf(char *str, const char *format, ...);
869 LPSTR __cdecl CRTDLL__strerror (LPCSTR err)
871 static char strerrbuff[256];
872 sprintf(strerrbuff,"%s: %s\n",err,CRTDLL_strerror(CRTDLL_errno));
877 /*********************************************************************
878 * perror (CRTDLL.435)
880 * Print a formatted system error message to stderr.
882 VOID __cdecl CRTDLL_perror (LPCSTR err)
884 char *err_str = CRTDLL_strerror(CRTDLL_errno);
885 CRTDLL_fprintf(CRTDLL_stderr,"%s: %s\n",err,err_str);
886 CRTDLL_free(err_str);
890 /*********************************************************************
891 * strerror (CRTDLL.465)
893 * Return the text of an error.
896 * The caller does not own the string returned.
898 extern char *strerror(int errnum);
900 LPSTR __cdecl CRTDLL_strerror (INT err)
902 return strerror(err);
906 /*********************************************************************
907 * signal (CRTDLL.455)
909 LPVOID __cdecl CRTDLL_signal(INT sig, sig_handler_type ptr)
911 FIXME("(%d %p):stub.\n", sig, ptr);
916 /*********************************************************************
917 * _sleep (CRTDLL.267)
919 VOID __cdecl CRTDLL__sleep(ULONG timeout)
921 TRACE("CRTDLL__sleep for %ld milliseconds\n",timeout);
922 Sleep((timeout)?timeout:1);
926 /*********************************************************************
927 * getenv (CRTDLL.437)
929 LPSTR __cdecl CRTDLL_getenv(LPCSTR name)
931 LPSTR environ = GetEnvironmentStringsA();
935 for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
942 if (!strncmp(pp,name,length)) break;
947 TRACE("got %s\n",pp);
949 FreeEnvironmentStringsA( environ );
954 /*********************************************************************
955 * isalnum (CRTDLL.442)
957 INT __cdecl CRTDLL_isalnum(INT c)
959 return CRTDLL__isctype( c,CRTDLL_ALPHA | CRTDLL_DIGIT );
963 /*********************************************************************
964 * isalpha (CRTDLL.443)
966 INT __cdecl CRTDLL_isalpha(INT c)
968 return CRTDLL__isctype( c, CRTDLL_ALPHA );
972 /*********************************************************************
973 * iscntrl (CRTDLL.444)
975 INT __cdecl CRTDLL_iscntrl(INT c)
977 return CRTDLL__isctype( c, CRTDLL_CONTROL );
981 /*********************************************************************
982 * isdigit (CRTDLL.445)
984 INT __cdecl CRTDLL_isdigit(INT c)
986 return CRTDLL__isctype( c, CRTDLL_DIGIT );
990 /*********************************************************************
991 * isgraph (CRTDLL.446)
993 INT __cdecl CRTDLL_isgraph(INT c)
995 return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT | CRTDLL_PUNCT );
999 /*********************************************************************
1000 * islower (CRTDLL.447)
1002 INT __cdecl CRTDLL_islower(INT c)
1004 return CRTDLL__isctype( c, CRTDLL_LOWER );
1008 /*********************************************************************
1009 * isprint (CRTDLL.448)
1011 INT __cdecl CRTDLL_isprint(INT c)
1013 return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT |
1014 CRTDLL_BLANK | CRTDLL_PUNCT );
1018 /*********************************************************************
1019 * ispunct (CRTDLL.449)
1021 INT __cdecl CRTDLL_ispunct(INT c)
1023 return CRTDLL__isctype( c, CRTDLL_PUNCT );
1027 /*********************************************************************
1028 * isspace (CRTDLL.450)
1030 INT __cdecl CRTDLL_isspace(INT c)
1032 return CRTDLL__isctype( c, CRTDLL_SPACE );
1036 /*********************************************************************
1037 * isupper (CRTDLL.451)
1039 INT __cdecl CRTDLL_isupper(INT c)
1041 return CRTDLL__isctype( c, CRTDLL_UPPER );
1045 /*********************************************************************
1046 * isxdigit (CRTDLL.452)
1048 INT __cdecl CRTDLL_isxdigit(INT c)
1050 return CRTDLL__isctype( c, CRTDLL_HEX );
1054 /*********************************************************************
1055 * ldexp (CRTDLL.454)
1057 double __cdecl CRTDLL_ldexp(double x, LONG y)
1059 double z = ldexp(x,y);
1062 CRTDLL_errno = ERANGE;
1063 else if (z == 0 && signbit(z))
1064 z = 0.0; /* Convert -0 -> +0 */
1068 /*********************************************************************
1069 * _except_handler2 (CRTDLL.78)
1071 INT __cdecl CRTDLL__except_handler2 (
1072 PEXCEPTION_RECORD rec,
1073 PEXCEPTION_FRAME frame,
1075 PEXCEPTION_FRAME *dispatcher)
1077 FIXME ("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
1078 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
1079 frame->Handler, context, dispatcher);
1080 return ExceptionContinueSearch;
1084 /*********************************************************************
1085 * __isascii (CRTDLL.028)
1088 INT __cdecl CRTDLL___isascii(INT c)
1090 return isascii((unsigned)c);
1094 /*********************************************************************
1095 * __toascii (CRTDLL.035)
1098 INT __cdecl CRTDLL___toascii(INT c)
1100 return (unsigned)c & 0x7f;
1104 /*********************************************************************
1105 * iswascii (CRTDLL.404)
1108 INT __cdecl CRTDLL_iswascii(LONG c)
1110 return ((unsigned)c < 0x80);
1114 /*********************************************************************
1115 * __iscsym (CRTDLL.029)
1117 * Is a character valid in a C identifier (a-Z,0-9,_).
1120 * c [I]: Character to check
1123 * Non zero if c is valid as t a C identifier.
1125 INT __cdecl CRTDLL___iscsym(UCHAR c)
1127 return (c < 127 && (isalnum(c) || c == '_'));
1131 /*********************************************************************
1132 * __iscsymf (CRTDLL.030)
1134 * Is a character valid as the first letter in a C identifier (a-Z,_).
1137 * c [in] Character to check
1140 * Non zero if c is valid as the first letter in a C identifier.
1142 INT __cdecl CRTDLL___iscsymf(UCHAR c)
1144 return (c < 127 && (isalpha(c) || c == '_'));
1148 /*********************************************************************
1149 * _lfind (CRTDLL.170)
1151 * Perform a linear search of an array for an element.
1153 LPVOID __cdecl CRTDLL__lfind(LPCVOID match, LPCVOID start, LPUINT array_size,
1154 UINT elem_size, comp_func cf)
1156 UINT size = *array_size;
1160 if (cf(match, start) == 0)
1161 return (LPVOID)start; /* found */
1168 /*********************************************************************
1169 * _loaddll (CRTDLL.171)
1171 * Get a handle to a DLL in memory. The DLL is loaded if it is not already.
1174 * dll [in] Name of DLL to load.
1177 * Success: A handle to the loaded DLL.
1181 INT __cdecl CRTDLL__loaddll(LPSTR dllname)
1183 return LoadLibraryA(dllname);
1187 /*********************************************************************
1188 * _unloaddll (CRTDLL.313)
1190 * Free reference to a DLL handle from loaddll().
1193 * dll [in] Handle to free.
1198 * Failure: Error number.
1200 INT __cdecl CRTDLL__unloaddll(HANDLE dll)
1203 if (FreeLibrary(dll))
1205 err = GetLastError();
1206 __CRTDLL__set_errno(err);
1211 /*********************************************************************
1212 * _lsearch (CRTDLL.177)
1214 * Linear search of an array of elements. Adds the item to the array if
1218 * match [in] Pointer to element to match
1219 * start [in] Pointer to start of search memory
1220 * array_size [in] Length of search array (element count)
1221 * elem_size [in] Size of each element in memory
1222 * cf [in] Pointer to comparison function (like qsort()).
1225 * Pointer to the location where element was found or added.
1227 LPVOID __cdecl CRTDLL__lsearch(LPVOID match,LPVOID start, LPUINT array_size,
1228 UINT elem_size, comp_func cf)
1230 UINT size = *array_size;
1234 if (cf(match, start) == 0)
1235 return start; /* found */
1239 /* not found, add to end */
1240 memcpy(start, match, elem_size);
1246 /*********************************************************************
1247 * _itow (CRTDLL.164)
1249 * Convert an integer to a wide char string.
1251 extern LPSTR __cdecl _itoa( long , LPSTR , INT); /* ntdll */
1253 WCHAR* __cdecl CRTDLL__itow(INT value,WCHAR* out,INT base)
1255 char buff[64]; /* FIXME: Whats the maximum buffer size for INT_MAX? */
1257 _itoa(value, buff, base);
1258 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1263 /*********************************************************************
1266 * Convert a long to a wide char string.
1268 extern LPSTR __cdecl _ltoa( long , LPSTR , INT); /* ntdll */
1270 WCHAR* __cdecl CRTDLL__ltow(LONG value,WCHAR* out,INT base)
1272 char buff[64]; /* FIXME: Whats the maximum buffer size for LONG_MAX? */
1274 _ltoa(value, buff, base);
1275 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1280 /*********************************************************************
1281 * _ultow (CRTDLL.??)
1283 * Convert an unsigned long to a wide char string.
1285 extern LPSTR __cdecl _ultoa( long , LPSTR , INT); /* ntdll */
1287 WCHAR* __cdecl CRTDLL__ultow(ULONG value,WCHAR* out,INT base)
1289 char buff[64]; /* FIXME: Whats the maximum buffer size for ULONG_MAX? */
1291 _ultoa(value, buff, base);
1292 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1297 /*********************************************************************
1298 * _toupper (CRTDLL.489)
1300 CHAR __cdecl CRTDLL__toupper(CHAR c)
1306 /*********************************************************************
1307 * _tolower (CRTDLL.490)
1309 CHAR __cdecl CRTDLL__tolower(CHAR c)
1317 /*********************************************************************
1318 * _cabs (CRTDLL.048)
1320 * Return the absolue value of a complex number.
1323 * c [in] Structure containing real and imaginary parts of complex number.
1326 * Absolute value of complex number (always a positive real number).
1328 double __cdecl CRTDLL__cabs(struct complex c)
1330 return sqrt(c.real * c.real + c.imaginary * c.imaginary);
1334 /*********************************************************************
1335 * _chgsign (CRTDLL.053)
1337 * Change the sign of an IEEE double.
1340 * d [in] Number to invert.
1343 * Number with sign inverted.
1345 double __cdecl CRTDLL__chgsign(double d)
1347 /* FIXME: +-infinity,Nan not tested */
1352 /*********************************************************************
1353 * _control87 (CRTDLL.060)
1355 * X86 implementation of _controlfp.
1358 UINT __cdecl CRTDLL__control87(UINT newVal, UINT mask)
1360 #if defined(__GNUC__) && defined(__i386__)
1361 UINT fpword, flags = 0;
1363 /* Get fp control word */
1364 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
1366 /* Convert into mask constants */
1367 if (fpword & 0x1) flags |= _EM_INVALID;
1368 if (fpword & 0x2) flags |= _EM_DENORMAL;
1369 if (fpword & 0x4) flags |= _EM_ZERODIVIDE;
1370 if (fpword & 0x8) flags |= _EM_OVERFLOW;
1371 if (fpword & 0x10) flags |= _EM_UNDERFLOW;
1372 if (fpword & 0x20) flags |= _EM_INEXACT;
1373 switch(fpword & 0xC00) {
1374 case 0xC00: flags |= _RC_UP|_RC_DOWN; break;
1375 case 0x800: flags |= _RC_UP; break;
1376 case 0x400: flags |= _RC_DOWN; break;
1378 switch(fpword & 0x300) {
1379 case 0x0: flags |= _PC_24; break;
1380 case 0x200: flags |= _PC_53; break;
1381 case 0x300: flags |= _PC_64; break;
1383 if (fpword & 0x1000) flags |= _IC_AFFINE;
1385 /* Mask with parameters */
1386 flags = (flags & ~mask) | (newVal & mask);
1388 /* Convert (masked) value back to fp word */
1390 if (flags & _EM_INVALID) fpword |= 0x1;
1391 if (flags & _EM_DENORMAL) fpword |= 0x2;
1392 if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
1393 if (flags & _EM_OVERFLOW) fpword |= 0x8;
1394 if (flags & _EM_UNDERFLOW) fpword |= 0x10;
1395 if (flags & _EM_INEXACT) fpword |= 0x20;
1396 switch(flags & (_RC_UP | _RC_DOWN)) {
1397 case _RC_UP|_RC_DOWN: fpword |= 0xC00; break;
1398 case _RC_UP: fpword |= 0x800; break;
1399 case _RC_DOWN: fpword |= 0x400; break;
1401 switch (flags & (_PC_24 | _PC_53)) {
1402 case _PC_64: fpword |= 0x300; break;
1403 case _PC_53: fpword |= 0x200; break;
1404 case _PC_24: fpword |= 0x0; break;
1406 if (!(flags & _IC_AFFINE)) fpword |= 0x1000;
1408 /* Put fp control word */
1409 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1412 return CRTDLL__controlfp( newVal, mask );
1417 /*********************************************************************
1418 * _controlfp (CRTDLL.061)
1420 * Set the state of the floating point unit.
1422 UINT __cdecl CRTDLL__controlfp( UINT newVal, UINT mask)
1424 #if defined(__GNUC__) && defined(__i386__)
1425 return CRTDLL__control87( newVal, mask );
1427 FIXME(":Not Implemented!\n");
1433 /*********************************************************************
1434 * _copysign (CRTDLL.062)
1436 * Return the number x with the sign of y.
1438 double __cdecl CRTDLL__copysign(double x, double y)
1440 /* FIXME: Behaviour for Nan/Inf etc? */
1442 return x < 0.0 ? x : -x;
1444 return x < 0.0 ? -x : x;
1448 /*********************************************************************
1449 * _finite (CRTDLL.101)
1451 * Determine if an IEEE double is finite (i.e. not +/- Infinity).
1454 * d [in] Number to check.
1457 * Non zero if number is finite.
1459 INT __cdecl CRTDLL__finite(double d)
1461 return (finite(d)?1:0); /* See comment for CRTDLL__isnan() */
1465 /*********************************************************************
1466 * _fpreset (CRTDLL.107)
1468 * Reset the state of the floating point processor.
1470 VOID __cdecl CRTDLL__fpreset(void)
1472 #if defined(__GNUC__) && defined(__i386__)
1473 __asm__ __volatile__( "fninit" );
1475 FIXME(":Not Implemented!\n");
1480 /*********************************************************************
1481 * _isnan (CRTDLL.164)
1483 * Determine if an IEEE double is unrepresentable (NaN).
1486 * d [in] Number to check.
1489 * Non zero if number is NaN.
1491 INT __cdecl CRTDLL__isnan(double d)
1493 /* some implementations return -1 for true(glibc), crtdll returns 1.
1494 * Do the same, as the result may be used in calculations.
1496 return isnan(d)?1:0;
1500 /*********************************************************************
1501 * _purecall (CRTDLL.249)
1503 * Abort program after pure virtual function call.
1505 VOID __cdecl CRTDLL__purecall(VOID)
1507 CRTDLL__amsg_exit( 6025 );
1511 /*********************************************************************
1514 * Return the quotient and remainder of long integer division.
1517 /* Windows binary compatible - returns the struct in eax/edx. */
1518 LONGLONG __cdecl CRTDLL_div(INT x, INT y)
1521 div_t dt = div(x,y);
1522 retVal = ((LONGLONG)dt.rem << 32) | dt.quot;
1526 /* Non-x86 cant run win32 apps so dont need binary compatibility */
1527 div_t __cdecl CRTDLL_div(INT x, INT y)
1531 #endif /* __i386__ */
1534 /*********************************************************************
1537 * Return the quotient and remainder of long integer division.
1540 /* Windows binary compatible - returns the struct in eax/edx. */
1541 LONGLONG __cdecl CRTDLL_ldiv(LONG x, LONG y)
1544 ldiv_t ldt = ldiv(x,y);
1545 retVal = ((LONGLONG)ldt.rem << 32) | ldt.quot;
1549 /* Non-x86 cant run win32 apps so dont need binary compatibility */
1550 ldiv_t __cdecl CRTDLL_ldiv(LONG x, LONG y)
1554 #endif /* __i386__ */
1557 /*********************************************************************
1561 double __cdecl CRTDLL__y0(double x)
1565 if (!finite(x)) CRTDLL_errno = EDOM;
1567 if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1569 CRTDLL_errno = EDOM;
1575 /*********************************************************************
1579 double __cdecl CRTDLL__y1(double x)
1583 if (!finite(x)) CRTDLL_errno = EDOM;
1585 if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1587 CRTDLL_errno = EDOM;
1593 /*********************************************************************
1597 double __cdecl CRTDLL__yn(INT x, double y)
1601 if (!finite(y)) CRTDLL_errno = EDOM;
1603 if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1605 CRTDLL_errno = EDOM;