CRT personalizada

Iniciado por 85, 26 Marzo 2013, 16:21 PM

0 Miembros y 1 Visitante están viendo este tema.

85

Hola, estaba leyendo este texto:
Citar
5) make your own CRT

  MUCH easier than you might think... what do you need from a runtime? to allocate/deallocate
  mem? to print to the console?

  look up the functions required to allocate memory from windows...

  now just have some functions that set needed globals:

  HANDLE g_hHeap = 0;

  extern "C" BOOL crt_initialize() { return (g_hHeap = HeapCreate(0, 0, 0))); }
  extern "C" BOOL crt_uninitialize() { return HeapDestroy(g_hHeap)); }

  you can now, if you choose, override the default CRT entry's name:

  extern "C" int mainCRTStartup()
  {
     crt_initialize();
     // maybe get the arguments here with GetCommandLine()
     main();//maybe send args here
     return 0;
  }

  so how do you do malloc()/free() ? how do you do new/delete? it's as simple as passing the
  requested sizes to the OS functions along with the heap handle made during the initialization

  extern "C" void * malloc(unsigned int size) { return HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, size); }
  extern "C" void free(void * p) { HeapFree(g_hHeap, 0, p); }

  void * __cdecl operator new(unsigned int size) { return HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, size); }
  void __cdecl operator delete(void *p) { HeapFree(g_hHeap, 0, p); }

  hopefully you can figure out the rest... especially how your crt entry should acquire and
  supply needed parameters to your main() or winmain()

6) bypass the normal CRT

  if you don't want to write a CRT, but also don't want the cruft that comes with the normal CRT,
  just specify that the linker should jump to your code first, NOT the crt

  /ENTRY:yourfunction

Y buscando información encontré algunas cosas interesantes, por ejemplo 2 proyectos de CRT propias, más que el otro estuve mirando el más reciente del 2010, que se llama 'minicrt'.
Me parece que les puede interesar a algunos, porque en el proyecto se puede encontrar el código de muchas implementaciones de funciones de C.
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e6f222d7-8e20-4d4a-8a6f-b72ade3661ac/
http://www.benshoof.org/blog/minicrt/
http://www.wheaty.net/
http://www.benshoof.org/blog/archive/
http://www.wheaty.net/downloads.htm

Se pueden encontrar versiones de las funciones originales que cumplen con los standards de C, hay implementaciones de algunas funciones que a mi por ejemplo me interesaban crear implementaciones personalizadas de ellas, atoi, strtok, y muchas otras

por ejemplo atoi

//==========================================
// minicrt - Chris Benshoof 2009
// atoi(), modified from
// http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/atoi.c.htm
//==========================================
#include "libctiny.h"

extern "C" int __cdecl atoi(const char *String)
{
   int Value = 0, Digit;
   int c;

   while ((c = *String++) != '\0') {

       if (c >= '0' && c <= '9')
           Digit = (c - '0');
       else
           break;

       Value = (Value * 10) + Digit;
   }

   return Value;
}


aparte es un proyecto no tan antiguo, dice que es del 2010.
El otro si es del 2000.

saludos
Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/

rir3760

Cita de: 85 en 26 Marzo 2013, 16:21 PMSe pueden encontrar versiones de las funciones originales que cumplen con los standards de C, hay implementaciones de algunas funciones que a mi por ejemplo me interesaban crear implementaciones personalizadas de ellas, atoi, strtok, y muchas otras
La especificación de strtok según la referencia sobre C90 de P. J. Plauger (un poco mas estricta que la estándar) es:
Citarstrtok

char *strtok(char *s1, const char *s2);

If s1 is not a null pointer, the function begins a search of the string s1. Otherwise, it begins a search of the string whose address was last stored in an internal static-duration object on an earlier call to the function, as described below. The search proceeds as follows:

1. The function searches the string for begin, the address of the first element that equals none of the elements of the string s2 (a set of token separators). It considers the terminating null character as part of the search string only.

2. If the search does not find an element, the function stores the address of the terminating null character in the internal static-duration object (so that a subsequent search beginning with that address will fail) and returns a null pointer. Otherwise, the function searches from begin for end, the address of the first element that equals any one of the elements of the string s2. It again considers the terminating null character as part of the search string only.

