Removed some unnecessary includes.
[wine] / dlls / crtdll / crtdll_main.c
1 /*
2  * The C RunTime DLL
3  * 
4  * Implements C run-time functionality as known from UNIX.
5  *
6  * Copyright 1996,1998 Marcus Meissner
7  * Copyright 1996 Jukka Iivonen
8  * Copyright 1997,2000 Uwe Bonnes
9  * Copyright 2000 Jon Griffiths
10  */
11
12 /*
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
16 UB 000416:
17 - probably not thread safe
18 */
19
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
23  */
24
25 #include "crtdll.h"
26 #include <ctype.h>
27 #define __USE_ISOC9X 1
28 #define __USE_ISOC99 1
29 #include <math.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include "ntddk.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35
36 #ifndef HAVE_FINITE
37 #ifndef finite /* Could be macro */
38 #ifdef isfinite 
39 #define finite(x) isfinite(x) 
40 #else
41 #define finite(x) (!isnan(x)) /* At least catch some cases */
42 #endif
43 #endif
44 #endif
45
46 #ifndef signbit
47 #define signbit(x) 0
48 #endif
49
50 DEFAULT_DEBUG_CHANNEL(crtdll);
51
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; 
71 INT  CRTDLL_errno = 0;
72 const INT  CRTDLL__sys_nerr = 43;
73
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
82
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
101 };
102
103 /*********************************************************************
104  *                  CRTDLL_MainInit  (CRTDLL.init)
105  */
106 BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
107 {
108         TRACE("(0x%08x,%ld,%p)\n",hinstDLL,fdwReason,lpvReserved);
109
110         if (fdwReason == DLL_PROCESS_ATTACH) {
111           __CRTDLL__init_io();
112           CRTDLL_HUGE_dll = HUGE_VAL;
113         }
114         return TRUE;
115 }
116
117
118 /* INTERNAL: Set the crt and dos errno's from the OS error given. */
119 void __CRTDLL__set_errno(ULONG err)
120 {
121   /* FIXME: not MT safe */
122   CRTDLL_doserrno = err;
123
124   switch(err)
125   {
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);
169   default:
170     /*  Remaining cases map to EINVAL */
171     /* FIXME: may be missing some errors above */
172     CRTDLL_errno = EINVAL;
173   }
174 }
175
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) : )
182 #else
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")
187 #endif
188
189 /*********************************************************************
190  *                  _CIacos             (CRTDLL.004)
191  */
192 double __cdecl CRTDLL__CIacos(void)
193 {
194   FPU_DOUBLE(x);
195   if (x < -1.0 || x > 1.0 || !finite(x)) CRTDLL_errno = EDOM;
196   return acos(x);
197 }
198
199
200 /*********************************************************************
201  *                  _CIasin             (CRTDLL.005)
202  */
203 double __cdecl CRTDLL__CIasin(void)
204 {
205   FPU_DOUBLE(x);
206   if (x < -1.0 || x > 1.0 || !finite(x)) CRTDLL_errno = EDOM;
207   return asin(x);
208 }
209
210
211 /*********************************************************************
212  *                  _CIatan             (CRTDLL.006)
213  */
214 double __cdecl CRTDLL__CIatan(void)
215 {
216   FPU_DOUBLE(x);
217   if (!finite(x)) CRTDLL_errno = EDOM;
218   return atan(x);
219 }
220
221 /*********************************************************************
222  *                  _CIatan2            (CRTDLL.007)
223  */
224 double __cdecl CRTDLL__CIatan2(void)
225 {
226   FPU_DOUBLES(x,y);
227   if (!finite(x)) CRTDLL_errno = EDOM;
228   return atan2(x,y);
229 }
230
231
232 /*********************************************************************
233  *                  _CIcos             (CRTDLL.008)
234  */
235 double __cdecl CRTDLL__CIcos(void)
236 {
237   FPU_DOUBLE(x);
238   if (!finite(x)) CRTDLL_errno = EDOM;
239   return cos(x);
240 }
241
242 /*********************************************************************
243  *                  _CIcosh            (CRTDLL.009)
244  */
245 double __cdecl CRTDLL__CIcosh(void)
246 {
247   FPU_DOUBLE(x);
248   if (!finite(x)) CRTDLL_errno = EDOM;
249   return cosh(x);
250 }
251
252 /*********************************************************************
253  *                  _CIexp             (CRTDLL.010)
254  */
255 double __cdecl CRTDLL__CIexp(void)
256 {
257   FPU_DOUBLE(x);
258   if (!finite(x)) CRTDLL_errno = EDOM;
259   return exp(x);
260 }
261
262 /*********************************************************************
263  *                  _CIfmod            (CRTDLL.011)
264  */
265 double __cdecl CRTDLL__CIfmod(void)
266 {
267   FPU_DOUBLES(x,y);
268   if (!finite(x) || !finite(y)) CRTDLL_errno = EDOM;
269   return fmod(x,y);
270 }
271
272 /*********************************************************************
273  *                  _CIlog             (CRTDLL.012)
274  */
275 double __cdecl CRTDLL__CIlog(void)
276 {
277   FPU_DOUBLE(x);
278   if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
279   if (x == 0.0) CRTDLL_errno = ERANGE;
280   return log(x);
281 }
282
283 /*********************************************************************
284  *                  _CIlog10           (CRTDLL.013)
285  */
286 double __cdecl CRTDLL__CIlog10(void)
287 {
288   FPU_DOUBLE(x);
289   if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
290   if (x == 0.0) CRTDLL_errno = ERANGE;
291   return log10(x);
292 }
293
294 /*********************************************************************
295  *                  _CIpow             (CRTDLL.014)
296  */
297 double __cdecl CRTDLL__CIpow(void)
298 {
299   double z;
300   FPU_DOUBLES(x,y);
301   /* FIXME: If x < 0 and y is not integral, set EDOM */
302   z = pow(x,y);
303   if (!finite(z)) CRTDLL_errno = EDOM;
304   return z;
305 }
306
307 /*********************************************************************
308  *                  _CIsin             (CRTDLL.015)
309  */
310 double __cdecl CRTDLL__CIsin(void)
311 {
312   FPU_DOUBLE(x);
313   if (!finite(x)) CRTDLL_errno = EDOM;
314   return sin(x);
315 }
316
317 /*********************************************************************
318  *                  _CIsinh            (CRTDLL.016)
319  */
320 double __cdecl CRTDLL__CIsinh(void)
321 {
322   FPU_DOUBLE(x);
323   if (!finite(x)) CRTDLL_errno = EDOM;
324   return sinh(x);
325 }
326
327 /*********************************************************************
328  *                  _CIsqrt            (CRTDLL.017)
329  */
330 double __cdecl CRTDLL__CIsqrt(void)
331 {
332   FPU_DOUBLE(x);
333   if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
334   return sqrt(x);
335 }
336
337 /*********************************************************************
338  *                  _CItan             (CRTDLL.018)
339  */
340 double __cdecl CRTDLL__CItan(void)
341 {
342   FPU_DOUBLE(x);
343   if (!finite(x)) CRTDLL_errno = EDOM;
344   return tan(x);
345 }
346
347 /*********************************************************************
348  *                  _CItanh            (CRTDLL.019)
349  */
350 double __cdecl CRTDLL__CItanh(void)
351 {
352   FPU_DOUBLE(x);
353   if (!finite(x)) CRTDLL_errno = EDOM;
354   return tanh(x);
355 }
356
357 /*********************************************************************
358  *                  _GetMainArgs  (CRTDLL.022)
359  */
360 LPSTR * __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
361                                 LPSTR *environ,DWORD flag)
362 {
363         char *cmdline;
364         char  **xargv;
365         int     xargc,end,last_arg,afterlastspace;
366         DWORD   version;
367
368         TRACE("(%p,%p,%p,%ld).\n",
369                 argc,argv,environ,flag
370         );
371
372         if (CRTDLL_acmdln_dll != NULL)
373                 HeapFree(GetProcessHeap(), 0, CRTDLL_acmdln_dll);
374
375         CRTDLL_acmdln_dll = cmdline = CRTDLL__strdup( GetCommandLineA() );
376         TRACE("got '%s'\n", cmdline);
377
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;
389
390         /* missing threading init */
391
392         end=0;last_arg=0;xargv=NULL;xargc=0;afterlastspace=0;
393         while (1)
394         {
395             if ((cmdline[end]==' ') || (cmdline[end]=='\0'))
396             {
397                 if (cmdline[end]=='\0')
398                     last_arg=1;
399                 else
400                     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))
405                 {
406                     xargv[xargc] = CRTDLL__strdup(cmdline+afterlastspace);
407                     xargc++;
408                     if (!last_arg) /* need to seek to the next arg ? */
409                     {
410                         end++;
411                         while (cmdline[end]==' ')
412                             end++;
413         }
414                     afterlastspace=end;
415                 }
416                 else
417                 {
418                     xargv[xargc] = NULL; /* the last entry is NULL */
419                     break;
420                 }
421             }
422             else
423                 end++;
424         }
425         CRTDLL_argc_dll = xargc;
426         *argc           = xargc;
427         CRTDLL_argv_dll = xargv;
428         *argv           = xargv;
429
430         TRACE("found %d arguments\n",
431                 CRTDLL_argc_dll);
432         CRTDLL_environ_dll = *environ = GetEnvironmentStringsA();
433         return environ;
434 }
435
436
437
438 /*********************************************************************
439  *                  _clearfp         (CRTDLL.056)
440  *
441  * Clear and return the previous FP status.
442  */
443 UINT __cdecl CRTDLL__clearfp( VOID )
444 {
445   UINT retVal = CRTDLL__statusfp();
446 #if defined(__GNUC__) && defined(__i386__)
447   __asm__ __volatile__( "fnclex" );
448 #else
449   FIXME(":Not Implemented!\n");
450 #endif
451   return retVal;
452 }
453
454 /*********************************************************************
455  *                  _fpclass         (CRTDLL.105)
456  *
457  * Return the FP classification of d.
458  */
459 INT __cdecl CRTDLL__fpclass(double d)
460 {
461 #if defined(HAVE_FPCLASS) || defined(fpclass)
462   switch (fpclass( d ))
463   {
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;
473   }
474   return _FPCLASS_PN;
475 #elif defined (fpclassify)
476   switch (fpclassify( d ))
477   {
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;
482   }
483   return signbit(d) ? _FPCLASS_NN : _FPCLASS_PN;
484 #else
485   if (!finite(d))
486     return _FPCLASS_QNAN;
487   return d == 0.0 ? _FPCLASS_PZ : (d < 0 ? _FPCLASS_NN : _FPCLASS_PN);
488 #endif
489 }
490
491
492 /*********************************************************************
493  *                  _initterm     (CRTDLL.135)
494  */
495 DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
496 {
497         _INITTERMFUN    *current;
498
499         TRACE("(%p,%p)\n",start,end);
500         current=start;
501         while (current<end) {
502                 if (*current) (*current)();
503                 current++;
504         }
505         return 0;
506 }
507
508
509 /*******************************************************************
510  *         _global_unwind2  (CRTDLL.129)
511  */
512 void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
513 {
514     RtlUnwind( frame, 0, NULL, 0 );
515 }
516
517
518 /*******************************************************************
519  *         _local_unwind2  (CRTDLL.173)
520  */
521 void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
522 {
523     TRACE("(%p,%ld)\n",endframe,nr);
524 }
525
526
527 /*******************************************************************
528  *         _setjmp  (CRTDLL.264)
529  */
530 INT __cdecl CRTDLL__setjmp(LPDWORD *jmpbuf)
531 {
532   FIXME(":(%p): stub\n",jmpbuf);
533   return 0;
534 }
535
536
537 /*********************************************************************
538  *                  _beep          (CRTDLL.045)
539  *
540  * Output a tone using the PC speaker.
541  *
542  * PARAMS
543  * freq [in]     Frequency of the tone
544  *
545  * duration [in] Length of time the tone should sound
546  *
547  * RETURNS
548  * None.
549  */
550 void __cdecl CRTDLL__beep( UINT freq, UINT duration)
551 {
552     TRACE(":Freq %d, Duration %d\n",freq,duration);
553     Beep(freq, duration);
554 }
555
556
557 /*********************************************************************
558  *                  rand          (CRTDLL.446)
559  */
560 INT __cdecl CRTDLL_rand()
561 {
562     return (rand() & CRTDLL_RAND_MAX); 
563 }
564
565
566 /*********************************************************************
567  *                  _rotl          (CRTDLL.259)
568  */
569 UINT __cdecl CRTDLL__rotl(UINT x,INT shift)
570 {
571     shift &= 31;
572     return (x << shift) | (x >> (32-shift));
573 }
574
575
576 /*********************************************************************
577  *                  _logb           (CRTDLL.174)
578  */
579 double __cdecl CRTDLL__logb(double x)
580 {
581   if (!finite(x)) CRTDLL_errno = EDOM;
582   return logb(x);
583 }
584
585
586 /*********************************************************************
587  *                  _lrotl          (CRTDLL.175)
588  */
589 DWORD __cdecl CRTDLL__lrotl(DWORD x,INT shift)
590 {
591     shift &= 31;
592     return (x << shift) | (x >> (32-shift));
593 }
594
595
596 /*********************************************************************
597  *                  _lrotr          (CRTDLL.176)
598  */
599 DWORD __cdecl CRTDLL__lrotr(DWORD x,INT shift)
600 {
601     shift &= 0x1f;
602     return (x >> shift) | (x << (32-shift));
603 }
604
605
606 /*********************************************************************
607  *                  _rotr          (CRTDLL.258)
608  */
609 DWORD __cdecl CRTDLL__rotr(UINT x,INT shift)
610 {
611     shift &= 0x1f;
612     return (x >> shift) | (x << (32-shift));
613 }
614
615
616 /*********************************************************************
617  *                  _scalb          (CRTDLL.259)
618  *
619  * Return x*2^y.
620  */
621 double  __cdecl CRTDLL__scalb(double x, LONG y)
622 {
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 );
627 }
628
629
630 /*********************************************************************
631  *                  longjmp        (CRTDLL.426)
632  */
633 VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
634 {
635     FIXME("CRTDLL_longjmp semistup, expect crash\n");
636     longjmp(env, val);
637 }
638
639
640 /*********************************************************************
641  *                  setlocale           (CRTDLL.453)
642  */
643 LPSTR __cdecl CRTDLL_setlocale(INT category,LPCSTR locale)
644 {
645     LPSTR categorystr;
646
647     switch (category) {
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;
655     }
656     FIXME("(%s,%s),stub!\n",categorystr,locale);
657     return "C";
658 }
659
660
661 /*********************************************************************
662  *                  _isctype           (CRTDLL.138)
663  */
664 INT __cdecl CRTDLL__isctype(INT c,UINT type)
665 {
666   return CRTDLL_ctype[(UINT)c+1] & type;
667 }
668
669
670 /*********************************************************************
671  *                  _fullpath           (CRTDLL.114)
672  */
673 LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT size)
674 {
675   if (!buf)
676   {
677       size = 256;
678       if(!(buf = CRTDLL_malloc(size))) return NULL;
679   }
680   if (!GetFullPathNameA( name, size, buf, NULL )) return NULL;
681   TRACE("CRTDLL_fullpath got %s\n",buf);
682   return buf;
683 }
684
685
686 /*********************************************************************
687  *                  _splitpath           (CRTDLL.279)
688  */
689 VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
690 {
691   /* drive includes :
692      directory includes leading and trailing (forward and backward slashes)
693      filename without dot and slashes
694      extension with leading dot
695      */
696   char * drivechar,*dirchar,*namechar;
697
698   TRACE("CRTDLL__splitpath got %s\n",path);
699
700   drivechar  = strchr(path,':');
701   dirchar    = strrchr(path,'/');
702   namechar   = strrchr(path,'\\');
703   dirchar = max(dirchar,namechar);
704   if (dirchar)
705     namechar   = strrchr(dirchar,'.');
706   else
707     namechar   = strrchr(path,'.');
708
709   if (drive)
710     {
711       *drive = 0x00;
712       if (drivechar)
713       {
714           strncat(drive,path,drivechar-path+1);
715           path = drivechar+1;
716       }
717     }
718   if (directory)
719     {
720       *directory = 0x00;
721       if (dirchar)
722       {
723           strncat(directory,path,dirchar-path+1);
724           path = dirchar+1;
725       }
726     }
727   if (filename)
728     {
729       *filename = 0x00;
730       if (namechar)
731       {
732           strncat(filename,path,namechar-path);
733           if (extension)
734           {
735               *extension = 0x00;
736               strcat(extension,namechar);
737           }
738       }
739     }
740
741   TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
742 }
743
744
745 /*********************************************************************
746  *                  _matherr            (CRTDLL.181)
747  *
748  * Default handler for math errors.
749 */
750 INT __cdecl CRTDLL__matherr(struct _exception *e)
751 {
752   /* FIXME: Supposedly this can be user overridden, but
753    * currently it will never be called anyway.
754    */
755   FIXME(":Unhandled math error!\n");
756   return e == NULL ? 0 : 0;
757 }
758
759
760 /*********************************************************************
761  *                  _makepath           (CRTDLL.182)
762  */
763
764 VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive,
765                               LPCSTR directory, LPCSTR filename,
766                               LPCSTR extension )
767 {
768     char ch;
769     TRACE("CRTDLL__makepath got %s %s %s %s\n", drive, directory,
770           filename, extension);
771
772     if ( !path )
773         return;
774
775     path[0] = 0;
776     if (drive && drive[0])
777     {
778         path[0] = drive[0];
779         path[1] = ':';
780         path[2] = 0;
781     }
782     if (directory && directory[0])
783     {
784         strcat(path, directory);
785         ch = path[strlen(path)-1];
786         if (ch != '/' && ch != '\\')
787             strcat(path,"\\");
788     }
789     if (filename && filename[0])
790     {
791         strcat(path, filename);
792         if (extension && extension[0])
793         {
794             if ( extension[0] != '.' ) {
795                 strcat(path,".");
796             }
797             strcat(path,extension);
798         }
799     }
800
801     TRACE("CRTDLL__makepath returns %s\n",path);
802 }
803
804
805 /*********************************************************************
806  *                  _errno           (CRTDLL.52)
807  * Return the address of the CRT errno (Not the libc errno).
808  *
809  * BUGS
810  * Not MT safe.
811  */
812 LPINT __cdecl CRTDLL__errno( VOID )
813 {
814   return &CRTDLL_errno;
815 }
816
817
818 /*********************************************************************
819  *                  __doserrno       (CRTDLL.26)
820  * 
821  * Return the address of the DOS errno (holding the last OS error).
822  *
823  * BUGS
824  * Not MT safe.
825  */
826 LPINT __cdecl CRTDLL___doserrno( VOID )
827 {
828   return &CRTDLL_doserrno;
829 }
830
831 /**********************************************************************
832  *                  _statusfp       (CRTDLL.279)
833  *
834  * Return the status of the FP control word.
835  */
836 UINT __cdecl CRTDLL__statusfp( VOID )
837 {
838   UINT retVal = 0;
839 #if defined(__GNUC__) && defined(__i386__)
840   UINT fpword;
841
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;
849 #else
850   FIXME(":Not implemented!\n");
851 #endif
852   return retVal;
853 }
854
855
856 /**********************************************************************
857  *                  _strerror       (CRTDLL.284)
858  *
859  * Return a formatted system error message.
860  *
861  * NOTES
862  * The caller does not own the string returned.
863  */
864 extern int sprintf(char *str, const char *format, ...);
865
866 LPSTR __cdecl CRTDLL__strerror (LPCSTR err)
867 {
868   static char strerrbuff[256];
869   sprintf(strerrbuff,"%s: %s\n",err,CRTDLL_strerror(CRTDLL_errno));
870   return strerrbuff;
871 }
872
873
874 /*********************************************************************
875  *                  perror       (CRTDLL.435)
876  *
877  * Print a formatted system error message to stderr.
878  */
879 VOID __cdecl CRTDLL_perror (LPCSTR err)
880 {
881   char *err_str = CRTDLL_strerror(CRTDLL_errno);
882   CRTDLL_fprintf(CRTDLL_stderr,"%s: %s\n",err,err_str);
883   CRTDLL_free(err_str);
884 }
885  
886
887 /*********************************************************************
888  *                  strerror       (CRTDLL.465)
889  *
890  * Return the text of an error.
891  *
892  * NOTES
893  * The caller does not own the string returned.
894  */
895 extern char *strerror(int errnum); 
896
897 LPSTR __cdecl CRTDLL_strerror (INT err)
898 {
899   return strerror(err);
900 }
901
902
903 /*********************************************************************
904  *                  signal           (CRTDLL.455)
905  */
906 LPVOID __cdecl CRTDLL_signal(INT sig, sig_handler_type ptr)
907 {
908     FIXME("(%d %p):stub.\n", sig, ptr);
909     return (void*)-1;
910 }
911
912
913 /*********************************************************************
914  *                  _sleep           (CRTDLL.267)
915  */
916 VOID __cdecl CRTDLL__sleep(ULONG timeout)
917 {
918   TRACE("CRTDLL__sleep for %ld milliseconds\n",timeout);
919   Sleep((timeout)?timeout:1);
920 }
921
922
923 /*********************************************************************
924  *                  getenv           (CRTDLL.437)
925  */
926 LPSTR __cdecl CRTDLL_getenv(LPCSTR name)
927 {
928      LPSTR environ = GetEnvironmentStringsA();
929      LPSTR pp,pos = NULL;
930      unsigned int length;
931
932      for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
933        {
934          pos =strchr(pp,'=');
935          if (pos)
936            length = pos -pp;
937          else
938            length = strlen(pp);
939          if (!strncmp(pp,name,length)) break;
940        }
941      if ((pp)&& (pos)) 
942        {
943          pp = pos+1;
944          TRACE("got %s\n",pp);
945        }
946      FreeEnvironmentStringsA( environ );
947      return pp;
948 }
949
950
951 /*********************************************************************
952  *                  isalnum          (CRTDLL.442)
953  */
954 INT __cdecl CRTDLL_isalnum(INT c)
955 {
956   return CRTDLL__isctype( c,CRTDLL_ALPHA | CRTDLL_DIGIT );
957 }
958
959
960 /*********************************************************************
961  *                  isalpha          (CRTDLL.443)
962  */
963 INT __cdecl CRTDLL_isalpha(INT c)
964 {
965   return CRTDLL__isctype( c, CRTDLL_ALPHA );
966 }
967
968
969 /*********************************************************************
970  *                  iscntrl          (CRTDLL.444)
971  */
972 INT __cdecl CRTDLL_iscntrl(INT c)
973 {
974   return CRTDLL__isctype( c, CRTDLL_CONTROL );
975 }
976
977
978 /*********************************************************************
979  *                  isdigit          (CRTDLL.445)
980  */
981 INT __cdecl CRTDLL_isdigit(INT c)
982 {
983   return CRTDLL__isctype( c, CRTDLL_DIGIT );
984 }
985
986
987 /*********************************************************************
988  *                  isgraph          (CRTDLL.446)
989  */
990 INT __cdecl CRTDLL_isgraph(INT c)
991 {
992   return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT | CRTDLL_PUNCT );
993 }
994
995
996 /*********************************************************************
997  *                  islower          (CRTDLL.447)
998  */
999 INT __cdecl CRTDLL_islower(INT c)
1000 {
1001   return CRTDLL__isctype( c, CRTDLL_LOWER );
1002 }
1003
1004
1005 /*********************************************************************
1006  *                  isprint          (CRTDLL.448)
1007  */
1008 INT __cdecl CRTDLL_isprint(INT c)
1009 {
1010   return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT |
1011                           CRTDLL_BLANK | CRTDLL_PUNCT );
1012 }
1013
1014
1015 /*********************************************************************
1016  *                  ispunct           (CRTDLL.449)
1017  */
1018 INT __cdecl CRTDLL_ispunct(INT c)
1019 {
1020   return CRTDLL__isctype( c, CRTDLL_PUNCT );
1021 }
1022
1023
1024 /*********************************************************************
1025  *                  isspace           (CRTDLL.450)
1026  */
1027 INT __cdecl CRTDLL_isspace(INT c)
1028 {
1029   return CRTDLL__isctype( c, CRTDLL_SPACE );
1030 }
1031
1032
1033 /*********************************************************************
1034  *                  isupper           (CRTDLL.451)
1035  */
1036 INT __cdecl CRTDLL_isupper(INT c)
1037 {
1038   return CRTDLL__isctype( c, CRTDLL_UPPER );
1039 }
1040
1041
1042 /*********************************************************************
1043  *                  isxdigit           (CRTDLL.452)
1044  */
1045 INT __cdecl CRTDLL_isxdigit(INT c)
1046 {
1047   return CRTDLL__isctype( c, CRTDLL_HEX );
1048 }
1049
1050
1051 /*********************************************************************
1052  *                  ldexp            (CRTDLL.454)
1053  */
1054 double __cdecl CRTDLL_ldexp(double x, LONG y)
1055 {
1056   double z = ldexp(x,y);
1057
1058   if (!finite(z))
1059     CRTDLL_errno = ERANGE;
1060   else if (z == 0 && signbit(z))
1061     z = 0.0; /* Convert -0 -> +0 */
1062   return z;
1063 }
1064
1065 /*********************************************************************
1066  *                  _except_handler2  (CRTDLL.78)
1067  */
1068 INT __cdecl CRTDLL__except_handler2 (
1069         PEXCEPTION_RECORD rec,
1070         PEXCEPTION_FRAME frame,
1071         PCONTEXT context,
1072         PEXCEPTION_FRAME  *dispatcher)
1073 {
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;
1078 }
1079
1080
1081 /*********************************************************************
1082  *                  __isascii           (CRTDLL.028)
1083  *
1084  */
1085 INT __cdecl CRTDLL___isascii(INT c)
1086 {
1087   return isascii((unsigned)c);
1088 }
1089
1090
1091 /*********************************************************************
1092  *                  __toascii           (CRTDLL.035)
1093  *
1094  */
1095 INT __cdecl CRTDLL___toascii(INT c)
1096 {
1097   return (unsigned)c & 0x7f;
1098 }
1099
1100
1101 /*********************************************************************
1102  *                  iswascii           (CRTDLL.404)
1103  *
1104  */
1105 INT __cdecl CRTDLL_iswascii(LONG c)
1106 {
1107   return ((unsigned)c < 0x80);
1108 }
1109
1110
1111 /*********************************************************************
1112  *                  __iscsym           (CRTDLL.029)
1113  *
1114  * Is a character valid in a C identifier (a-Z,0-9,_).
1115  *
1116  * PARAMS
1117  *   c       [I]: Character to check
1118  *
1119  * RETURNS
1120  * Non zero if c is valid as t a C identifier.
1121  */
1122 INT __cdecl CRTDLL___iscsym(UCHAR c)
1123 {
1124   return (c < 127 && (isalnum(c) || c == '_'));
1125 }
1126
1127
1128 /*********************************************************************
1129  *                  __iscsymf           (CRTDLL.030)
1130  *
1131  * Is a character valid as the first letter in a C identifier (a-Z,_).
1132  *
1133  * PARAMS
1134  *   c [in]  Character to check
1135  *
1136  * RETURNS
1137  *   Non zero if c is valid as the first letter in a C identifier.
1138  */
1139 INT __cdecl CRTDLL___iscsymf(UCHAR c)
1140 {
1141   return (c < 127 && (isalpha(c) || c == '_'));
1142 }
1143
1144
1145 /*********************************************************************
1146  *                  _lfind          (CRTDLL.170)
1147  *
1148  * Perform a linear search of an array for an element.
1149  */
1150 LPVOID __cdecl CRTDLL__lfind(LPCVOID match, LPCVOID start, LPUINT array_size,
1151                              UINT elem_size, comp_func cf)
1152 {
1153   UINT size = *array_size;
1154   if (size)
1155     do
1156     {
1157       if (cf(match, start) == 0)
1158         return (LPVOID)start; /* found */
1159       start += elem_size;
1160     } while (--size);
1161   return NULL;
1162 }
1163
1164
1165 /*********************************************************************
1166  *                  _loaddll        (CRTDLL.171)
1167  *
1168  * Get a handle to a DLL in memory. The DLL is loaded if it is not already.
1169  *
1170  * PARAMS
1171  * dll [in]  Name of DLL to load.
1172  *
1173  * RETURNS
1174  * Success: A handle to the loaded DLL.
1175  *
1176  * Failure: FIXME.
1177  */
1178 INT __cdecl CRTDLL__loaddll(LPSTR dllname)
1179 {
1180   return LoadLibraryA(dllname);
1181 }
1182
1183
1184 /*********************************************************************
1185  *                  _unloaddll        (CRTDLL.313)
1186  *
1187  * Free reference to a DLL handle from loaddll().
1188  *
1189  * PARAMS
1190  *   dll [in] Handle to free.
1191  *
1192  * RETURNS
1193  * Success: 0.
1194  *
1195  * Failure: Error number.
1196  */
1197 INT __cdecl CRTDLL__unloaddll(HANDLE dll)
1198 {
1199   INT err;
1200   if (FreeLibrary(dll))
1201     return 0;
1202   err = GetLastError();
1203   __CRTDLL__set_errno(err);
1204   return err;
1205 }
1206
1207
1208 /*********************************************************************
1209  *                  _lsearch        (CRTDLL.177)
1210  *
1211  * Linear search of an array of elements. Adds the item to the array if
1212  * not found.
1213  *
1214  * PARAMS
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()).
1220  *
1221  * RETURNS
1222  *   Pointer to the location where element was found or added.
1223  */
1224 LPVOID __cdecl CRTDLL__lsearch(LPVOID match,LPVOID start, LPUINT array_size,
1225                                UINT elem_size, comp_func cf)
1226 {
1227   UINT size = *array_size;
1228   if (size)
1229     do
1230     {
1231       if (cf(match, start) == 0)
1232         return start; /* found */
1233       start += elem_size;
1234     } while (--size);
1235
1236   /* not found, add to end */
1237   memcpy(start, match, elem_size);
1238   array_size[0]++;
1239   return start;
1240 }
1241
1242
1243 /*********************************************************************
1244  *                  _itow           (CRTDLL.164)
1245  *
1246  * Convert an integer to a wide char string.
1247  */
1248 extern LPSTR  __cdecl _itoa( long , LPSTR , INT); /* ntdll */
1249
1250 WCHAR* __cdecl CRTDLL__itow(INT value,WCHAR* out,INT base)
1251 {
1252   char buff[64]; /* FIXME: Whats the maximum buffer size for INT_MAX? */
1253
1254   _itoa(value, buff, base);
1255   MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1256   return out;
1257 }
1258
1259
1260 /*********************************************************************
1261  *                  _ltow           (CRTDLL.??)
1262  *
1263  * Convert a long to a wide char string.
1264  */
1265 extern LPSTR  __cdecl _ltoa( long , LPSTR , INT); /* ntdll */
1266
1267 WCHAR* __cdecl CRTDLL__ltow(LONG value,WCHAR* out,INT base)
1268 {
1269   char buff[64]; /* FIXME: Whats the maximum buffer size for LONG_MAX? */
1270
1271   _ltoa(value, buff, base);
1272   MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1273   return out;
1274 }
1275
1276
1277 /*********************************************************************
1278  *                  _ultow           (CRTDLL.??)
1279  *
1280  * Convert an unsigned long to a wide char string.
1281  */
1282 extern LPSTR  __cdecl _ultoa( long , LPSTR , INT); /* ntdll */
1283
1284 WCHAR* __cdecl CRTDLL__ultow(ULONG value,WCHAR* out,INT base)
1285 {
1286   char buff[64]; /* FIXME: Whats the maximum buffer size for ULONG_MAX? */
1287
1288   _ultoa(value, buff, base);
1289   MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
1290   return out;
1291 }
1292
1293
1294 /*********************************************************************
1295  *                  _toupper           (CRTDLL.489)
1296  */
1297 CHAR __cdecl CRTDLL__toupper(CHAR c)
1298 {
1299   return toupper(c);
1300 }
1301
1302
1303 /*********************************************************************
1304  *                  _tolower           (CRTDLL.490)
1305  */
1306 CHAR __cdecl CRTDLL__tolower(CHAR c)
1307 {
1308   return tolower(c);
1309 }
1310
1311
1312 /* FP functions */
1313
1314 /*********************************************************************
1315  *                  _cabs           (CRTDLL.048)
1316  *
1317  * Return the absolue value of a complex number.
1318  *
1319  * PARAMS
1320  *   c [in] Structure containing real and imaginary parts of complex number.
1321  *
1322  * RETURNS
1323  *   Absolute value of complex number (always a positive real number).
1324  */
1325 double __cdecl CRTDLL__cabs(struct complex c)
1326 {
1327   return sqrt(c.real * c.real + c.imaginary * c.imaginary);
1328 }
1329
1330
1331 /*********************************************************************
1332  *                  _chgsign    (CRTDLL.053)
1333  *
1334  * Change the sign of an IEEE double.
1335  *
1336  * PARAMS
1337  *   d [in] Number to invert.
1338  *
1339  * RETURNS
1340  *   Number with sign inverted.
1341  */
1342 double __cdecl CRTDLL__chgsign(double d)
1343 {
1344   /* FIXME: +-infinity,Nan not tested */
1345   return -d;
1346 }
1347
1348
1349 /*********************************************************************
1350  *                  _control87    (CRTDLL.060)
1351  *
1352  * X86 implementation of _controlfp.
1353  *
1354  */
1355 UINT __cdecl CRTDLL__control87(UINT newVal, UINT mask)
1356 {
1357 #if defined(__GNUC__) && defined(__i386__)
1358    UINT fpword, flags = 0;
1359
1360   /* Get fp control word */
1361   __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
1362
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;
1374   }
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;
1379   }
1380   if (fpword & 0x1000) flags |= _IC_AFFINE;
1381
1382   /* Mask with parameters */
1383   flags = (flags & ~mask) | (newVal & mask);
1384
1385   /* Convert (masked) value back to fp word */
1386   fpword = 0;
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;
1397   }
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;
1402   }
1403   if (!(flags & _IC_AFFINE)) fpword |= 0x1000;
1404
1405   /* Put fp control word */
1406   __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
1407   return fpword;
1408 #else
1409   return  CRTDLL__controlfp( newVal, mask );
1410 #endif
1411 }
1412
1413
1414 /*********************************************************************
1415  *                  _controlfp    (CRTDLL.061)
1416  *
1417  * Set the state of the floating point unit.
1418  */
1419 UINT __cdecl CRTDLL__controlfp( UINT newVal, UINT mask)
1420 {
1421 #if defined(__GNUC__) && defined(__i386__)
1422   return CRTDLL__control87( newVal, mask );
1423 #else
1424   FIXME(":Not Implemented!\n");
1425   return 0;
1426 #endif
1427 }
1428
1429
1430 /*********************************************************************
1431  *                  _copysign           (CRTDLL.062)
1432  *
1433  * Return the number x with the sign of y.
1434  */
1435 double __cdecl CRTDLL__copysign(double x, double y)
1436 {
1437   /* FIXME: Behaviour for Nan/Inf etc? */
1438   if (y < 0.0)
1439     return x < 0.0 ? x : -x;
1440
1441   return x < 0.0 ? -x : x;
1442 }
1443
1444
1445 /*********************************************************************
1446  *                  _finite           (CRTDLL.101)
1447  *
1448  * Determine if an IEEE double is finite (i.e. not +/- Infinity).
1449  *
1450  * PARAMS
1451  *   d [in]  Number to check.
1452  *
1453  * RETURNS
1454  *   Non zero if number is finite.
1455  */
1456 INT __cdecl  CRTDLL__finite(double d)
1457 {
1458   return (finite(d)?1:0); /* See comment for CRTDLL__isnan() */
1459 }
1460
1461
1462 /*********************************************************************
1463  *                  _fpreset           (CRTDLL.107)
1464  *
1465  * Reset the state of the floating point processor.
1466  */
1467 VOID __cdecl CRTDLL__fpreset(void)
1468 {
1469 #if defined(__GNUC__) && defined(__i386__)
1470   __asm__ __volatile__( "fninit" );
1471 #else
1472   FIXME(":Not Implemented!\n");
1473 #endif
1474 }
1475
1476
1477 /*********************************************************************
1478  *                  _isnan           (CRTDLL.164)
1479  *
1480  * Determine if an IEEE double is unrepresentable (NaN).
1481  *
1482  * PARAMS
1483  *   d [in]  Number to check.
1484  *
1485  * RETURNS
1486  *   Non zero if number is NaN.
1487  */
1488 INT __cdecl  CRTDLL__isnan(double d)
1489 {
1490   /* some implementations return -1 for true(glibc), crtdll returns 1.
1491    * Do the same, as the result may be used in calculations.
1492    */
1493   return isnan(d)?1:0;
1494 }
1495
1496
1497 /*********************************************************************
1498  *                  _purecall           (CRTDLL.249)
1499  *
1500  * Abort program after pure virtual function call.
1501  */
1502 VOID __cdecl CRTDLL__purecall(VOID)
1503 {
1504   CRTDLL__amsg_exit( 6025 );
1505 }
1506
1507
1508 /*********************************************************************
1509  *                  _div               (CRTDLL.358)
1510  *
1511  * Return the quotient and remainder of long integer division.
1512  */
1513 #ifdef __i386__
1514 /* Windows binary compatible - returns the struct in eax/edx. */
1515 LONGLONG __cdecl CRTDLL_div(INT x, INT y)
1516 {
1517   LONGLONG retVal;
1518   div_t dt = div(x,y);
1519   retVal = ((LONGLONG)dt.rem << 32) | dt.quot;
1520   return retVal;
1521 }
1522 #else
1523 /* Non-x86 cant run win32 apps so dont need binary compatibility */
1524 div_t __cdecl CRTDLL_div(INT x, INT y)
1525 {
1526   return div(x,y);
1527 }
1528 #endif /* __i386__ */
1529
1530
1531 /*********************************************************************
1532  *                  _ldiv               (CRTDLL.249)
1533  *
1534  * Return the quotient and remainder of long integer division.
1535  */
1536 #ifdef __i386__
1537 /* Windows binary compatible - returns the struct in eax/edx. */
1538 LONGLONG __cdecl CRTDLL_ldiv(LONG x, LONG y)
1539 {
1540   LONGLONG retVal;
1541   ldiv_t ldt = ldiv(x,y);
1542   retVal = ((LONGLONG)ldt.rem << 32) | ldt.quot;
1543   return retVal;
1544 }
1545 #else
1546 /* Non-x86 cant run win32 apps so dont need binary compatibility */
1547 ldiv_t __cdecl CRTDLL_ldiv(LONG x, LONG y)
1548 {
1549   return ldiv(x,y);
1550 }
1551 #endif /* __i386__ */
1552
1553
1554 /*********************************************************************
1555  *                  _y0               (CRTDLL.332)
1556  *
1557  */
1558 double __cdecl CRTDLL__y0(double x)
1559 {
1560   double retVal;
1561
1562   if (!finite(x)) CRTDLL_errno = EDOM;
1563   retVal  = y0(x);
1564   if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1565   {
1566     CRTDLL_errno = EDOM;
1567     retVal = sqrt(-1);
1568   }
1569   return retVal;
1570 }
1571
1572 /*********************************************************************
1573  *                  _y1               (CRTDLL.333)
1574  *
1575  */
1576 double __cdecl CRTDLL__y1(double x)
1577 {
1578   double retVal;
1579
1580   if (!finite(x)) CRTDLL_errno = EDOM;
1581   retVal  = y1(x);
1582   if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1583   {
1584     CRTDLL_errno = EDOM;
1585     retVal = sqrt(-1);
1586   }
1587   return retVal;
1588 }
1589
1590 /*********************************************************************
1591  *                  _yn               (CRTDLL.334)
1592  *
1593  */
1594 double __cdecl CRTDLL__yn(INT x, double y)
1595 {
1596   double retVal;
1597
1598   if (!finite(y)) CRTDLL_errno = EDOM;
1599   retVal  = yn(x,y);
1600   if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
1601   {
1602     CRTDLL_errno = EDOM;
1603     retVal = sqrt(-1);
1604   }
1605   return retVal;
1606 }