source: trunk/src/crtdll/crtdll_main.c@ 6645

Last change on this file since 6645 was 6645, checked in by bird, 24 years ago

Added $Id:$ keyword.

File size: 25.6 KB
Line 
1/* $Id: crtdll_main.c,v 1.2 2001-09-05 12:14:24 bird Exp $ */
2/*
3 * The C RunTime DLL
4 *
5 * Implements C run-time functionality as known from UNIX.
6 *
7 * Copyright 1996,1998 Marcus Meissner
8 * Copyright 1996 Jukka Iivonen
9 * Copyright 1997,2000 Uwe Bonnes
10 * Copyright 2000 Jon Griffiths
11 */
12
13/*
14Unresolved issues Uwe Bonnes 970904:
15- tested with ftp://ftp.remcomp.com/pub/remcomp/lcc-win32.zip, a C-Compiler
16 for Win32, based on lcc, from Jacob Navia
17UB 000416:
18- probably not thread safe
19*/
20
21/* NOTE: This file also implements the wcs* functions. They _ARE_ in
22 * the newer Linux libcs, but use 4 byte wide characters, so are unusable,
23 * since we need 2 byte wide characters. - Marcus Meissner, 981031
24 */
25
26#include <string.h>
27#include <errno.h>
28
29#include <float.h>
30#include <libc\locale.h>
31#include <setjmp.h>
32#include "signal.h"
33
34
35#include "crtdll.h"
36#include <ctype.h>
37#define __USE_ISOC9X 1 /* for isfinite */
38#include <math.h>
39#include <errno.h>
40#include <stdlib.h>
41#include "ntddk.h"
42#include "wingdi.h"
43#include "winuser.h"
44
45
46DEFAULT_DEBUG_CHANNEL(crtdll);
47
48
49UINT CRTDLL_argc_dll; /* CRTDLL.23 */
50LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
51LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
52UINT CRTDLL_basemajor_dll; /* CRTDLL.42 */
53UINT CRTDLL_baseminor_dll; /* CRTDLL.43 */
54UINT CRTDLL_baseversion_dll; /* CRTDLL.44 */
55UINT CRTDLL_commode_dll; /* CRTDLL.59 */
56LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
57UINT CRTDLL_fmode_dll; /* CRTDLL.104 */
58UINT CRTDLL_osmajor_dll; /* CRTDLL.241 */
59UINT CRTDLL_osminor_dll; /* CRTDLL.242 */
60UINT CRTDLL_osmode_dll; /* CRTDLL.243 */
61UINT CRTDLL_osver_dll; /* CRTDLL.244 */
62UINT CRTDLL_osversion_dll; /* CRTDLL.245 */
63UINT CRTDLL_winmajor_dll; /* CRTDLL.329 */
64UINT CRTDLL_winminor_dll; /* CRTDLL.330 */
65UINT CRTDLL_winver_dll; /* CRTDLL.331 */
66INT CRTDLL_doserrno = 0;
67INT CRTDLL_errno = 0;
68const INT CRTDLL__sys_nerr = 43;
69
70
71
72
73#define FS_OS2 unsigned short sel = RestoreOS2FS();
74#define FS_WIN32 SetFS(sel);
75
76
77/*********************************************************************
78 * CRTDLL_MainInit (CRTDLL.init)
79 */
80
81BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
82{
83 FS_OS2
84
85 // call i/o initializer in file.c
86 if (fdwReason == DLL_PROCESS_ATTACH)
87 {
88 __CRTDLL__init_io();
89 }
90
91 /*
92 PH 2000/11/21 this code doesn't look very useful
93
94 if (fdwReason == DLL_PROCESS_ATTACH) {
95 _fdopen(0,"r");
96 _fdopen(1,"w");
97 _fdopen(2,"w");
98 CRTDLL_hHeap = HeapCreate(0, 0x10000, 0);
99 }
100 else
101 if (fdwReason == DLL_PROCESS_DETACH) {
102 HeapDestroy(CRTDLL_hHeap);
103 CRTDLL_hHeap = 0;
104 }
105 */
106
107 FS_WIN32
108 return TRUE;
109}
110
111
112/* INTERNAL: Set the crt and dos errno's from the OS error given. */
113void __CRTDLL__set_errno(ULONG err)
114{
115 /* FIXME: not MT safe */
116 CRTDLL_doserrno = err;
117
118 switch(err)
119 {
120#define ERR_CASE(oserr) case oserr:
121#define ERR_MAPS(oserr,crterr) case oserr:CRTDLL_errno = crterr;break;
122 ERR_CASE(ERROR_ACCESS_DENIED)
123 ERR_CASE(ERROR_NETWORK_ACCESS_DENIED)
124 ERR_CASE(ERROR_CANNOT_MAKE)
125 ERR_CASE(ERROR_SEEK_ON_DEVICE)
126 ERR_CASE(ERROR_LOCK_FAILED)
127 ERR_CASE(ERROR_FAIL_I24)
128 ERR_CASE(ERROR_CURRENT_DIRECTORY)
129 ERR_CASE(ERROR_DRIVE_LOCKED)
130 ERR_CASE(ERROR_NOT_LOCKED)
131 ERR_CASE(ERROR_INVALID_ACCESS)
132 ERR_MAPS(ERROR_LOCK_VIOLATION, EACCES);
133 ERR_CASE(ERROR_FILE_NOT_FOUND)
134 ERR_CASE(ERROR_NO_MORE_FILES)
135 ERR_CASE(ERROR_BAD_PATHNAME)
136 ERR_CASE(ERROR_BAD_NETPATH)
137 ERR_CASE(ERROR_INVALID_DRIVE)
138 ERR_CASE(ERROR_BAD_NET_NAME)
139 ERR_CASE(ERROR_FILENAME_EXCED_RANGE)
140 ERR_MAPS(ERROR_PATH_NOT_FOUND, ENOENT);
141/* @@@PH ERR_MAPS(ERROR_IO_DEVICE, EIO); */
142 ERR_MAPS(ERROR_BAD_FORMAT, ENOEXEC);
143 ERR_MAPS(ERROR_INVALID_HANDLE, EBADF);
144 ERR_CASE(ERROR_OUTOFMEMORY)
145 ERR_CASE(ERROR_INVALID_BLOCK)
146 ERR_CASE(ERROR_NOT_ENOUGH_QUOTA);
147 ERR_MAPS(ERROR_ARENA_TRASHED, ENOMEM);
148/* @@@PH ERR_MAPS(ERROR_BUSY, EBUSY); */
149 ERR_CASE(ERROR_ALREADY_EXISTS)
150 ERR_MAPS(ERROR_FILE_EXISTS, EEXIST);
151/* @@@PH ERR_MAPS(ERROR_BAD_DEVICE, ENODEV); */
152 ERR_MAPS(ERROR_TOO_MANY_OPEN_FILES, EMFILE);
153 ERR_MAPS(ERROR_DISK_FULL, ENOSPC);
154/* @@@PH ERR_MAPS(ERROR_BROKEN_PIPE, EPIPE); */
155/* @@@PH ERR_MAPS(ERROR_POSSIBLE_DEADLOCK, EDEADLK); */
156/* @@@PH ERR_MAPS(ERROR_DIR_NOT_EMPTY, ENOTEMPTY); */
157 ERR_MAPS(ERROR_BAD_ENVIRONMENT, E2BIG);
158 ERR_CASE(ERROR_WAIT_NO_CHILDREN)
159 ERR_MAPS(ERROR_CHILD_NOT_COMPLETE, ECHILD);
160 ERR_CASE(ERROR_NO_PROC_SLOTS)
161 ERR_CASE(ERROR_MAX_THRDS_REACHED)
162 ERR_MAPS(ERROR_NESTING_NOT_ALLOWED, EAGAIN);
163 default:
164 /* Remaining cases map to EINVAL */
165 /* FIXME: may be missing some errors above */
166 CRTDLL_errno = EINVAL;
167 }
168}
169
170
171/*********************************************************************
172 * _GetMainArgs (CRTDLL.022)
173 */
174LPSTR * CDECL CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
175 LPSTR *environ,DWORD flag)
176{
177 char *cmdline;
178 char **xargv;
179 int xargc,end,last_arg,afterlastspace;
180 DWORD version;
181
182 TRACE("(%p,%p,%p,%ld).\n",
183 argc,argv,environ,flag
184 );
185
186 if (CRTDLL_acmdln_dll != NULL)
187 HeapFree(GetProcessHeap(), 0, CRTDLL_acmdln_dll);
188
189 CRTDLL_acmdln_dll = cmdline = CRTDLL__strdup( GetCommandLineA() );
190 TRACE("got '%s'\n", cmdline);
191
192 version = GetVersion();
193 CRTDLL_osver_dll = version >> 16;
194 CRTDLL_winminor_dll = version & 0xFF;
195 CRTDLL_winmajor_dll = (version>>8) & 0xFF;
196 CRTDLL_baseversion_dll = version >> 16;
197 CRTDLL_winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
198 CRTDLL_baseminor_dll = (version >> 16) & 0xFF;
199 CRTDLL_basemajor_dll = (version >> 24) & 0xFF;
200 CRTDLL_osversion_dll = version & 0xFFFF;
201 CRTDLL_osminor_dll = version & 0xFF;
202 CRTDLL_osmajor_dll = (version>>8) & 0xFF;
203
204 /* missing threading init */
205
206 end=0;last_arg=0;xargv=NULL;xargc=0;afterlastspace=0;
207 while (1)
208 {
209 if ((cmdline[end]==' ') || (cmdline[end]=='\0'))
210 {
211 if (cmdline[end]=='\0')
212 last_arg=1;
213 else
214 cmdline[end]='\0';
215 /* alloc xargc + NULL entry */
216 xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
217 sizeof(char*)*(xargc+1));
218 if (strlen(cmdline+afterlastspace))
219 {
220 xargv[xargc] = CRTDLL__strdup(cmdline+afterlastspace);
221 xargc++;
222 if (!last_arg) /* need to seek to the next arg ? */
223 {
224 end++;
225 while (cmdline[end]==' ')
226 end++;
227 }
228 afterlastspace=end;
229 }
230 else
231 {
232 xargv[xargc] = NULL; /* the last entry is NULL */
233 break;
234 }
235 }
236 else
237 end++;
238 }
239 CRTDLL_argc_dll = xargc;
240 *argc = xargc;
241 CRTDLL_argv_dll = xargv;
242 *argv = xargv;
243
244 TRACE("found %d arguments\n",
245 CRTDLL_argc_dll);
246 CRTDLL_environ_dll = *environ = GetEnvironmentStringsA();
247 return environ;
248}
249
250
251/*********************************************************************
252 * _initterm (CRTDLL.135)
253 */
254DWORD CDECL CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
255{
256 _INITTERMFUN *current;
257
258 TRACE("(%p,%p)\n",start,end);
259 current=start;
260 while (current<end) {
261 if (*current) (*current)();
262 current++;
263 }
264 return 0;
265}
266
267
268/*******************************************************************
269 * _global_unwind2 (CRTDLL.129)
270 */
271void CDECL CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
272{
273 RtlUnwind( frame, 0, NULL, 0 );
274}
275
276
277/*******************************************************************
278 * _local_unwind2 (CRTDLL.173)
279 */
280void CDECL CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
281{
282 dprintf2(("CRTDLL: _local_unwind2\n"));
283 TRACE("(%p,%ld)\n",endframe,nr);
284}
285
286
287/*********************************************************************
288 * _beep (CRTDLL.045)
289 *
290 * Output a tone using the PC speaker.
291 *
292 * PARAMS
293 * freq [in] Frequency of the tone
294 *
295 * duration [in] Length of time the tone should sound
296 *
297 * RETURNS
298 * None.
299 */
300void CDECL CRTDLL__beep( UINT freq, UINT duration)
301{
302 TRACE(":Freq %d, Duration %d\n",freq,duration);
303 Beep(freq, duration);
304}
305
306
307/*********************************************************************
308 * rand (CRTDLL.446)
309 */
310INT CDECL CRTDLL_rand()
311{
312 return (rand() & CRTDLL_RAND_MAX);
313}
314
315
316/*********************************************************************
317 * _rotl (CRTDLL.259)
318 */
319UINT CDECL CRTDLL__rotl(UINT x,INT shift)
320{
321 // return (_rotl(value, shift));
322
323 shift &= 31;
324 return (x << shift) | (x >> (32-shift));
325}
326
327
328/*********************************************************************
329 * _lrotl (CRTDLL.175)
330 */
331DWORD CDECL CRTDLL__lrotl(DWORD x,INT shift)
332{
333 // return (_lrotl(value, shift));
334
335 shift &= 31;
336 return (x << shift) | (x >> (32-shift));
337}
338
339
340/*********************************************************************
341 * _lrotr (CRTDLL.176)
342 */
343DWORD CDECL CRTDLL__lrotr(DWORD x,INT shift)
344{
345 // return (_lrotr(value, shift));
346
347 shift &= 0x1f;
348 return (x >> shift) | (x << (32-shift));
349}
350
351
352/*********************************************************************
353 * _rotr (CRTDLL.258)
354 */
355DWORD CDECL CRTDLL__rotr(UINT x,INT shift)
356{
357 // return (_rotr(value, shift));
358
359 shift &= 0x1f;
360 return (x >> shift) | (x << (32-shift));
361}
362
363
364/*********************************************************************
365 * vswprintf (CRTDLL.501)
366 */
367INT CDECL CRTDLL_vswprintf( LPWSTR buffer, LPCWSTR spec, va_list args )
368{
369 // return (vswprintf(s, t, format, arg));
370
371 return wvsprintfW( buffer, spec, args );
372}
373
374
375/*********************************************************************
376 * longjmp (CRTDLL.426)
377 */
378VOID CDECL CRTDLL_longjmp(jmp_buf env, int val)
379{
380 FIXME("CRTDLL_longjmp semistub, expect crash\n");
381 longjmp(env, val);
382}
383
384
385/*********************************************************************
386 * setlocale (CRTDLL.453)
387 */
388LPSTR CDECL CRTDLL_setlocale(INT category,LPCSTR locale)
389{
390 return (setlocale(category, locale));
391
392 /*
393 LPSTR categorystr;
394
395 switch (category) {
396 case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
397 case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
398 case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
399 case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
400 case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
401 case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
402 default: categorystr = "UNKNOWN?";break;
403 }
404 FIXME("(%s,%s),stub!\n",categorystr,locale);
405 return "C";
406 */
407}
408
409
410/*********************************************************************
411 * _isctype (CRTDLL.138)
412 */
413BOOL CDECL CRTDLL__isctype(CHAR x,CHAR type)
414{
415 if ((type & CRTDLL_SPACE) && isspace(x))
416 return TRUE;
417 if ((type & CRTDLL_PUNCT) && ispunct(x))
418 return TRUE;
419 if ((type & CRTDLL_LOWER) && islower(x))
420 return TRUE;
421 if ((type & CRTDLL_UPPER) && isupper(x))
422 return TRUE;
423 if ((type & CRTDLL_ALPHA) && isalpha(x))
424 return TRUE;
425 if ((type & CRTDLL_DIGIT) && isdigit(x))
426 return TRUE;
427 if ((type & CRTDLL_CONTROL) && iscntrl(x))
428 return TRUE;
429 /* check CRTDLL_LEADBYTE */
430 return FALSE;
431}
432
433
434/*********************************************************************
435 * _fullpath (CRTDLL.114)
436 */
437LPSTR CDECL CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT size)
438{
439 // return (_fullpath(buf, path, size));
440
441 if (!buf)
442 {
443 size = 256;
444 if(!(buf = CRTDLL_malloc(size))) return NULL;
445 }
446 if (!GetFullPathNameA( name, size, buf, NULL )) return NULL;
447 TRACE("CRTDLL_fullpath got %s\n",buf);
448 return buf;
449}
450
451
452/*********************************************************************
453 * _splitpath (CRTDLL.279)
454 */
455VOID CDECL CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
456{
457 // _splitpath( path, drive, dir, fname, ext);
458
459 /* drive includes :
460 directory includes leading and trailing (forward and backward slashes)
461 filename without dot and slashes
462 extension with leading dot
463 */
464 char * drivechar,*dirchar,*namechar;
465
466 TRACE("CRTDLL__splitpath got %s\n",path);
467
468 drivechar = strchr(path,':');
469 dirchar = strrchr(path,'/');
470 namechar = strrchr(path,'\\');
471 dirchar = max(dirchar,namechar);
472 if (dirchar)
473 namechar = strrchr(dirchar,'.');
474 else
475 namechar = strrchr(path,'.');
476
477 if (drive)
478 {
479 *drive = 0x00;
480 if (drivechar)
481 {
482 strncat(drive,path,drivechar-path+1);
483 path = drivechar+1;
484 }
485 }
486 if (directory)
487 {
488 *directory = 0x00;
489 if (dirchar)
490 {
491 strncat(directory,path,dirchar-path+1);
492 path = dirchar+1;
493 }
494 }
495 if (filename)
496 {
497 *filename = 0x00;
498 if (namechar)
499 {
500 strncat(filename,path,namechar-path);
501 if (extension)
502 {
503 *extension = 0x00;
504 strcat(extension,namechar);
505 }
506 }
507 }
508
509 TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
510}
511
512
513/*********************************************************************
514 * _makepath (CRTDLL.182)
515 */
516
517VOID CDECL CRTDLL__makepath(LPSTR path, LPCSTR drive,
518 LPCSTR directory, LPCSTR filename,
519 LPCSTR extension )
520{
521 // _makepath(path, drive, dir, fname, ext);
522
523 char ch;
524 TRACE("CRTDLL__makepath got %s %s %s %s\n", drive, directory,
525 filename, extension);
526
527 if ( !path )
528 return;
529
530 path[0] = 0;
531 if (drive && drive[0])
532 {
533 path[0] = drive[0];
534 path[1] = ':';
535 path[2] = 0;
536 }
537 if (directory && directory[0])
538 {
539 strcat(path, directory);
540 ch = path[strlen(path)-1];
541 if (ch != '/' && ch != '\\')
542 strcat(path,"\\");
543 }
544 if (filename && filename[0])
545 {
546 strcat(path, filename);
547 if (extension && extension[0])
548 {
549 if ( extension[0] != '.' ) {
550 strcat(path,".");
551 }
552 strcat(path,extension);
553 }
554 }
555
556 TRACE("CRTDLL__makepath returns %s\n",path);
557}
558
559
560/*********************************************************************
561 * _errno (CRTDLL.52)
562 * Return the address of the CRT errno (Not the libc errno).
563 * @@@PH Note: veeeery strange ...
564 * BUGS
565 * Not MT safe.
566 */
567LPINT CDECL CRTDLL__errno( VOID )
568{
569 // return (_errno());
570
571 return &CRTDLL_errno;
572}
573
574
575/*********************************************************************
576 * __doserrno (CRTDLL.26)
577 *
578 * Return the address of the DOS errno (holding the last OS error).
579 * @@@PH Note: veeeery strange ...
580 * BUGS
581 * Not MT safe.
582 */
583LPINT CDECL CRTDLL___doserrno( VOID )
584{
585 // return (__doserrno());
586
587 return &CRTDLL_doserrno;
588}
589
590
591/**********************************************************************
592 * _strerror (CRTDLL.284)
593 *
594 * Return a formatted system error message.
595 *
596 * NOTES
597 * The caller does not own the string returned.
598 */
599extern int sprintf(char *str, const char *format, ...);
600
601LPSTR CDECL CRTDLL__strerror (LPCSTR err)
602{
603 // return (_strerror((char*)s));
604
605 static char strerrbuff[256];
606 sprintf(strerrbuff,"%s: %s\n",err,CRTDLL_strerror(CRTDLL_errno));
607 return strerrbuff;
608}
609
610
611/*********************************************************************
612 * perror (CRTDLL.435)
613 *
614 * Print a formatted system error message to stderr.
615 */
616VOID CDECL CRTDLL_perror (LPCSTR err)
617{
618 // perror( s );
619
620 char *err_str = CRTDLL_strerror(CRTDLL_errno);
621 CRTDLL_fprintf(CRTDLL_stderr,"%s: %s\n",err,err_str);
622 CRTDLL_free(err_str);
623}
624
625
626/*********************************************************************
627 * strerror (CRTDLL.465)
628 *
629 * Return the text of an error.
630 *
631 * NOTES
632 * The caller does not own the string returned.
633 */
634extern char *strerror(int errnum);
635
636LPSTR CDECL CRTDLL_strerror (INT err)
637{
638 return strerror(err);
639}
640
641
642/*********************************************************************
643 * signal (CRTDLL.455)
644 */
645LPVOID CDECL CRTDLL_signal(INT sig, sig_handler_type ptr)
646{
647 //return (signal(sig, ptr));
648
649 FIXME("(%d %p):stub.\n", sig, ptr);
650 return (void*)-1;
651}
652
653
654/*********************************************************************
655 * _sleep (CRTDLL.267)
656 */
657VOID CDECL CRTDLL__sleep(ULONG timeout)
658{
659 TRACE("CRTDLL__sleep for %ld milliseconds\n",timeout);
660 Sleep((timeout)?timeout:1);
661}
662
663
664/*********************************************************************
665 * getenv (CRTDLL.437)
666 */
667LPSTR CDECL CRTDLL_getenv(LPCSTR name)
668{
669 // return (getenv(name));
670
671 LPSTR environ = GetEnvironmentStringsA();
672 LPSTR pp,pos = NULL;
673 unsigned int length;
674
675 for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
676 {
677 pos =strchr(pp,'=');
678 if (pos)
679 length = pos -pp;
680 else
681 length = strlen(pp);
682 if (!strncmp(pp,name,length)) break;
683 }
684 if ((pp)&& (pos))
685 {
686 pp = pos+1;
687 TRACE("got %s\n",pp);
688 }
689 FreeEnvironmentStringsA( environ );
690 return pp;
691}
692
693
694/*********************************************************************
695 * _except_handler2 (CRTDLL.78)
696 */
697INT CDECL CRTDLL__except_handler2 (
698 PEXCEPTION_RECORD rec,
699 PEXCEPTION_FRAME frame,
700 PCONTEXT context,
701 PEXCEPTION_FRAME *dispatcher)
702{
703 FIXME ("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
704 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
705 frame->Handler, context, dispatcher);
706 return ExceptionContinueSearch;
707}
708
709
710/*********************************************************************
711 * __isascii (CRTDLL.028)
712 *
713 */
714INT CDECL CRTDLL___isascii(INT c)
715{
716 return isascii(c);
717}
718
719
720/*********************************************************************
721 * __toascii (CRTDLL.035)
722 *
723 */
724INT CDECL CRTDLL___toascii(INT c)
725{
726 // return (_toascii(c));
727
728 return c & 0x7f;
729}
730
731
732/*********************************************************************
733 * iswascii (CRTDLL.404)
734 *
735 */
736INT CDECL CRTDLL_iswascii(LONG c)
737{
738 // return (!((c)&(~0x7f)));
739 return ((unsigned)c < 0x80);
740}
741
742
743/*********************************************************************
744 * __iscsym (CRTDLL.029)
745 *
746 * Is a character valid in a C identifier (a-Z,0-9,_).
747 *
748 * PARAMS
749 * c [I]: Character to check
750 *
751 * RETURNS
752 * Non zero if c is valid as t a C identifier.
753 */
754INT CDECL CRTDLL___iscsym(LONG c)
755{
756 // return (_iscsym(c));
757
758 return (isalnum(c) || c == '_');
759}
760
761
762/*********************************************************************
763 * __iscsymf (CRTDLL.030)
764 *
765 * Is a character valid as the first letter in a C identifier (a-Z,_).
766 *
767 * PARAMS
768 * c [in] Character to check
769 *
770 * RETURNS
771 * Non zero if c is valid as the first letter in a C identifier.
772 */
773INT CDECL CRTDLL___iscsymf(LONG c)
774{
775 // return (_iscsymf(c));
776
777 return (isalpha(c) || c == '_');
778}
779
780
781/*********************************************************************
782 * _loaddll (CRTDLL.171)
783 *
784 * Get a handle to a DLL in memory. The DLL is loaded if it is not already.
785 *
786 * PARAMS
787 * dll [in] Name of DLL to load.
788 *
789 * RETURNS
790 * Success: A handle to the loaded DLL.
791 *
792 * Failure: FIXME.
793 */
794INT CDECL CRTDLL__loaddll(LPSTR dllname)
795{
796 return LoadLibraryA(dllname);
797}
798
799
800/*********************************************************************
801 * _unloaddll (CRTDLL.313)
802 *
803 * Free reference to a DLL handle from loaddll().
804 *
805 * PARAMS
806 * dll [in] Handle to free.
807 *
808 * RETURNS
809 * Success: 0.
810 *
811 * Failure: Error number.
812 */
813INT CDECL CRTDLL__unloaddll(HANDLE dll)
814{
815 INT err;
816 if (FreeLibrary(dll))
817 return 0;
818 err = GetLastError();
819 __CRTDLL__set_errno(err);
820 return err;
821}
822
823
824/*********************************************************************
825 * _lsearch (CRTDLL.177)
826 *
827 * Linear search of an array of elements. Adds the item to the array if
828 * not found.
829 *
830 * PARAMS
831 * match [in] Pointer to element to match
832 * start [in] Pointer to start of search memory
833 * array_size [in] Length of search array (element count)
834 * elem_size [in] Size of each element in memory
835 * comp_func [in] Pointer to comparason function (like qsort()).
836 *
837 * RETURNS
838 * Pointer to the location where element was found or added.
839 */
840LPVOID CDECL CRTDLL__lsearch(LPVOID match,LPVOID start, LPUINT array_size,
841 UINT elem_size, comp_func cf)
842{
843 LPBYTE pStart = (LPBYTE)start;
844 UINT size = *array_size;
845 if (size)
846 do
847 {
848 if (cf((LPVOID*)match, (LPVOID*)pStart) == 0)
849 return pStart; /* found */
850 pStart += elem_size;
851 } while (--size);
852
853 /* not found, add to end */
854 memcpy(pStart, match, elem_size);
855 array_size[0]++;
856 return pStart;
857}
858
859
860/*********************************************************************
861 * _itow (CRTDLL.164)
862 *
863 * Convert an integer to a wide char string.
864 */
865/* @@@PH extern LPSTR CDECL _itoa( long , LPSTR , INT);*/ /* ntdll */
866
867WCHAR* CDECL CRTDLL__itow(INT value,WCHAR* out,INT base)
868{
869 char buff[64]; /* FIXME: Whats the maximum buffer size for INT_MAX? */
870
871 _itoa(value, buff, base);
872 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
873 return out;
874}
875
876
877/*********************************************************************
878 * _ltow (CRTDLL.??)
879 *
880 * Convert a long to a wide char string.
881 */
882/* @@@PH extern LPSTR CDECL _ltoa( long , LPSTR , INT); */ /* ntdll */
883
884WCHAR* CDECL CRTDLL__ltow(LONG value,WCHAR* out,INT base)
885{
886 char buff[64]; /* FIXME: Whats the maximum buffer size for LONG_MAX? */
887
888 _ltoa(value, buff, base);
889 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
890 return out;
891}
892
893
894/*********************************************************************
895 * _ultow (CRTDLL.??)
896 *
897 * Convert an unsigned long to a wide char string.
898 */
899/* @@@PH extern LPSTR CDECL _ultoa( long , LPSTR , INT); */ /* ntdll */
900
901WCHAR* CDECL CRTDLL__ultow(ULONG value,WCHAR* out,INT base)
902{
903 char buff[64]; /* FIXME: Whats the maximum buffer size for ULONG_MAX? */
904
905 _ultoa(value, buff, base);
906 MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
907 return out;
908}
909
910
911/*********************************************************************
912 * _toupper (CRTDLL.489)
913 */
914CHAR CDECL CRTDLL__toupper(CHAR c)
915{
916 // return (_toupper(n));
917
918 return toupper(c);
919}
920
921
922/*********************************************************************
923 * _tolower (CRTDLL.490)
924 */
925CHAR CDECL CRTDLL__tolower(CHAR c)
926{
927 // return (_tolower(n));
928
929 return tolower(c);
930}
931
932
933/* FP functions */
934
935/*********************************************************************
936 * _cabs (CRTDLL.048)
937 *
938 * Return the absolue value of a complex number.
939 *
940 * PARAMS
941 * c [in] Structure containing real and imaginary parts of complex number.
942 *
943 * RETURNS
944 * Absolute value of complex number (always a positive real number).
945 */
946double CDECL CRTDLL__cabs(struct __CRTDLL_complex c)
947{
948 // return (_cabs(c));
949
950 return sqrt(c.real * c.real + c.imaginary * c.imaginary);
951}
952
953
954/*********************************************************************
955 * _chgsign (CRTDLL.053)
956 *
957 * Change the sign of an IEEE double.
958 *
959 * PARAMS
960 * d [in] Number to invert.
961 *
962 * RETURNS
963 * Number with sign inverted.
964 */
965double CDECL CRTDLL__chgsign(double d)
966{
967 /* FIXME: +-infinity,Nan not tested */
968 return -d;
969}
970
971
972/*********************************************************************
973 * _copysign (CRTDLL.062)
974 *
975 * Return the number x with the sign of y.
976 */
977double CDECL CRTDLL__copysign(double x, double y)
978{
979 /* FIXME: Behaviour for Nan/Inf etc? */
980 if (y < 0.0)
981 return x < 0.0 ? x : -x;
982
983 return x < 0.0 ? -x : x;
984}
985
986
987/*********************************************************************
988 * _finite (CRTDLL.101)
989 *
990 * Determine if an IEEE double is finite (i.e. not +/- Infinity).
991 *
992 * PARAMS
993 * d [in] Number to check.
994 *
995 * RETURNS
996 * Non zero if number is finite.
997 */
998INT CDECL CRTDLL__finite(double d)
999{
1000 return 0;
1001 //@@@PH return (isfinite(d)?1:0); /* See comment for CRTDLL__isnan() */
1002}
1003
1004
1005/*********************************************************************
1006 * _fpreset (CRTDLL.107)
1007 *
1008 * Reset the state of the floating point processor.
1009 *
1010 * PARAMS
1011 * None.
1012 *
1013 * RETURNS
1014 * None.
1015 *
1016 * BUGS
1017 * Unimplemented.
1018 */
1019VOID CDECL CRTDLL__fpreset(void)
1020{
1021 //FIXME(":stub!\n");
1022 _fpreset();
1023}
1024
1025
1026/*********************************************************************
1027 * _isnan (CRTDLL.164)
1028 *
1029 * Determine if an IEEE double is unrepresentable (NaN).
1030 *
1031 * PARAMS
1032 * d [in] Number to check.
1033 *
1034 * RETURNS
1035 * Non zero if number is NaN.
1036 */
1037INT CDECL CRTDLL__isnan(double d)
1038{
1039 /* some implementations return -1 for true(glibc), crtdll returns 1.
1040 * Do the same, as the result may be used in calculations.
1041 */
1042 return 0;
1043 //@@@PH return isnan(d)?1:0;
1044}
Note: See TracBrowser for help on using the repository browser.