3. If the search does not find an element, the function stores the address of the terminating null character in the internal static-duration object. Otherwise, it stores a null character in the element whose address is end. Then it stores the address of the next element after end in the internal static-duration object (so that a subsequent search beginning with that address will continue with the remaining elements of the string) and returns begin.

Esta se puede implementar utilizando las funciones strspn y strcspn (prototipos en <string.h>). Un programa de ejemplo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *fn_strtok(char *str, char const *set);

int main(void)
{
   char str[] = "?a???b,,,#c";

   printf("\"%s\"\n", strtok(str, "?"));
   printf("\"%s\"\n", strtok(NULL, ","));
   printf("\"%s\"\n", strtok(NULL, "#,"));
   printf("%p\n", (void *) strtok(NULL, "?"));
   
   strcpy(str, "?a???b,,,#c");
   
   printf("\"%s\"\n", fn_strtok(str, "?"));
   printf("\"%s\"\n", fn_strtok(NULL, ","));
   printf("\"%s\"\n", fn_strtok(NULL, "#,"));
   printf("%p\n", (void *) fn_strtok(NULL, "?"));
   
   return EXIT_SUCCESS;
}

char *fn_strtok(char *str, char const *set)
{
   static char *p;
   
   if (str == NULL)
      str = p;
   
   p = str += strspn(str, set);
   if (*str == '\0')
      str = NULL;
   else {
      p += strcspn(p, set);
     
      if (*p != '\0')
         *p++ = '\0';
   }
   
   return str;
}


Y su salida es:
"a"
"??b"
"c"
(null)
"a"
"??b"
"c"
(null)


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

85

#2
Yo tenía estas pero esa que postiaste está mucho mejor  ;-)

char* mi_strtok(char* str, const char* delimiters){

printf("mi_strtok\n");
system("pause");
static char* last;
char* tok;

/* pick up from previous stopping point, if told to do so */
if (str == NULL && (str = last) == NULL) return NULL;

/* skip initial delimiters to find start of token */
tok = str + strspn(str, delimiters);

/* skip over non-delimiters to find end of token */
str = tok + strcspn(tok, delimiters);

/*
* Save state for next call, and return token. If there
* is no token, both *tok and *s will be '\0'. If there
* is one token that is ended with '\0', *s will be '\0'.
* (If there are trailing delimiters, we will skip them
* later.)
*/
last=*str=='\0' ?NULL:str+1;
return *tok=='\0' ?NULL:tok;
}



char* mi_strtok2(char* input, const char* tokenizer)
{
printf("mi_strtok2\n");
system("pause");
static char* memorizeInput;
bool tokenFound = false;
if(input != NULL)
memorizeInput = input;
else
input = memorizeInput;
if(!(*memorizeInput))
return NULL;
while(*memorizeInput)
{
for(int i=0; i<(int)(strlen(tokenizer)&&!tokenFound);i++){
 
if(*memorizeInput == tokenizer[i])
{
*memorizeInput = 0;
tokenFound = true;
}
}
if(tokenFound)
{
memorizeInput++;
break;
}
memorizeInput++;
}

return input;
}



char* lastPos = 0;
char token[100];

char* mi_strtok3(char* str, const char* delim)
{
printf("mi_strtok3\n");
system("pause");
if(!str && !lastPos) return 0;
if(!delim) return 0;
if(str)
lastPos = str;
int delim_len = strlen(delim);
char* strt_ptr = lastPos;
int count = 0;
while(*lastPos != '\0')
{
bool is_found = false;
for(int y=0; y<delim_len; y++)
{
if(*(delim + y) == *lastPos)
is_found = true;
}
lastPos++;
if(is_found) break;
count++;
}

if(*lastPos == '\0')
lastPos = 0;

//added to remove empty ones
if(!count)
return mi_strtok3(0, delim);
//
for(int x=0; x<count; x++)
token[x] = *(strt_ptr + x);
token[count] = '\0';
return token;
}


habría que probar con el ejemplo de aquí:
http://www.cplusplus.com/reference/cstring/strtok/
:rolleyes:

Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/

