_TSCHAR * __cdecl _tasctime ( const struct tm *tb ) { _TSCHAR *p = buf; errno_t e = 0; _TSCHAR *retval; /* holds retval pointer */ _ptiddata ptd = _getptd_noexit(); /* Use per thread buffer area (malloc space, if necessary) */ if (ptd) { #ifdef _UNICODE if ( (ptd->_wasctimebuf != NULL) || ((ptd->_wasctimebuf = (wchar_t *)_calloc_crt(_ASCBUFSIZE, sizeof(wchar_t))) != NULL) ) p = ptd->_wasctimebuf; #else /* _UNICODE */ if ( (ptd->_asctimebuf != NULL) || ((ptd->_asctimebuf = (char *)_calloc_crt(_ASCBUFSIZE, sizeof(char))) != NULL) ) p = ptd->_asctimebuf; #endif /* _UNICODE */ } retval = p; /* save return value for later */ e = _tasctime_s( p, _ASCBUFSIZE, tb ); if ( e != 0 ) { return NULL; } return (retval); }
/*** *char *strerror(errnum) - Map error number to error message string. * *Purpose: * The strerror runtime takes an error number for input and * returns the corresponding error message string. This routine * conforms to the ANSI standard interface. * *Entry: * int errnum - Integer error number (corresponding to an errno value). * *Exit: * char * - Strerror returns a pointer to the error message string. * This string is internal to the strerror routine (i.e., not supplied * by the user). * *Exceptions: * None. * *******************************************************************************/ #ifdef _UNICODE wchar_t * cdecl _wcserror( #else /* _UNICODE */ char * __cdecl strerror ( #endif /* _UNICODE */ int errnum ) { _TCHAR *errmsg; _ptiddata ptd = _getptd_noexit(); if (!ptd) return _T("Visual C++ CRT: Not enough memory to complete call to strerror."); if ( (ptd->_terrmsg == NULL) && ((ptd->_terrmsg = _calloc_crt(_ERRMSGLEN_, sizeof(_TCHAR))) == NULL) ) return _T("Visual C++ CRT: Not enough memory to complete call to strerror."); else errmsg = ptd->_terrmsg; #ifdef _UNICODE _ERRCHECK(mbstowcs_s(NULL, errmsg, _ERRMSGLEN_, _get_sys_err_msg(errnum), _ERRMSGLEN_ - 1)); #else /* _UNICODE */ _ERRCHECK(strcpy_s(errmsg, _ERRMSGLEN_, _get_sys_err_msg(errnum))); #endif /* _UNICODE */ return(errmsg); }
/*** *errno_t _set_doserrno() - set _doserrno * *Purpose: * Set the value of _doserrno * *Entry: * unsigned long value * *Exit: * The error code * *Exceptions: * *******************************************************************************/ errno_t _set_doserrno(unsigned long value) { _ptiddata ptd = _getptd_noexit(); if (!ptd) { return ENOMEM; } else { _doserrno = value; return 0; } }
/*** *errno_t _set_errno() - set errno * *Purpose: * Set the value of errno * *Entry: * int value * *Exit: * The error code * *Exceptions: * *******************************************************************************/ errno_t _set_errno(int value) { _ptiddata ptd = _getptd_noexit(); if (!ptd) { return ENOMEM; } else { errno = value; return 0; } }
_ptiddata __cdecl _getptd ( void ) { _ptiddata ptd = _getptd_noexit(); if (!ptd) { _amsg_exit(_RT_THREAD); /* write message and die */ } return ptd; }
unsigned long* __cdecl __doserrno( void ) { _ptiddata ptd = _getptd_noexit(); if (!ptd) { return &DoserrorNoMem; } else { return (&ptd->_tdoserrno); } }
int* __cdecl _errno( void ) { _ptiddata ptd = _getptd_noexit(); if (!ptd) { return &ErrnoNoMem; } else { return (&ptd->_terrno); } }
void __cdecl _endthread ( void ) { _ptiddata ptd; /* pointer to thread's _tiddata struct */ /* * Call fp termination, if necessary */ #ifdef CRTDLL _fpclear(); #else /* CRTDLL */ if (_FPmtterm != NULL && _IsNonwritableInCurrentImage((PBYTE)&_FPmtterm)) { (*_FPmtterm)(); } #endif /* CRTDLL */ ptd = _getptd_noexit(); if (ptd) { /* * Close the thread handle (if there was one) */ if ( ptd->_thandle != (uintptr_t)(-1) ) (void) CloseHandle( (HANDLE)(ptd->_thandle) ); /* * Free up the _tiddata structure & its subordinate buffers * _freeptd() will also clear the value for this thread * of the FLS variable __flsindex. */ _freeptd(ptd); } /* * Terminate the thread */ ExitThread(0); }
/*** *char *_strerror(message) - get system error message * *Purpose: * builds an error message consisting of the users error message * (the message parameter), followed by ": ", followed by the system * error message (index through errno), followed by a newline. If * message is NULL or a null string, returns a pointer to just * the system error message. * *Entry: * char *message - user's message to prefix system error message * *Exit: * returns pointer to static memory containing error message. * returns NULL if malloc() fails in multi-thread versions. * *Exceptions: * *******************************************************************************/ #ifdef _UNICODE wchar_t * __cdecl __wcserror( #else /* _UNICODE */ char * __cdecl _strerror ( #endif /* _UNICODE */ const _TCHAR *message ) { const char *sysErrorMsg = NULL; _TCHAR *bldmsg; _ptiddata ptd = _getptd_noexit(); if (!ptd) return NULL; /* Use per thread buffer area (malloc space, if necessary) */ /* [NOTE: This buffer is shared between _strerror and streror.] */ if ( (ptd->_terrmsg == NULL) && ((ptd->_terrmsg = _calloc_crt(_ERRMSGLEN_, sizeof(_TCHAR))) == NULL) ) return(NULL); bldmsg = ptd->_terrmsg; /* Build the error message */ bldmsg[0] = '\0'; if (message && *message) { // should leave space for ": \n\0" _ERRCHECK(_tcsncat_s( bldmsg, _ERRMSGLEN_, message, _ERRMSGLEN_-4 )); _ERRCHECK(_tcscat_s( bldmsg, _ERRMSGLEN_, _T(": "))); } // We should have extra space for "\n\0" sysErrorMsg = _get_sys_err_msg(errno); #ifdef _UNICODE _ERRCHECK(mbstowcs_s(NULL, bldmsg + wcslen(bldmsg), _ERRMSGLEN_ - wcslen(bldmsg), sysErrorMsg, _ERRMSGLEN_ - wcslen(bldmsg) - 2)); #else /* _UNICODE */ _ERRCHECK(strncat_s(bldmsg, _ERRMSGLEN_, sysErrorMsg, _ERRMSGLEN_ - strlen(bldmsg) - 2)); #endif /* _UNICODE */ _ERRCHECK(_tcscat_s( bldmsg, _ERRMSGLEN_, _T("\n"))); return bldmsg; }
int __cdecl _XcptFilter ( unsigned long xcptnum, PEXCEPTION_POINTERS pxcptinfoptrs ) { struct _XCPT_ACTION * pxcptact; _PHNDLR phandler; void *oldpxcptinfoptrs; int oldfpecode; int indx; _ptiddata ptd = _getptd_noexit(); if (!ptd) { // we can't deal with it - pass it on. return( UnhandledExceptionFilter(pxcptinfoptrs) ); } pxcptact = xcptlookup(xcptnum, ptd->_pxcptacttab); if (pxcptact == NULL) { phandler = SIG_DFL; } else { phandler = pxcptact->XcptAction; } /* * first, take care of all unrecognized exceptions and exceptions with * XcptAction values of SIG_DFL. */ if ( phandler == SIG_DFL ) /* * pass the buck to the UnhandledExceptionFilter */ return( UnhandledExceptionFilter(pxcptinfoptrs) ); /* * next, weed out all of the exceptions that need to be handled by * dying, perhaps with a runtime error message */ if ( phandler == SIG_DIE ) { /* * reset XcptAction (in case of recursion) and drop into the * except-clause. */ pxcptact->XcptAction = SIG_DFL; return(EXCEPTION_EXECUTE_HANDLER); } /* * next, weed out all of the exceptions that are simply ignored */ if ( phandler == SIG_IGN ) /* * resume execution */ return(EXCEPTION_CONTINUE_EXECUTION); /* * the remaining exceptions all correspond to C signals which have * signal handlers associated with them. for some, special setup * is required before the signal handler is called. in all cases, * if the signal handler returns, -1 is returned by this function * to resume execution at the point where the exception occurred. */ /* * save the old value of _pxcptinfoptrs (in case this is a nested * exception/signal) and store the current one. */ oldpxcptinfoptrs = PXCPTINFOPTRS; PXCPTINFOPTRS = pxcptinfoptrs; /* * call the user-supplied signal handler * * floating point exceptions must be handled specially since, from * the C point-of-view, there is only one signal. the exact identity * of the exception is passed in the global variable _fpecode. */ if ( pxcptact->SigNum == SIGFPE ) { /* * reset the XcptAction field to the default for all entries * corresponding to SIGFPE. */ for ( indx = _First_FPE_Indx ; indx < _First_FPE_Indx + _Num_FPE ; indx++ ) { ( (struct _XCPT_ACTION *)(ptd->_pxcptacttab) + indx )->XcptAction = SIG_DFL; } /* * Save the current _fpecode in case it is a nested floating * point exception (not clear that we need to support this, * but it's easy). */ oldfpecode = FPECODE; /* * there are no exceptions corresponding to * following _FPE_xxx codes: * * _FPE_UNEMULATED * _FPE_SQRTNEG * * futhermore, STATUS_FLOATING_STACK_CHECK is * raised for both floating point stack under- * flow and overflow. thus, the exception does * not distinguish between _FPE_STACKOVERLOW * and _FPE_STACKUNDERFLOW. arbitrarily, _fpecode * is set to the former value. * * the following should be a switch statement but, alas, the * compiler doesn't like switching on unsigned longs... */ if ( pxcptact->XcptNum == STATUS_FLOAT_DIVIDE_BY_ZERO ) FPECODE = _FPE_ZERODIVIDE; else if ( pxcptact->XcptNum == STATUS_FLOAT_INVALID_OPERATION ) FPECODE = _FPE_INVALID; else if ( pxcptact->XcptNum == STATUS_FLOAT_OVERFLOW ) FPECODE = _FPE_OVERFLOW; else if ( pxcptact->XcptNum == STATUS_FLOAT_UNDERFLOW ) FPECODE = _FPE_UNDERFLOW; else if ( pxcptact->XcptNum == STATUS_FLOAT_DENORMAL_OPERAND ) FPECODE = _FPE_DENORMAL; else if ( pxcptact->XcptNum == STATUS_FLOAT_INEXACT_RESULT ) FPECODE = _FPE_INEXACT; else if ( pxcptact->XcptNum == STATUS_FLOAT_STACK_CHECK ) FPECODE = _FPE_STACKOVERFLOW; /* * call the SIGFPE handler. note the special code to support * old MS-C programs whose SIGFPE handlers expect two args. * * NOTE: THE CAST AND CALL BELOW DEPEND ON __cdecl BEING * CALLER CLEANUP! */ (*(void (__cdecl *)(int, int))phandler)(SIGFPE, FPECODE); /* * restore the old value of _fpecode */ FPECODE = oldfpecode; } else { /* * reset the XcptAction field to the default, then call the * user-supplied handler */ pxcptact->XcptAction = SIG_DFL; (*phandler)(pxcptact->SigNum); } /* * restore the old value of _pxcptinfoptrs */ PXCPTINFOPTRS = oldpxcptinfoptrs; return(EXCEPTION_CONTINUE_EXECUTION); }