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
28 #define __USE_ISOC99 1
37 #ifndef finite /* Could be macro */
39 #define finite(x) isfinite(x)
41 #define finite(x) (!isnan(x)) /* At least catch some cases */
50 DEFAULT_DEBUG_CHANNEL(crtdll);
52 double CRTDLL_HUGE_dll; /* CRTDLL.20 */
53 UINT CRTDLL_argc_dll; /* CRTDLL.23 */
54 LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
55 LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
56 UINT CRTDLL_basemajor_dll; /* CRTDLL.42 */
57 UINT CRTDLL_baseminor_dll; /* CRTDLL.43 */
58 UINT CRTDLL_baseversion_dll; /* CRTDLL.44 */
59 UINT CRTDLL_commode_dll; /* CRTDLL.59 */
60 LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
61 UINT CRTDLL_fmode_dll; /* CRTDLL.104 */
62 UINT CRTDLL_osmajor_dll; /* CRTDLL.241 */
63 UINT CRTDLL_osminor_dll; /* CRTDLL.242 */
64 UINT CRTDLL_osmode_dll; /* CRTDLL.243 */
65 UINT CRTDLL_osver_dll; /* CRTDLL.244 */
66 UINT CRTDLL_osversion_dll; /* CRTDLL.245 */
67 UINT CRTDLL_winmajor_dll; /* CRTDLL.329 */
68 UINT CRTDLL_winminor_dll; /* CRTDLL.330 */
69 UINT CRTDLL_winver_dll; /* CRTDLL.331 */
70 INT CRTDLL_doserrno = 0;
72 const INT CRTDLL__sys_nerr = 43;
74 /* ASCII char classification flags - binary compatible */
75 #define _C_ CRTDLL_CONTROL
76 #define _S_ CRTDLL_SPACE
77 #define _P_ CRTDLL_PUNCT
78 #define _D_ CRTDLL_DIGIT
79 #define _H_ CRTDLL_HEX
80 #define _U_ CRTDLL_UPPER
81 #define _L_ CRTDLL_LOWER
83 WORD CRTDLL_ctype [257] = {
84 0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_,
85 _S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_,
86 _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|CRTDLL_BLANK,
87 _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_,
88 _P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_,
89 _D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_,
90 _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_,
91 _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_,
92 _U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_,
93 _L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_,
94 _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_,
95 _C_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 0, 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
103 /*********************************************************************
104 * CRTDLL_MainInit (CRTDLL.init)
106 BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
108 TRACE("(0x%08x,%ld,%p)\n",hinstDLL,fdwReason,lpvReserved);
110 if (fdwReason == DLL_PROCESS_ATTACH) {
112 CRTDLL_HUGE_dll = HUGE_VAL;
118 /* INTERNAL: Set the crt and dos errno's from the OS error given. */
119 void __CRTDLL__set_errno(ULONG err)
121 /* FIXME: not MT safe */
122 CRTDLL_doserrno = err;
126 #define ERR_CASE(oserr) case oserr:
127 #define ERR_MAPS(oserr,crterr) case oserr:CRTDLL_errno = crterr;break;
128 ERR_CASE(ERROR_ACCESS_DENIED)
129 ERR_CASE(ERROR_NETWORK_ACCESS_DENIED)
130 ERR_CASE(ERROR_CANNOT_MAKE)
131 ERR_CASE(ERROR_SEEK_ON_DEVICE)
132 ERR_CASE(ERROR_LOCK_FAILED)
133 ERR_CASE(ERROR_FAIL_I24)
134 ERR_CASE(ERROR_CURRENT_DIRECTORY)
135 ERR_CASE(ERROR_DRIVE_LOCKED)
136 ERR_CASE(ERROR_NOT_LOCKED)
137 ERR_CASE(ERROR_INVALID_ACCESS)
138 ERR_MAPS(ERROR_LOCK_VIOLATION, EACCES);
139 ERR_CASE(ERROR_FILE_NOT_FOUND)
140 ERR_CASE(ERROR_NO_MORE_FILES)
141 ERR_CASE(ERROR_BAD_PATHNAME)
142 ERR_CASE(ERROR_BAD_NETPATH)
143 ERR_CASE(ERROR_INVALID_DRIVE)
144 ERR_CASE(ERROR_BAD_NET_NAME)
145 ERR_CASE(ERROR_FILENAME_EXCED_RANGE)
146 ERR_MAPS(ERROR_PATH_NOT_FOUND, ENOENT);
147 ERR_MAPS(ERROR_IO_DEVICE, EIO);
148 ERR_MAPS(ERROR_BAD_FORMAT, ENOEXEC);
149 ERR_MAPS(ERROR_INVALID_HANDLE, EBADF);
150 ERR_CASE(ERROR_OUTOFMEMORY)
151 ERR_CASE(ERROR_INVALID_BLOCK)
152 ERR_CASE(ERROR_NOT_ENOUGH_QUOTA);
153 ERR_MAPS(ERROR_ARENA_TRASHED, ENOMEM);
154 ERR_MAPS(ERROR_BUSY, EBUSY);
155 ERR_CASE(ERROR_ALREADY_EXISTS)
156 ERR_MAPS(ERROR_FILE_EXISTS, EEXIST);
157 ERR_MAPS(ERROR_BAD_DEVICE, ENODEV);
158 ERR_MAPS(ERROR_TOO_MANY_OPEN_FILES, EMFILE);
159 ERR_MAPS(ERROR_DISK_FULL, ENOSPC);
160 ERR_MAPS(ERROR_BROKEN_PIPE, EPIPE);
161 ERR_MAPS(ERROR_POSSIBLE_DEADLOCK, EDEADLK);
162 ERR_MAPS(ERROR_DIR_NOT_EMPTY, ENOTEMPTY);
163 ERR_MAPS(ERROR_BAD_ENVIRONMENT, E2BIG);
164 ERR_CASE(ERROR_WAIT_NO_CHILDREN)
165 ERR_MAPS(ERROR_CHILD_NOT_COMPLETE, ECHILD);
166 ERR_CASE(ERROR_NO_PROC_SLOTS)
167 ERR_CASE(ERROR_MAX_THRDS_REACHED)
168 ERR_MAPS(ERROR_NESTING_NOT_ALLOWED, EAGAIN);
170 /* Remaining cases map to EINVAL */
171 /* FIXME: may be missing some errors above */
172 CRTDLL_errno = EINVAL;
176 #if defined(__GNUC__) && defined(__i386__)
177 #define FPU_DOUBLE(var) double var; \
178 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
179 #define FPU_DOUBLES(var1,var2) double var1,var2; \
180 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
181 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
183 #define FPU_DOUBLE(var) double var = sqrt(-1); \
184 FIXME(":not implemented\n");
185 #define FPU_DOUBLES(var1,var2) double var1,var2; \
186 var1=var2=sqrt(-1); FIXME(":not implemented\n")
189 /*********************************************************************
190 * _CIacos (CRTDLL.004)
192 double __cdecl CRTDLL__CIacos(void)
195 if (x < -1.0 || x > 1.0 || !finite(x)) CRTDLL_errno = EDOM;
200 /*********************************************************************
201 * _CIasin (CRTDLL.005)
203 double __cdecl CRTDLL__CIasin(void)
206 if (x < -1.0 || x > 1.0 || !finite(x)) CRTDLL_errno = EDOM;
211 /*********************************************************************
212 * _CIatan (CRTDLL.006)
214 double __cdecl CRTDLL__CIatan(void)
217 if (!finite(x)) CRTDLL_errno = EDOM;
221 /*********************************************************************
222 * _CIatan2 (CRTDLL.007)
224 double __cdecl CRTDLL__CIatan2(void)
227 if (!finite(x)) CRTDLL_errno = EDOM;
232 /*********************************************************************
233 * _CIcos (CRTDLL.008)
235 double __cdecl CRTDLL__CIcos(void)
238 if (!finite(x)) CRTDLL_errno = EDOM;
242 /*********************************************************************
243 * _CIcosh (CRTDLL.009)
245 double __cdecl CRTDLL__CIcosh(void)
248 if (!finite(x)) CRTDLL_errno = EDOM;
252 /*********************************************************************
253 * _CIexp (CRTDLL.010)
255 double __cdecl CRTDLL__CIexp(void)
258 if (!finite(x)) CRTDLL_errno = EDOM;
262 /*********************************************************************
263 * _CIfmod (CRTDLL.011)
265 double __cdecl CRTDLL__CIfmod(void)
268 if (!finite(x) || !finite(y)) CRTDLL_errno = EDOM;
272 /*********************************************************************
273 * _CIlog (CRTDLL.012)
275 double __cdecl CRTDLL__CIlog(void)
278 if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
279 if (x == 0.0) CRTDLL_errno = ERANGE;
283 /*********************************************************************
284 * _CIlog10 (CRTDLL.013)
286 double __cdecl CRTDLL__CIlog10(void)
289 if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
290 if (x == 0.0) CRTDLL_errno = ERANGE;
294 /*********************************************************************
295 * _CIpow (CRTDLL.014)
297 double __cdecl CRTDLL__CIpow(void)
301 /* FIXME: If x < 0 and y is not integral, set EDOM */
303 if (!finite(z)) CRTDLL_errno = EDOM;
307 /*********************************************************************
308 * _CIsin (CRTDLL.015)
310 double __cdecl CRTDLL__CIsin(void)
313 if (!finite(x)) CRTDLL_errno = EDOM;
317 /*********************************************************************
318 * _CIsinh (CRTDLL.016)
320 double __cdecl CRTDLL__CIsinh(void)
323 if (!finite(x)) CRTDLL_errno = EDOM;
327 /*********************************************************************
328 * _CIsqrt (CRTDLL.017)
330 double __cdecl CRTDLL__CIsqrt(void)
333 if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
337 /*********************************************************************
338 * _CItan (CRTDLL.018)
340 double __cdecl CRTDLL__CItan(void)
343 if (!finite(x)) CRTDLL_errno = EDOM;
347 /*********************************************************************
348 * _CItanh (CRTDLL.019)
350 double __cdecl CRTDLL__CItanh(void)
353 if (!finite(x)) CRTDLL_errno = EDOM;
357 /*********************************************************************
358 * _GetMainArgs (CRTDLL.022)
360 LPSTR * __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
361 LPSTR *environ,DWORD flag)
365 int xargc,end,last_arg,afterlastspace;
368 TRACE("(%p,%p,%p,%ld).\n",
369 argc,argv,environ,flag
372 if (CRTDLL_acmdln_dll != NULL)
373 HeapFree(GetProcessHeap(), 0, CRTDLL_acmdln_dll);
375 CRTDLL_acmdln_dll = cmdline = CRTDLL__strdup( GetCommandLineA() );
376 TRACE("got '%s'\n", cmdline);
378 version = GetVersion();
379 CRTDLL_osver_dll = version >> 16;
380 CRTDLL_winminor_dll = version & 0xFF;
381 CRTDLL_winmajor_dll = (version>>8) & 0xFF;
382 CRTDLL_baseversion_dll = version >> 16;
383 CRTDLL_winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
384 CRTDLL_baseminor_dll = (version >> 16) & 0xFF;
385 CRTDLL_basemajor_dll = (version >> 24) & 0xFF;
386 CRTDLL_osversion_dll = version & 0xFFFF;
387 CRTDLL_osminor_dll = version & 0xFF;
388 CRTDLL_osmajor_dll = (version>>8) & 0xFF;
390 /* missing threading init */
392 end=0;last_arg=0;xargv=NULL;xargc=0;afterlastspace=0;
395 if ((cmdline[end]==' ') || (cmdline[end]=='\0'))
397 if (cmdline[end]=='\0')
401 /* alloc xargc + NULL entry */
402 xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
403 sizeof(char*)*(xargc+1));
404 if (strlen(cmdline+afterlastspace))
406 xargv[xargc] = CRTDLL__strdup(cmdline+afterlastspace);
408 if (!last_arg) /* need to seek to the next arg ? */
411 while (cmdline[end]==' ')
418 xargv[xargc] = NULL; /* the last entry is NULL */
425 CRTDLL_argc_dll = xargc;
427 CRTDLL_argv_dll = xargv;
430 TRACE("found %d arguments\n",
432 CRTDLL_environ_dll = *environ = GetEnvironmentStringsA();
438 /*********************************************************************
439 * _clearfp (CRTDLL.056)
441 * Clear and return the previous FP status.
443 UINT __cdecl CRTDLL__clearfp( VOID )
445 UINT retVal = CRTDLL__statusfp();
446 #if defined(__GNUC__) && defined(__i386__)
447 __asm__ __volatile__( "fnclex" );
449 FIXME(":Not Implemented!\n");
454 /*********************************************************************
455 * _fpclass (CRTDLL.105)
457 * Return the FP classification of d.
459 INT __cdecl CRTDLL__fpclass(double d)
461 #if defined(HAVE_FPCLASS) || defined(fpclass)
462 switch (fpclass( d ))
464 case FP_SNAN: return _FPCLASS_SNAN;
465 case FP_QNAN: return _FPCLASS_QNAN;
466 case FP_NINF: return _FPCLASS_NINF;
467 case FP_PINF: return _FPCLASS_PINF;
468 case FP_NDENORM: return _FPCLASS_ND;
469 case FP_PDENORM: return _FPCLASS_PD;
470 case FP_NZERO: return _FPCLASS_NZ;
471 case FP_PZERO: return _FPCLASS_PZ;
472 case FP_NNORM: return _FPCLASS_NN;
475 #elif defined (fpclassify)
476 switch (fpclassify( d ))
478 case FP_NAN: return _FPCLASS_QNAN;
479 case FP_INFINITE: return signbit(d) ? _FPCLASS_NINF : _FPCLASS_PINF;
480 case FP_SUBNORMAL: return signbit(d) ?_FPCLASS_ND : _FPCLASS_PD;
481 case FP_ZERO: return signbit(d) ? _FPCLASS_NZ : _FPCLASS_PZ;
483 return signbit(d) ? _FPCLASS_NN : _FPCLASS_PN;
486 return _FPCLASS_QNAN;
487 return d == 0.0 ? _FPCLASS_PZ : (d < 0 ? _FPCLASS_NN : _FPCLASS_PN);
492 /*********************************************************************
493 * _initterm (CRTDLL.135)
495 DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
497 _INITTERMFUN *current;
499 TRACE("(%p,%p)\n",start,end);
501 while (current<end) {
502 if (*current) (*current)();
509 /*******************************************************************
510 * _global_unwind2 (CRTDLL.129)
512 void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
514 RtlUnwind( frame, 0, NULL, 0 );
518 /*******************************************************************
519 * _local_unwind2 (CRTDLL.173)
521 void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
523 TRACE("(%p,%ld)\n",endframe,nr);
527 /*******************************************************************
528 * _setjmp (CRTDLL.264)
530 INT __cdecl CRTDLL__setjmp(LPDWORD *jmpbuf)
532 FIXME(":(%p): stub\n",jmpbuf);
537 /*********************************************************************
540 * Output a tone using the PC speaker.
543 * freq [in] Frequency of the tone
545 * duration [in] Length of time the tone should sound
550 void __cdecl CRTDLL__beep( UINT freq, UINT duration)
552 TRACE(":Freq %d, Duration %d\n",freq,duration);
553 Beep(freq, duration);
557 /*********************************************************************
560 INT __cdecl CRTDLL_rand()
562 return (rand() & CRTDLL_RAND_MAX);
566 /*********************************************************************
569 UINT __cdecl CRTDLL__rotl(UINT x,INT shift)
572 return (x << shift) | (x >> (32-shift));
576 /*********************************************************************
579 double __cdecl CRTDLL__logb(double x)
581 if (!finite(x)) CRTDLL_errno = EDOM;
586 /*********************************************************************
587 * _lrotl (CRTDLL.175)
589 DWORD __cdecl CRTDLL__lrotl(DWORD x,INT shift)
592 return (x << shift) | (x >> (32-shift));
596 /*********************************************************************
597 * _lrotr (CRTDLL.176)
599 DWORD __cdecl CRTDLL__lrotr(DWORD x,INT shift)
602 return (x >> shift) | (x << (32-shift));
606 /*********************************************************************
609 DWORD __cdecl CRTDLL__rotr(UINT x,INT shift)
612 return (x >> shift) | (x << (32-shift));
616 /*********************************************************************
617 * _scalb (CRTDLL.259)
621 double __cdecl CRTDLL__scalb(double x, LONG y)
623 /* Note - Can't forward directly as libc expects y as double */
624 double y2 = (double)y;
625 if (!finite(x)) CRTDLL_errno = EDOM;
626 return scalb( x, y2 );
630 /*********************************************************************
631 * longjmp (CRTDLL.426)
633 VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
635 FIXME("CRTDLL_longjmp semistup, expect crash\n");
640 /*********************************************************************
641 * setlocale (CRTDLL.453)
643 LPSTR __cdecl CRTDLL_setlocale(INT category,LPCSTR locale)
648 case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
649 case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
650 case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
651 case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
652 case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
653 case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
654 default: categorystr = "UNKNOWN?";break;
656 FIXME("(%s,%s),stub!\n",categorystr,locale);
661 /*********************************************************************
662 * _isctype (CRTDLL.138)
664 INT __cdecl CRTDLL__isctype(INT c,UINT type)
666 return CRTDLL_ctype[(UINT)c+1] & type;
670 /*********************************************************************
671 * _fullpath (CRTDLL.114)
673 LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT size)
678 if(!(buf = CRTDLL_malloc(size))) return NULL;
680 if (!GetFullPathNameA( name, size, buf, NULL )) return NULL;
681 TRACE("CRTDLL_fullpath got %s\n",buf);
686 /*********************************************************************
687 * _splitpath (CRTDLL.279)
689 VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
692 directory includes leading and trailing (forward and backward slashes)
693 filename without dot and slashes
694 extension with leading dot
696 char * drivechar,*dirchar,*namechar;
698 TRACE("CRTDLL__splitpath got %s\n",path);
700 drivechar = strchr(path,':');
701 dirchar = strrchr(path,'/');
702 namechar = strrchr(path,'\\');
703 dirchar = max(dirchar,namechar);
705 namechar = strrchr(dirchar,'.');
707 namechar = strrchr(path,'.');
714 strncat(drive,path,drivechar-path+1);
723 strncat(directory,path,dirchar-path+1);
732 strncat(filename,path,namechar-path);
736 strcat(extension,namechar);
741 TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
745 /*********************************************************************
746 * _matherr (CRTDLL.181)
748 * Default handler for math errors.
750 INT __cdecl CRTDLL__matherr(struct _exception *e)
752 /* FIXME: Supposedly this can be user overridden, but
753 * currently it will never be called anyway.
755 FIXME(":Unhandled math error!\n");
756 return e == NULL ? 0 : 0;
760 /*********************************************************************
761 * _makepath (CRTDLL.182)
764 VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive,
765 LPCSTR directory, LPCSTR filename,
769 TRACE("CRTDLL__makepath got %s %s %s %s\n", drive, directory,
770 filename, extension);
776 if (drive && drive[0])
782 if (directory && directory[0])
784 strcat(path, directory);
785 ch = path[strlen(path)-1];
786 if (ch != '/' && ch != '\\')
789 if (filename && filename[0])
791 strcat(path, filename);
792 if (extension && extension[0])
794 if ( extension[0] != '.' ) {
797 strcat(path,extension);
801 TRACE("CRTDLL__makepath returns %s\n",path);
805 /*********************************************************************
807 * Return the address of the CRT errno (Not the libc errno).
812 LPINT __cdecl CRTDLL__errno( VOID )
814 return &CRTDLL_errno;
818 /*********************************************************************
819 * __doserrno (CRTDLL.26)
821 * Return the address of the DOS errno (holding the last OS error).
826 LPINT __cdecl CRTDLL___doserrno( VOID )
828 return &CRTDLL_doserrno;
831 /**********************************************************************
832 * _statusfp (CRTDLL.279)
834 * Return the status of the FP control word.
836 UINT __cdecl CRTDLL__statusfp( VOID )
839 #if defined(__GNUC__) && defined(__i386__)
842 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
843 if (fpword & 0x1) retVal |= _SW_INVALID;
844 if (fpword & 0x2) retVal |= _SW_DENORMAL;
845 if (fpword & 0x4) retVal |= _SW_ZERODIVIDE;
846 if (fpword & 0x8) retVal |= _SW_OVERFLOW;
847 if (fpword & 0x10) retVal |= _SW_UNDERFLOW;
848 if (fpword & 0x20) retVal |= _SW_INEXACT;
850 FIXME(":Not implemented!\n");
856 /**********************************************************************
857 * _strerror (CRTDLL.284)
859 * Return a formatted system error message.
862 * The caller does not own the string returned.
864 extern int sprintf(char *str, const char *format, ...);
866 LPSTR __cdecl CRTDLL__strerror (LPCSTR err)
868 static char strerrbuff[256];
869 sprintf(strerrbuff,"%s: %s\n",err,CRTDLL_strerror(CRTDLL_errno));
874 /*********************************************************************
875 * perror (CRTDLL.435)
877 * Print a formatted system error message to stderr.
879 VOID __cdecl CRTDLL_perror (LPCSTR err)
881 char *err_str = CRTDLL_strerror(CRTDLL_errno);
882 CRTDLL_fprintf(CRTDLL_stderr,"%s: %s\n",err,err_str);
883 CRTDLL_free(err_str);
887 /*********************************************************************
888 * strerror (CRTDLL.465)
890 * Return the text of an error.
893 * The caller does not own the string returned.
895 extern char *strerror(int errnum);
897 LPSTR __cdecl CRTDLL_strerror (INT err)
899 return strerror(err);
903 /*********************************************************************
904 * signal (CRTDLL.455)
906 LPVOID __cdecl CRTDLL_signal(INT sig, sig_handler_type ptr)
908 FIXME("(%d %p):stub.\n", sig, ptr);
913 /*********************************************************************
914 * _sleep (CRTDLL.267)
916 VOID __cdecl CRTDLL__sleep(ULONG timeout)
918 TRACE("CRTDLL__sleep for %ld milliseconds\n",timeout);
919 Sleep((timeout)?timeout:1);
923 /*********************************************************************
924 * getenv (CRTDLL.437)
926 LPSTR __cdecl CRTDLL_getenv(LPCSTR name)
928 LPSTR environ = GetEnvironmentStringsA();
932 for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
939 if (!strncmp(pp,name,length)) break;
944 TRACE("got %s\n",pp);
946 FreeEnvironmentStringsA( environ );
951 /*********************************************************************
952 * isalnum (CRTDLL.442)
954 INT __cdecl CRTDLL_isalnum(INT c)
956 return CRTDLL__isctype( c,CRTDLL_ALPHA | CRTDLL_DIGIT );
960 /*********************************************************************
961 * isalpha (CRTDLL.443)
963 INT __cdecl CRTDLL_isalpha(INT c)
965 return CRTDLL__isctype( c, CRTDLL_ALPHA );
969 /*********************************************************************
970 * iscntrl (CRTDLL.444)
972 INT __cdecl CRTDLL_iscntrl(INT c)
974 return CRTDLL__isctype( c, CRTDLL_CONTROL );
978 /*********************************************************************
979 * isdigit (CRTDLL.445)
981 INT __cdecl CRTDLL_isdigit(INT c)
983 return CRTDLL__isctype( c, CRTDLL_DIGIT );
987 /*********************************************************************
988 * isgraph (CRTDLL.446)
990 INT __cdecl CRTDLL_isgraph(INT c)
992 return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT | CRTDLL_PUNCT );
996 /*********************************************************************
997 * islower (CRTDLL.447)
999 INT __cdecl CRTDLL_islower(INT c)
1001 return CRTDLL__isctype( c, CRTDLL_LOWER );
1005 /*********************************************************************
1006 * isprint (CRTDLL.448)
1008 INT __cdecl CRTDLL_isprint(INT c)
1010 return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT |
1011 CRTDLL_BLANK | CRTDLL_PUNCT );
1015 /*********************************************************************
1016 * ispunct (CRTDLL.449)
1018 INT __cdecl CRTDLL_ispunct(INT c)
1020 return CRTDLL__isctype( c, CRTDLL_PUNCT );
1024 /*********************************************************************
1025 * isspace (CRTDLL.450)
1027 INT __cdecl CRTDLL_isspace(INT c)
1029 return CRTDLL__isctype( c, CRTDLL_SPACE );
1033 /*********************************************************************
1034 * isupper (CRTDLL.451)
1036 INT __cdecl CRTDLL_isupper(INT c)
1038 return CRTDLL__isctype( c, CRTDLL_UPPER );
1042 /*********************************************************************
1043 * isxdigit (CRTDLL.452)
1045 INT __cdecl CRTDLL_isxdigit(INT c)
1047 return CRTDLL__isctype( c, CRTDLL_HEX );
1051 /*********************************************************************
1052 * ldexp (CRTDLL.454)
1054 double __cdecl CRTDLL_ldexp(double x, LONG y)
1056 double z = ldexp(x,y);
1059 CRTDLL_errno = ERANGE;
1060 else if (z == 0 && signbit(z))
1061 z = 0.0; /* Convert -0 -> +0 */
1065 /*********************************************************************
1066 * _except_handler2 (CRTDLL.78)
1068 INT __cdecl CRTDLL__except_handler2 (
1069 PEXCEPTION_RECORD rec,
1070 PEXCEPTION_FRAME frame,
1072 PEXCEPTION_FRAME *dispatcher)
1074 FIXME ("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
1075 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
1076 frame->Handler, context, dispatcher);
1077 return ExceptionContinueSearch;
1081 /*********************************************************************
1082 * __isascii (CRTDLL.028)
1085 INT __cdecl CRTDLL___isascii(INT c)
1087 return isascii((unsigned)c);
1091 /*********************************************************************
1092 * __toascii (CRTDLL.035)
1095 INT __cdecl CRTDLL___toascii(INT c)
1097 return (unsigned)c & 0x7f;
1101 /*********************************************************************
1102 * iswascii (CRTDLL.404)
1105 INT __cdecl CRTDLL_iswascii(LONG c)
1107 return ((unsigned)c < 0x80);
1111 /*********************************************************************
1112 * __iscsym (CRTDLL.029)
1114 * Is a character valid in a C identifier (a-Z,0-9,_).
1117 * c [I]: Character to check
1120 * Non zero if c is valid as t a C identifier.
1122 INT __cdecl CRTDLL___iscsym(UCHAR c)
1124 return (c < 127 && (isalnum(c) || c == '_'));
1128 /*********************************************************************
1129 * __iscsymf (CRTDLL.030)
1131 * Is a character valid as the first letter in a C identifier (a-Z,_).
1134 * c [in] Character to check
1137 * Non zero if c is valid as the first letter in a C identifier.
1139 INT __cdecl CRTDLL___iscsymf(UCHAR c)
1141 return (c < 127 && (isalpha(c) || c == '_'));
1145 /*********************************************************************
1146 * _lfind (CRTDLL.170)
1148 * Perform a linear search of an array for an element.
1150 LPVOID __cdecl CRTDLL__lfind(LPCVOID match, LPCVOID start, LPUINT array_size,
1151 UINT elem_size, comp_func cf)
1153 UINT size = *array_size;
1157 if (cf(match, start) == 0)
1158 return (LPVOID)start; /* found */
1165 /*********************************************************************
1166 * _loaddll (CRTDLL.171)
1168 * Get a handle to a DLL in memory. The DLL is loaded if it is not already.
1171 * dll [in] Name of DLL to load.
1174 * Success: A handle to the loaded DLL.
1178 INT __cdecl CRTDLL__loaddll(LPSTR dllname)
1180 return LoadLibraryA(dllname);
1184 /*********************************************************************
1185 * _unloaddll (CRTDLL.313)
1187 * Free reference to a DLL handle from loaddll().
1190 * dll [in] Handle to free.
1195 * Failure: Error number.
1197 INT __cdecl CRTDLL__unloaddll(HANDLE dll)
1200 if (FreeLibrary(dll))
1202 err = GetLastError();
1203 __CRTDLL__set_errno(err);
1208 /*********************************************************************
1209 * _lsearch (CRTDLL.177)
1211 * Linear search of an array of elements. Adds the item to the array if
1215 * match [in] Pointer to element to match
1216 * start [in] Pointer to start of search memory
1217 * array_size [in] Length of search array (element count)
1218 * elem_size [in] Size of each element in memory
1219 * cf [in] Pointer to comparison function (like qsort()).
1222 * Pointer to the location where element was found or added.
1224 LPVOID __cdecl CRTDLL__lsearch(LPVOID match,LPVOID start, LPUINT array_size,
1225 UINT elem_size, comp_func cf)
1227 UINT size = *array_size;
1231 if (cf(match, start) == 0)
1232 return start; /* found */
1236 /* not found, add to end */
1237 memcpy(start, match, elem_size);
1243 /*********************************************************************
1244 * _itow (CRTDLL.164)
1246 * Convert an integer to a wide char string.
1248 extern LPSTR __cdecl _itoa( long , LPSTR , INT); /* ntdll */
1250 WCHAR* __cdecl CRTDLL__itow(INT value,WCHAR* out,INT base)
1252 char buff[64]; /* FIXME: Whats the maximum buffer size for INT_MAX? */
1254 _itoa(value, buff, base);
1255 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1260 /*********************************************************************
1263 * Convert a long to a wide char string.
1265 extern LPSTR __cdecl _ltoa( long , LPSTR , INT); /* ntdll */
1267 WCHAR* __cdecl CRTDLL__ltow(LONG value,WCHAR* out,INT base)
1269 char buff[64]; /* FIXME: Whats the maximum buffer size for LONG_MAX? */
1271 _ltoa(value, buff, base);
1272 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1277 /*********************************************************************
1278 * _ultow (CRTDLL.??)
1280 * Convert an unsigned long to a wide char string.
1282 extern LPSTR __cdecl _ultoa( long , LPSTR , INT); /* ntdll */
1284 WCHAR* __cdecl CRTDLL__ultow(ULONG value,WCHAR* out,INT base)
1286 char buff[64]; /* FIXME: Whats the maximum buffer size for ULONG_MAX? */
1288 _ultoa(value, buff, base);
1289 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1294 /*********************************************************************
1295 * _toupper (CRTDLL.489)
1297 CHAR __cdecl CRTDLL__toupper(CHAR c)
1303 /*********************************************************************
1304 * _tolower (CRTDLL.490)
1306 CHAR __cdecl CRTDLL__tolower(CHAR c)
1314 /*********************************************************************
1315 * _cabs (CRTDLL.048)
1317 * Return the absolue value of a complex number.
1320 * c [in] Structure containing real and imaginary parts of complex number.
1323 * Absolute value of complex number (always a positive real number).
1325 double __cdecl CRTDLL__cabs(struct complex c)
1327 return sqrt(c.real * c.real + c.imaginary * c.imaginary);
1331 /*********************************************************************
1332 * _chgsign (CRTDLL.053)
1334 * Change the sign of an IEEE double.
1337 * d [in] Number to invert.
1340 * Number with sign inverted.
1342 double __cdecl CRTDLL__chgsign(double d)
1344 /* FIXME: +-infinity,Nan not tested */
1349 /*********************************************************************
1350 * _control87 (CRTDLL.060)
1352 * X86 implementation of _controlfp.
1355 UINT __cdecl CRTDLL__control87(UINT newVal, UINT mask)
1357 #if defined(__GNUC__) && defined(__i386__)
1358 UINT fpword, flags = 0;
1360 /* Get fp control word */
1361 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
1363 /* Convert into mask constants */
1364 if (fpword & 0x1) flags |= _EM_INVALID;
1365 if (fpword & 0x2) flags |= _EM_DENORMAL;
1366 if (fpword & 0x4) flags |= _EM_ZERODIVIDE;
1367 if (fpword & 0x8) flags |= _EM_OVERFLOW;
1368 if (fpword & 0x10) flags |= _EM_UNDERFLOW;
1369 if (fpword & 0x20) flags |= _EM_INEXACT;
1370 switch(fpword & 0xC00) {
1371 case 0xC00: flags |= _RC_UP|_RC_DOWN; break;
1372 case 0x800: flags |= _RC_UP; break;
1373 case 0x400: flags |= _RC_DOWN; break;
1375 switch(fpword & 0x300) {
1376 case 0x0: flags |= _PC_24; break;
1377 case 0x200: flags |= _PC_53; break;
1378 case 0x300: flags |= _PC_64; break;
1380 if (fpword & 0x1000) flags |= _IC_AFFINE;
1382 /* Mask with parameters */
1383 flags = (flags & ~mask) | (newVal & mask);
1385 /* Convert (masked) value back to fp word */
1387 if (flags & _EM_INVALID) fpword |= 0x1;
1388 if (flags & _EM_DENORMAL) fpword |= 0x2;
1389 if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
1390 if (flags & _EM_OVERFLOW) fpword |= 0x8;
1391 if (flags & _EM_UNDERFLOW) fpword |= 0x10;
1392 if (flags & _EM_INEXACT) fpword |= 0x20;
1393 switch(flags & (_RC_UP | _RC_DOWN)) {
1394 case _RC_UP|_RC_DOWN: fpword |= 0xC00; break;
1395 case _RC_UP: fpword |= 0x800; break;
1396 case _RC_DOWN: fpword |= 0x400; break;
1398 switch (flags & (_PC_24 | _PC_53)) {
1399 case _PC_64: fpword |= 0x300; break;
1400 case _PC_53: fpword |= 0x200; break;
1401 case _PC_24: fpword |= 0x0; break;
1403 if (!(flags & _IC_AFFINE)) fpword |= 0x1000;
1405 /* Put fp control word */
1406 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1409 return CRTDLL__controlfp( newVal, mask );
1414 /*********************************************************************
1415 * _controlfp (CRTDLL.061)
1417 * Set the state of the floating point unit.
1419 UINT __cdecl CRTDLL__controlfp( UINT newVal, UINT mask)
1421 #if defined(__GNUC__) && defined(__i386__)
1422 return CRTDLL__control87( newVal, mask );
1424 FIXME(":Not Implemented!\n");
1430 /*********************************************************************
1431 * _copysign (CRTDLL.062)
1433 * Return the number x with the sign of y.
1435 double __cdecl CRTDLL__copysign(double x, double y)
1437 /* FIXME: Behaviour for Nan/Inf etc? */
1439 return x < 0.0 ? x : -x;
1441 return x < 0.0 ? -x : x;
1445 /*********************************************************************
1446 * _finite (CRTDLL.101)
1448 * Determine if an IEEE double is finite (i.e. not +/- Infinity).
1451 * d [in] Number to check.
1454 * Non zero if number is finite.
1456 INT __cdecl CRTDLL__finite(double d)
1458 return (finite(d)?1:0); /* See comment for CRTDLL__isnan() */
1462 /*********************************************************************
1463 * _fpreset (CRTDLL.107)
1465 * Reset the state of the floating point processor.
1467 VOID __cdecl CRTDLL__fpreset(void)
1469 #if defined(__GNUC__) && defined(__i386__)
1470 __asm__ __volatile__( "fninit" );
1472 FIXME(":Not Implemented!\n");
1477 /*********************************************************************
1478 * _isnan (CRTDLL.164)
1480 * Determine if an IEEE double is unrepresentable (NaN).
1483 * d [in] Number to check.
1486 * Non zero if number is NaN.
1488 INT __cdecl CRTDLL__isnan(double d)
1490 /* some implementations return -1 for true(glibc), crtdll returns 1.
1491 * Do the same, as the result may be used in calculations.
1493 return isnan(d)?1:0;
1497 /*********************************************************************
1498 * _purecall (CRTDLL.249)
1500 * Abort program after pure virtual function call.
1502 VOID __cdecl CRTDLL__purecall(VOID)
1504 CRTDLL__amsg_exit( 6025 );
1508 /*********************************************************************
1511 * Return the quotient and remainder of long integer division.
1514 /* Windows binary compatible - returns the struct in eax/edx. */
1515 LONGLONG __cdecl CRTDLL_div(INT x, INT y)
1518 div_t dt = div(x,y);
1519 retVal = ((LONGLONG)dt.rem << 32) | dt.quot;
1523 /* Non-x86 cant run win32 apps so dont need binary compatibility */
1524 div_t __cdecl CRTDLL_div(INT x, INT y)
1528 #endif /* __i386__ */
1531 /*********************************************************************
1532 * _ldiv (CRTDLL.249)
1534 * Return the quotient and remainder of long integer division.
1537 /* Windows binary compatible - returns the struct in eax/edx. */
1538 LONGLONG __cdecl CRTDLL_ldiv(LONG x, LONG y)
1541 ldiv_t ldt = ldiv(x,y);
1542 retVal = ((LONGLONG)ldt.rem << 32) | ldt.quot;
1546 /* Non-x86 cant run win32 apps so dont need binary compatibility */
1547 ldiv_t __cdecl CRTDLL_ldiv(LONG x, LONG y)
1551 #endif /* __i386__ */
1554 /*********************************************************************
1558 double __cdecl CRTDLL__y0(double x)
1562 if (!finite(x)) CRTDLL_errno = EDOM;
1564 if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1566 CRTDLL_errno = EDOM;
1572 /*********************************************************************
1576 double __cdecl CRTDLL__y1(double x)
1580 if (!finite(x)) CRTDLL_errno = EDOM;
1582 if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1584 CRTDLL_errno = EDOM;
1590 /*********************************************************************
1594 double __cdecl CRTDLL__yn(INT x, double y)
1598 if (!finite(y)) CRTDLL_errno = EDOM;
1600 if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1602 CRTDLL_errno = EDOM;