BloodSharp

Si les sirve, encontré un par de funciones de manejo de strings unicode...

/***
*wcscat.c - contains wcscat() and wcscpy()
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       wcscat() appends one wchar_t string onto another.
*       wcscpy() copies one wchar_t string into another.
*
*       wcscat() concatenates (appends) a copy of the source string to the
*       end of the destination string, returning the destination string.
*       Strings are wide-character strings.
*
*       wcscpy() copies the source string to the spot pointed to be
*       the destination string, returning the destination string.
*       Strings are wide-character strings.
*
*******************************************************************************/


#include <string.h>

/***
*wchar_t *wcscat(dst, src) - concatenate (append) one wchar_t string to another
*
*Purpose:
*       Concatenates src onto the end of dest.  Assumes enough
*       space in dest.
*
*Entry:
*       wchar_t *dst - wchar_t string to which "src" is to be appended
*       const wchar_t *src - wchar_t string to be appended to the end of "dst"
*
*Exit:
*       The address of "dst"
*
*Exceptions:
*
*******************************************************************************/

wchar_t * __cdecl wcscat (
        wchar_t * dst,
        const wchar_t * src
        )
{
        wchar_t * cp = dst;

        while( *cp )
                cp++;                   /* find end of dst */

        while( *cp++ = *src++ ) ;       /* Copy src to end of dst */

        return( dst );                  /* return dst */

}


/***
*wchar_t *wcscpy(dst, src) - copy one wchar_t string over another
*
*Purpose:
*       Copies the wchar_t string src into the spot specified by
*       dest; assumes enough room.
*
*Entry:
*       wchar_t * dst - wchar_t string over which "src" is to be copied
*       const wchar_t * src - wchar_t string to be copied over "dst"
*
*Exit:
*       The address of "dst"
*
*Exceptions:
*******************************************************************************/

wchar_t * __cdecl wcscpy(wchar_t * dst, const wchar_t * src)
{
        wchar_t * cp = dst;

        while( *cp++ = *src++ )
                ;               /* Copy src over dst */

        return( dst );
}



/***
*wcschr.c - search a wchar_t string for a given wchar_t character
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines wcschr() - search a wchar_t string for a wchar_t character
*
*******************************************************************************/


#include <string.h>

/***
*wchar_t *wcschr(string, c) - search a string for a wchar_t character
*
*Purpose:
*       Searches a wchar_t string for a given wchar_t character,
*       which may be the null character L'\0'.
*
*Entry:
*       wchar_t *string - wchar_t string to search in
*       wchar_t c - wchar_t character to search for
*
*Exit:
*       returns pointer to the first occurence of c in string
*       returns NULL if c does not occur in string
*
*Exceptions:
*
*******************************************************************************/

wchar_t * __cdecl wcschr (
        const wchar_t * string,
        wchar_t ch
        )
{
        while (*string && *string != (wchar_t)ch)
                string++;

        if (*string == (wchar_t)ch)
                return((wchar_t *)string);
        return(NULL);
}



/***
*wcscmp.c - routine to compare two wchar_t strings (for equal, less, or greater)
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       Compares two wide-character strings, determining their lexical order.
*
*******************************************************************************/


#include <string.h>

/***
*wcscmp - compare two wchar_t strings,
*        returning less than, equal to, or greater than
*
*Purpose:
*       wcscmp compares two wide-character strings and returns an integer
*       to indicate whether the first is less than the second, the two are
*       equal, or whether the first is greater than the second.
*
*       Comparison is done wchar_t by wchar_t on an UNSIGNED basis, which is to
*       say that Null wchar_t(0) is less than any other character.
*
*Entry:
*       const wchar_t * src - string for left-hand side of comparison
*       const wchar_t * dst - string for right-hand side of comparison
*
*Exit:
*       returns -1 if src <  dst
*       returns  0 if src == dst
*       returns +1 if src >  dst
*
*Exceptions:
*
*******************************************************************************/

int __cdecl wcscmp (
        const wchar_t * src,
        const wchar_t * dst
        )
{
        int ret = 0 ;

        while( ! (ret = (int)(*src - *dst)) && *dst)
                ++src, ++dst;

        if ( ret < 0 )
                ret = -1 ;
        else if ( ret > 0 )
                ret = 1 ;

        return( ret );
}



/***
*wcslen.c - contains wcslen() routine
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       wcslen returns the length of a null-terminated wide-character string,
*       not including the null wchar_t itself.
*
*******************************************************************************/


#include <string.h>

/***
*wcslen - return the length of a null-terminated wide-character string
*
*Purpose:
*       Finds the length in wchar_t's of the given string, not including
*       the final null wchar_t (wide-characters).
*
*Entry:
*       const wchar_t * wcs - string whose length is to be computed
*
*Exit:
*       length of the string "wcs", exclusive of the final null wchar_t
*
*Exceptions:
*
*******************************************************************************/

size_t __cdecl wcslen (
        const wchar_t * wcs
        )
{
        const wchar_t *eos = wcs;

        while( *eos++ ) ;

        return( (size_t)(eos - wcs - 1) );
}



/***
*wcsncpy.c - copy at most n characters of wide-character string
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines wcsncpy() - copy at most n characters of wchar_t string
*
*******************************************************************************/


#include <string.h>

/***
*wchar_t *wcsncpy(dest, source, count) - copy at most n wide characters
*
*Purpose:
*       Copies count characters from the source string to the
*       destination.  If count is less than the length of source,
*       NO NULL CHARACTER is put onto the end of the copied string.
*       If count is greater than the length of sources, dest is padded
*       with null characters to length count (wide-characters).
*
*
*Entry:
*       wchar_t *dest - pointer to destination
*       wchar_t *source - source string for copy
*       size_t count - max number of characters to copy
*
*Exit:
*       returns dest
*
*Exceptions:
*
*******************************************************************************/

wchar_t * __cdecl wcsncpy (
        wchar_t * dest,
        const wchar_t * source,
        size_t count
        )
{
        wchar_t *start = dest;

        while (count && (*dest++ = *source++))    /* copy string */
                count--;

        if (count)                              /* pad out with zeroes */
                while (--count)
                        *dest++ = L'\0';

        return(start);
}



/***
*wcspbrk.c - scans wide character string for a character from control string
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines wcspbrk()- returns pointer to the first wide-character in
*       a wide-character string in the control string.
*
*******************************************************************************/


#include <string.h>

/***
*wchar_t *wcspbrk(string, control) - scans string for a character from control
*
*Purpose:
*       Returns pointer to the first wide-character in
*       a wide-character string in the control string.
*
*Entry:
*       wchar_t *string - string to search in
*       wchar_t *control - string containing characters to search for
*
*Exit:
*       returns a pointer to the first character from control found
*       in string.
*       returns NULL if string and control have no characters in common.
*
*Exceptions:
*
*******************************************************************************/

wchar_t * __cdecl wcspbrk (
        const wchar_t * string,
        const wchar_t * control
        )
{
        wchar_t *wcset;

        /* 1st char in control string stops search */
        while (*string) {
            for (wcset = (wchar_t *) control; *wcset; wcset++) {
                if (*wcset == *string) {
                    return (wchar_t *) string;
                }
            }
            string++;
        }
        return NULL;
}



/***
*wcsrchr.c - find last occurrence of wchar_t character in wide string
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines wcsrchr() - find the last occurrence of a given character
*       in a string (wide-characters).
*
*******************************************************************************/


#include <string.h>

/***
*wchar_t *wcsrchr(string, ch) - find last occurrence of ch in wide string
*
*Purpose:
*       Finds the last occurrence of ch in string.  The terminating
*       null character is used as part of the search (wide-characters).
*
*Entry:
*       wchar_t *string - string to search in
*       wchar_t ch - character to search for
*
*Exit:
*       returns a pointer to the last occurrence of ch in the given
*       string
*       returns NULL if ch does not occurr in the string
*
*Exceptions:
*
*******************************************************************************/

wchar_t * __cdecl wcsrchr (
        const wchar_t * string,
        wchar_t ch
        )
{
        wchar_t *start = (wchar_t *)string;

        while (*string++)                       /* find end of string */
                ;
                                                /* search towards front */
        while (--string != start && *string != (wchar_t)ch)
                ;

        if (*string == (wchar_t)ch)             /* wchar_t found ? */
                return( (wchar_t *)string );

        return(NULL);
}



/***
*wcsrev.c - reverse a wide-character string in place
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines _wcsrev() - reverse a wchar_t string in place (not including
*       L'\0' character)
*
*******************************************************************************/


#include <string.h>

/***
*wchar_t *_wcsrev(string) - reverse a wide-character string in place
*
*Purpose:
*       Reverses the order of characters in the string.  The terminating
*       null character remains in place (wide-characters).
*
*Entry:
*       wchar_t *string - string to reverse
*
*Exit:
*       returns string - now with reversed characters
*
*Exceptions:
*
*******************************************************************************/

wchar_t * __cdecl _wcsrev (
        wchar_t * string
        )
{
        wchar_t *start = string;
        wchar_t *left = string;
        wchar_t ch;

        while (*string++)                 /* find end of string */
                ;
        string -= 2;

        while (left < string)
        {
                ch = *left;
                *left++ = *string;
                *string-- = ch;
        }

        return(start);
}



/***
*wcsspn.c - find length of initial substring of chars from a control string
*       (wide-character strings)
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines wcsspn() - finds the length of the initial substring of
*       a string consisting entirely of characters from a control string
*       (wide-character strings).
*
*******************************************************************************/


#include <string.h>

/***
*int wcsspn(string, control) - find init substring of control chars
*
*Purpose:
*       Finds the index of the first character in string that does belong
*       to the set of characters specified by control.  This is
*       equivalent to the length of the initial substring of string that
*       consists entirely of characters from control.  The L'\0' character
*       that terminates control is not considered in the matching process
*       (wide-character strings).
*
*Entry:
*       wchar_t *string - string to search
*       wchar_t *control - string containing characters not to search for
*
*Exit:
*       returns index of first wchar_t in string not in control
*
*Exceptions:
*
*******************************************************************************/

size_t __cdecl wcsspn (
        const wchar_t * string,
        const wchar_t * control
        )
{
        wchar_t *str = (wchar_t *) string;
        wchar_t *ctl;

        /* 1st char not in control string stops search */
        while (*str) {
            for (ctl = (wchar_t *)control; *ctl != *str; ctl++) {
                if (*ctl == (wchar_t)0) {
                    /*
                     * reached end of control string without finding a match
                     */
                    return str - string;
                }
            }
            str++;
        }
        /*
         * The whole string consisted of characters from control
         */
        return str - string;
}



/***
*wcsstr.c - search for one wide-character string inside another
*
*       Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines wcsstr() - search for one wchar_t string inside another
*
*******************************************************************************/


#include <string.h>

/***
*wchar_t *wcsstr(string1, string2) - search for string2 in string1
*       (wide strings)
*
*Purpose:
*       finds the first occurrence of string2 in string1 (wide strings)
*
*Entry:
*       wchar_t *string1 - string to search in
*       wchar_t *string2 - string to search for
*
*Exit:
*       returns a pointer to the first occurrence of string2 in
*       string1, or NULL if string2 does not occur in string1
*
*Uses:
*
*Exceptions:
*
*******************************************************************************/

wchar_t * __cdecl wcsstr (
        const wchar_t * wcs1,
        const wchar_t * wcs2
        )
{
        wchar_t *cp = (wchar_t *) wcs1;
        wchar_t *s1, *s2;

        while (*cp)
        {
                s1 = cp;
                s2 = (wchar_t *) wcs2;

                while ( *s1 && *s2 && !(*s1-*s2) )
                        s1++, s2++;

                if (!*s2)
                        return(cp);

                cp++;
        }

        return(NULL);
}



/***
*wcstok.c - tokenize a wide-character string with given delimiters
*
*       Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines wcstok() - breaks wide-character string into series of token
*       via repeated calls.
*
*******************************************************************************/


#include "headers.hxx"

#ifndef X_STRING_H_
#define X_STRING_H_
#include <string.h>
#endif

/***
*wchar_t *wcstok(string, control) - tokenize string with delimiter in control
*       (wide-characters)
*
*Purpose:
*       wcstok considers the string to consist of a sequence of zero or more
*       text tokens separated by spans of one or more control chars. the first
*       call, with string specified, returns a pointer to the first wchar_t of
*       the first token, and will write a null wchar_t into string immediately
*       following the returned token. subsequent calls with zero for the first
*       argument (string) will work thru the string until no tokens remain. the
*       control string may be different from call to call. when no tokens remain
*       in string a NULL pointer is returned. remember the control chars with a
*       bit map, one bit per wchar_t. the null wchar_t is always a control char
*       (wide-characters).
*
*Entry:
*       wchar_t *string - wchar_t string to tokenize, or NULL to get next token
*       wchar_t *control - wchar_t string of characters to use as delimiters
*
*Exit:
*       returns pointer to first token in string, or if string
*       was NULL, to next token
*       returns NULL when no more tokens remain.
*
*Uses:
*
*Exceptions:
*
*******************************************************************************/

wchar_t * __cdecl wcstok (
        wchar_t * string,
        const wchar_t * control
        )
{
    wchar_t *token;
    const wchar_t *ctl;

    THREADSTATE *pts = GetThreadState();

    /* If string==NULL, continue with previous string */
    if (!string)
        string = pts->wtoken;

    /* Find beginning of token (skip over leading delimiters). Note that
     * there is no token iff this loop sets string to point to the terminal
     * null (*string == '\0') */

    while (*string) {
            for (ctl=control; *ctl && *ctl != *string; ctl++)
                    ;
            if (!*ctl) break;
            string++;
    }

    token = string;

    /* Find the end of the token. If it is not the end of the string,
     * put a null there. */
    for ( ; *string ; string++ ) {
            for (ctl=control; *ctl && *ctl != *string; ctl++)
                    ;
            if (*ctl) {
                    *string++ = '\0';
                    break;
            }
    }

    /* Update nextoken (or the corresponding field in the per-thread data
     * structure */
    pts->wtoken = string;

    /* Determine if a token has been found. */
    if ( token == string )
            return NULL;
    else
            return token;
}



/***
*wcstol.c - Contains C runtimes wcstol and wcstoul
*
*       Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       wcstol - convert wchar_t string to long signed integer
*       wcstoul - convert wchar_t string to long unsigned integer
*
*******************************************************************************/

#include "headers.hxx"

#ifndef X_STDLIB_H_
#define X_STDLIB_H_
#include <stdlib.h>
#endif

#ifndef X_LIMITS_H_
#define X_LIMITS_H_
#include <limits.h>
#endif

#ifndef X_CTYPE_H_
#define X_CTYPE_H_
#include <ctype.h>
#endif

/***
*wcstol, wcstoul(nptr,endptr,ibase) - Convert ascii string to long un/signed
*       int.
*
*Purpose:
*       Convert an ascii string to a long 32-bit value.  The base
*       used for the caculations is supplied by the caller.  The base
*       must be in the range 0, 2-36.  If a base of 0 is supplied, the
*       ascii string must be examined to determine the base of the
*       number:
*               (a) First char = '0', second char = 'x' or 'X',
*                   use base 16.
*               (b) First char = '0', use base 8
*               (c) First char in range '1' - '9', use base 10.
*
*       If the 'endptr' value is non-NULL, then wcstol/wcstoul places
*       a pointer to the terminating character in this value.
*       See ANSI standard for details
*
*Entry:
*       nptr == NEAR/FAR pointer to the start of string.
*       endptr == NEAR/FAR pointer to the end of the string.
*       ibase == integer base to use for the calculations.
*
*       string format: [whitespace] [sign] [0] [x] [digits/letters]
*
*Exit:
*       Good return:
*               result
*
*       Overflow return:
*               wcstol -- LONG_MAX or LONG_MIN
*               wcstoul -- ULONG_MAX
*               wcstol/wcstoul -- errno == ERANGE
*
*       No digits or bad base return:
*               0
*               endptr = nptr*
*
*Exceptions:
*       None.
*******************************************************************************/

/* flag values */
#define FL_UNSIGNED   1       /* wcstoul called */
#define FL_NEG        2       /* negative sign found */
#define FL_OVERFLOW   4       /* overflow occured */
#define FL_READDIGIT  8       /* we've read at least one correct digit */

#pragma warning (disable: 4305)
#pragma warning (disable: 4306)

static unsigned long __cdecl wcstoxl (
        const wchar_t *nptr,
        wchar_t **endptr,
        int ibase,
        int flags
        )
{
        const wchar_t *p;
        wchar_t c;
        unsigned long number;
        unsigned digval;
        unsigned long maxval;

        p = nptr;                       /* p is our scanning pointer */
        number = 0;                     /* start with zero */

        c = *p++;                       /* read char */
        while (_istspace(c))
                c = *p++;               /* skip whitespace */

        if (c == '-') {
                flags |= FL_NEG;        /* remember minus sign */
                c = *p++;
        }
        else if (c == '+')
                c = *p++;               /* skip sign */

        if (ibase < 0 || ibase == 1 || ibase > 36) {
                /* bad base! */
                if (endptr)
                        /* store beginning of string in endptr */
                        *endptr = (wchar_t *)nptr;
                return 0L;              /* return 0 */
        }
        else if (ibase == 0) {
                /* determine base free-lance, based on first two chars of
                   string */
                if (c != L'0')
                        ibase = 10;
                else if (*p == L'x' || *p == L'X')
                        ibase = 16;
                else
                        ibase = 8;
        }

        if (ibase == 16) {
                /* we might have 0x in front of number; remove if there */
                if (c == L'0' && (*p == L'x' || *p == L'X')) {
                        ++p;
                        c = *p++;       /* advance past prefix */
                }
        }

        /* if our number exceeds this, we will overflow on multiply */
        maxval = ULONG_MAX / ibase;


        for (;;) {      /* exit in middle of loop */
                /* convert c to value */
                if (_istdigit(c))
                        digval = c - L'0';
                else if (_istalpha(c))
                        digval = (TCHAR)CharUpper((LPTSTR)c) - L'A' + 10;
                else
                        break;
                if (digval >= (unsigned)ibase)
                        break;          /* exit loop if bad digit found */

                /* record the fact we have read one digit */
                flags |= FL_READDIGIT;

                /* we now need to compute number = number * base + digval,
                   but we need to know if overflow occured.  This requires
                   a tricky pre-check. */

                if (number < maxval || (number == maxval &&
                (unsigned long)digval <= ULONG_MAX % ibase)) {
                        /* we won't overflow, go ahead and multiply */
                        number = number * ibase + digval;
                }
                else {
                        /* we would have overflowed -- set the overflow flag */
                        flags |= FL_OVERFLOW;
                }

                c = *p++;               /* read next digit */
        }

        --p;                            /* point to place that stopped scan */

        if (!(flags & FL_READDIGIT)) {
                /* no number there; return 0 and point to beginning of
                   string */
                if (endptr)
                        /* store beginning of string in endptr later on */
                        p = nptr;
                number = 0L;            /* return 0 */
        }
        else if ( (flags & FL_OVERFLOW) ||
                  ( !(flags & FL_UNSIGNED) &&
                    ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
                      ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
        {
                /* overflow or signed overflow occurred */
                //errno = ERANGE;
                if ( flags & FL_UNSIGNED )
                        number = ULONG_MAX;
                else if ( flags & FL_NEG )
                        number = (unsigned long)(-LONG_MIN);
                else
                        number = LONG_MAX;
        }

        if (endptr != NULL)
                /* store pointer to char that stopped the scan */
                *endptr = (wchar_t *)p;

        if (flags & FL_NEG)
                /* negate result if there was a neg sign */
                number = (unsigned long)(-(long)number);

        return number;                  /* done. */
}

#pragma warning (default: 4305)
#pragma warning (default: 4306)

long __cdecl wcstol (
        const wchar_t *nptr,
        wchar_t **endptr,
        int ibase
        )
{
        return (long) wcstoxl(nptr, endptr, ibase, 0);
}

unsigned long __cdecl wcstoul (
        const wchar_t *nptr,
        wchar_t **endptr,
        int ibase
        )
{
        return wcstoxl(nptr, endptr, ibase, FL_UNSIGNED);
}




B#