mirror of
https://github.com/evilneuro/eudora-mac.git
synced 2024-06-06 04:29:31 +00:00
553 lines
14 KiB
C
Executable File
553 lines
14 KiB
C
Executable File
/* Copyright (c) 2017, Computer History Museum
|
|
All rights reserved.
|
|
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
|
|
the limitations in the disclaimer below) provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
|
|
disclaimer in the documentation and/or other materials provided with the distribution.
|
|
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
|
|
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE. */
|
|
|
|
/* Metrowerks Standard Library
|
|
* Copyright © 1995-2003 Metrowerks Corporation. All rights reserved.
|
|
*
|
|
* $Date: 2004/01/08 18:40:40 $
|
|
* $Revision: 1.14.2.6 $
|
|
*/
|
|
|
|
#include <extras.h>
|
|
#include <time.h>
|
|
#include <sys/stat.h>
|
|
#include <wchar.h>
|
|
#include <wctype.h>
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <file_io.h>
|
|
#include "ansi_files.h"
|
|
|
|
char * _MSL_CDECL strdup(const char *str) _MSL_CANT_THROW
|
|
{
|
|
return __msl_strdup(str);
|
|
}
|
|
|
|
char * _MSL_CDECL strlwr (char *string) _MSL_CANT_THROW
|
|
{
|
|
char *s = string;
|
|
|
|
while (*s)
|
|
{
|
|
*s = tolower (*s);
|
|
s++;
|
|
}
|
|
|
|
return string;
|
|
}
|
|
|
|
/* Convert unsigned integer to a string */
|
|
char * _MSL_CDECL ultoa(unsigned long val, char *str, int radix) _MSL_CANT_THROW
|
|
{
|
|
unsigned long theNum = val;
|
|
int StrIndex = 0;
|
|
|
|
do
|
|
{
|
|
int CurDigit = theNum % radix;
|
|
if (CurDigit > 9)
|
|
str[StrIndex++] = CurDigit + 'A' - 10;
|
|
else
|
|
str[StrIndex++] = CurDigit + '0';
|
|
|
|
theNum /= radix;
|
|
} while (theNum);
|
|
|
|
str[StrIndex++] = 0;
|
|
|
|
/* Now reverse the string.*/
|
|
__msl_strrev(str);
|
|
|
|
return str;
|
|
}
|
|
|
|
/* Convert a value as a g format */
|
|
#ifndef _No_Floating_Point
|
|
char * _MSL_CDECL gcvt(double value, int digits, char *buffer) _MSL_CANT_THROW
|
|
{
|
|
sprintf(buffer, "%.*g", digits, value);
|
|
return buffer;
|
|
}
|
|
#endif
|
|
|
|
/* return unused heap memory */
|
|
int _MSL_CDECL heapmin(void) _MSL_CANT_THROW
|
|
{
|
|
errno = ENOSYS;
|
|
return -1;
|
|
}
|
|
|
|
/* Compare lexigraphically two strings */
|
|
int _MSL_CDECL stricmp(const char *s1, const char *s2) _MSL_CANT_THROW
|
|
{
|
|
char c1, c2;
|
|
while (1)
|
|
{
|
|
c1 = tolower(*s1++);
|
|
c2 = tolower(*s2++);
|
|
if (c1 < c2) return -1;
|
|
if (c1 > c2) return 1;
|
|
if (c1 == 0) return 0;
|
|
}
|
|
#if CodeTEST
|
|
return 1; /*- ejs 030428: NOTREACHED but avoid warning due to complex code -*/
|
|
#endif
|
|
}
|
|
|
|
/* Compare lexigraphically two strings up to a max length */
|
|
int _MSL_CDECL strnicmp(const char *s1, const char *s2, size_t n) _MSL_CANT_THROW
|
|
{
|
|
return __msl_strnicmp(s1,s2, n);
|
|
}
|
|
|
|
/* Uppercase a string */
|
|
char * _MSL_CDECL strupr(char *str) _MSL_CANT_THROW
|
|
{
|
|
char *temp = str; /*- mm 010116 -*/
|
|
while (*temp) /*- mm 010116 -*/
|
|
{
|
|
*temp= toupper(*temp); /*- mm 010116 -*/
|
|
temp++; /*- mm 010116 -*/
|
|
}
|
|
return str;
|
|
}
|
|
|
|
|
|
/* Get the date in a string */
|
|
#ifndef _No_Time_OS_Support
|
|
char * _MSL_CDECL strdate(char *str) _MSL_CANT_THROW
|
|
{
|
|
time_t timer;
|
|
time(&timer);
|
|
strftime(str, 10, "%m/%d/%y", localtime(&timer));
|
|
return str;
|
|
}
|
|
#endif /* _No_Time_OS_Support */
|
|
|
|
/* Set characters of string to character */
|
|
char * _MSL_CDECL strset(char *str, int c) _MSL_CANT_THROW
|
|
{
|
|
char *save = str;
|
|
|
|
while (*str)
|
|
{
|
|
*str++ = c;
|
|
}
|
|
|
|
return save;
|
|
}
|
|
|
|
/* Set first n characters of string to character */
|
|
char * _MSL_CDECL strnset(char *str, int c, size_t n) _MSL_CANT_THROW
|
|
{
|
|
char *save = str;
|
|
|
|
while (n && *str)
|
|
{
|
|
*(str++) = c;
|
|
n--;
|
|
}
|
|
|
|
return save;
|
|
}
|
|
|
|
/* return pointer to first character in s1 that isn't in s2 */
|
|
char * _MSL_CDECL strspnp(char *s1, const char *s2) _MSL_CANT_THROW
|
|
{
|
|
int len; /*- mm 020906 -*/
|
|
len = strspn(s1, s2); /*- mm 020906 -*/
|
|
if (len < strlen(s1)) /*- mm 020906 -*/
|
|
return(s1+len); /*- mm 020906 -*/
|
|
else /*- mm 020906 -*/
|
|
return NULL; /*- mm 020906 -*/
|
|
}
|
|
|
|
/* Case-insensitive string comparison */
|
|
int _MSL_CDECL strncasecmp(const char *s1, const char *s2, size_t n) _MSL_CANT_THROW
|
|
{
|
|
return __msl_strnicmp(s1,s2, n);
|
|
}
|
|
|
|
int _MSL_CDECL strcmpi(const char *s1, const char *s2) _MSL_CANT_THROW
|
|
{
|
|
return stricmp(s1,s2);
|
|
}
|
|
|
|
int _MSL_CDECL strncmpi(const char *s1, const char *s2, size_t n) _MSL_CANT_THROW
|
|
{
|
|
return __msl_strnicmp(s1,s2, n);
|
|
}
|
|
|
|
int _MSL_CDECL strcasecmp(const char *s1, const char *s2) _MSL_CANT_THROW
|
|
{
|
|
return stricmp(s1,s2);
|
|
}
|
|
|
|
int _MSL_CDECL stricoll(const char *s1, const char *s2) _MSL_CANT_THROW
|
|
{
|
|
return stricmp(s1, s2);
|
|
}
|
|
|
|
int _MSL_CDECL strncoll(const char *s1, const char *s2, __std(size_t) sz) _MSL_CANT_THROW
|
|
{
|
|
return strncmp(s1, s2, sz);
|
|
}
|
|
|
|
int _MSL_CDECL strnicoll(const char *s1, const char *s2, __std(size_t) sz) _MSL_CANT_THROW
|
|
{
|
|
return strnicmp(s1, s2, sz);
|
|
}
|
|
|
|
char * _MSL_CDECL itoa(int val, char *str, int radix) _MSL_CANT_THROW
|
|
{
|
|
return __msl_itoa(val, str, radix);
|
|
}
|
|
|
|
/* reverse a string in place */
|
|
char * _MSL_CDECL strrev(char * str) _MSL_CANT_THROW
|
|
{
|
|
return __msl_strrev(str);
|
|
}
|
|
|
|
#ifndef _No_Disk_File_OS_Support
|
|
int _MSL_CDECL filelength(int fileno) _MSL_CANT_THROW
|
|
{
|
|
struct stat st;
|
|
if (fstat(fileno, &st)) return -1;
|
|
return st.st_size;
|
|
}
|
|
#endif
|
|
|
|
#ifndef _No_Disk_File_OS_Support
|
|
#if ((__dest_os == __win32_os || __dest_os == __mac_os) && _MSL_POSIX)
|
|
|
|
int _MSL_CDECL chsize( int handle, long size ) _MSL_CANT_THROW
|
|
{
|
|
FILE *infile;
|
|
struct stat buff;
|
|
int status;
|
|
long int file_size;
|
|
int i;
|
|
|
|
/* check the size */
|
|
if( size < 0 )
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
/* check if we have write permission */
|
|
if((fstat( handle, &buff)) == 0)
|
|
{
|
|
if(!( buff.st_mode & S_IWUSR))
|
|
{
|
|
/* we don't have write permission */
|
|
errno = EACCES;
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* fstat not able to obtain the file-status information -- errno set by fstat */
|
|
return -1;
|
|
}
|
|
|
|
if( (infile = fdopen( handle, "w" ))== NULL)
|
|
{
|
|
errno = EIO;
|
|
return -1;
|
|
}
|
|
|
|
file_size = (unsigned long) buff.st_size;
|
|
|
|
if((size - file_size) == 0)
|
|
return 0;
|
|
else
|
|
{
|
|
if( (unsigned long) size > file_size ) /* need to extend the file */
|
|
{
|
|
if((fseek( infile, 0, SEEK_END )) != 0 )
|
|
{
|
|
errno = EIO;
|
|
return -1;
|
|
}
|
|
|
|
for( i = file_size; i < size; i++ )
|
|
{
|
|
if((fputc( 0, infile )) == EOF )
|
|
{
|
|
errno = EIO;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/*flush the stream for the new eof to take effect */
|
|
if((status = fflush( infile )) != 0 )
|
|
{
|
|
errno = EIO;
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
else /* need to truncate the file */
|
|
{
|
|
/*flush the stream before changing the size */
|
|
status = fflush( infile );
|
|
if( status != 0 )
|
|
{
|
|
errno = EIO;
|
|
return -1;
|
|
}
|
|
|
|
status = __msl_setfilesize(handle, size);
|
|
if( status != 0 )
|
|
{
|
|
errno = EIO;
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
#endif /* _No_Disk_File_OS_Support */
|
|
|
|
#if _MSL_WIDE_CHAR
|
|
|
|
/* lowercase all characters in str */
|
|
int _MSL_CDECL wtoi(const wchar_t *_a) _MSL_CANT_THROW
|
|
{
|
|
return wcstol(_a, NULL, 10);
|
|
}
|
|
|
|
|
|
wchar_t * _MSL_CDECL wcslwr (wchar_t *str) _MSL_CANT_THROW
|
|
{
|
|
wchar_t *saved = str;
|
|
|
|
while (*str)
|
|
{
|
|
*str = towlower (*str);
|
|
str++;
|
|
}
|
|
|
|
return saved;
|
|
}
|
|
|
|
/* uppercase all characters in str */
|
|
wchar_t * _MSL_CDECL wcsupr (wchar_t *str) _MSL_CANT_THROW
|
|
{
|
|
wchar_t *saved = str;
|
|
|
|
while (*str)
|
|
{
|
|
*str = towupper (*str);
|
|
str++;
|
|
}
|
|
|
|
return saved;
|
|
}
|
|
|
|
int _MSL_CDECL wcsicmp(const wchar_t *s1, const wchar_t *s2) _MSL_CANT_THROW
|
|
{
|
|
wchar_t c1, c2;
|
|
while (1)
|
|
{
|
|
c1 = towlower(*s1++);
|
|
c2 = towlower(*s2++);
|
|
if (c1 < c2) return -1;
|
|
if (c1 > c2) return 1;
|
|
if (c1 == 0) return 0;
|
|
}
|
|
#if CodeTEST
|
|
return 1; /*- ejs 030428: NOTREACHED but avoid warning due to complex code -*/
|
|
#endif
|
|
}
|
|
|
|
/* case-insensitive compare of s1, s2, stopping after n characters */
|
|
int _MSL_CDECL wcsnicmp(const wchar_t *s1, const wchar_t *s2, size_t n) _MSL_CANT_THROW
|
|
{
|
|
int i;
|
|
wchar_t c1, c2;
|
|
for (i=0; i<n; i++)
|
|
{
|
|
c1 = towlower(*s1++);
|
|
c2 = towlower(*s2++);
|
|
if (c1 < c2) return -1;
|
|
if (c1 > c2) return 1;
|
|
if (!c1) return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* reverse order of characters in str */
|
|
wchar_t * _MSL_CDECL wcsrev(wchar_t *str) _MSL_CANT_THROW
|
|
{
|
|
int SmallIndex = 0;
|
|
int BigIndex = wcslen(str) - 1;
|
|
|
|
while (SmallIndex < BigIndex) {
|
|
wchar_t Temp = str[SmallIndex];
|
|
|
|
str[SmallIndex] = str[BigIndex];
|
|
str[BigIndex] = Temp;
|
|
|
|
SmallIndex++;
|
|
BigIndex--;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/* set all characters of str to wc */
|
|
wchar_t * _MSL_CDECL wcsset(wchar_t *str, wchar_t wc) _MSL_CANT_THROW
|
|
{
|
|
wchar_t *saved = str;
|
|
|
|
while (*str)
|
|
{
|
|
*str++ = wc;
|
|
}
|
|
|
|
return saved;
|
|
}
|
|
|
|
|
|
/* set characters of str to wc, up to max of n characters */
|
|
wchar_t * _MSL_CDECL wcsnset(wchar_t *str, wchar_t wc, size_t n) _MSL_CANT_THROW
|
|
{
|
|
wchar_t *saved = str;
|
|
|
|
while (*str && n--)
|
|
{
|
|
*str = wc;
|
|
}
|
|
|
|
return saved;
|
|
}
|
|
|
|
/* return pointer to first character in s1 that isn't in s2 */
|
|
wchar_t * _MSL_CDECL wcsspnp(const wchar_t *s1, const wchar_t *s2) _MSL_CANT_THROW
|
|
{
|
|
int len; /*- mm 020906 -*/
|
|
len = wcsspn(s1, s2); /*- mm 020906 -*/
|
|
if (len < wcslen(s1)) /*- mm 020906 -*/
|
|
return((wchar_t*)(s1+len)); /*- mm 020906 -*/
|
|
else /*- mm 020906 -*/
|
|
return NULL; /*- mm 020906 -*/
|
|
}
|
|
|
|
wchar_t * _MSL_CDECL wcsdup (const wchar_t *str) _MSL_CANT_THROW
|
|
{
|
|
wchar_t * rval = (wchar_t *)__std(malloc)((__std(wcslen)(str)+1) * sizeof (wchar_t));
|
|
|
|
if (rval) {
|
|
__std(wcscpy)(rval, str);
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
wchar_t * _MSL_CDECL wstrrev(wchar_t * str) _MSL_CANT_THROW
|
|
{
|
|
int SmallIndex = 0;
|
|
int BigIndex = wcslen(str) - 1;
|
|
|
|
while (SmallIndex < BigIndex) {
|
|
wchar_t Temp = str[SmallIndex];
|
|
|
|
str[SmallIndex] = str[BigIndex];
|
|
str[BigIndex] = Temp;
|
|
|
|
SmallIndex++;
|
|
BigIndex--;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
int _MSL_CDECL wcsicoll(const wchar_t *s1, const wchar_t *s2) _MSL_CANT_THROW
|
|
{
|
|
return wcsicmp(s1, s2);
|
|
}
|
|
|
|
int _MSL_CDECL wcsncoll(const wchar_t *s1, const wchar_t *s2, __std(size_t) sz) _MSL_CANT_THROW
|
|
{
|
|
return wcsncmp(s1, s2, sz);
|
|
}
|
|
|
|
int _MSL_CDECL wcsnicoll(const wchar_t *s1, const wchar_t *s2, __std(size_t) sz) _MSL_CANT_THROW
|
|
{
|
|
return wcsnicmp(s1, s2, sz);
|
|
}
|
|
|
|
wchar_t * _MSL_CDECL itow(int val, wchar_t *str, int radix) _MSL_CANT_THROW
|
|
{
|
|
char IsNegative = 0;
|
|
int theNum = val;
|
|
unsigned int theUNum; /*- mm 000209 -*/
|
|
int StrIndex = 0;
|
|
|
|
if (val < 0) /*- mm 000209 -*/
|
|
{ /*- mm 000209 -*/
|
|
theUNum = -val; /*- mm 000209 -*/
|
|
IsNegative = 1; /*- mm 000209 -*/
|
|
} /*- mm 000209 -*/
|
|
else /*- mm 000209 -*/
|
|
theUNum = val; /*- mm 000209 -*/
|
|
|
|
do
|
|
{
|
|
int CurDigit = theUNum % radix; /*- mm 000209 -*/
|
|
if (CurDigit > 9)
|
|
str[StrIndex++] = CurDigit + L'A' - 10;
|
|
else
|
|
str[StrIndex++] = CurDigit + L'0';
|
|
|
|
theUNum /= radix; /*- mm 000209 -*/
|
|
} while (theUNum); /*- mm 000209 -*/
|
|
if (IsNegative)
|
|
str[StrIndex++] = '-';
|
|
str[StrIndex++] = 0;
|
|
|
|
/* Now reverse the string.*/
|
|
wstrrev(str);
|
|
|
|
return str;
|
|
}
|
|
|
|
double _MSL_CDECL watof(const wchar_t * str) _MSL_CANT_THROW
|
|
{
|
|
return(wcstod(str, NULL));
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Change record:
|
|
* cc 000510 made __myraise an inline in unix.h
|
|
* cc 000511 moved common source from extras.win32.c
|
|
* cc 000511 added <cwchar>, <cwctype>
|
|
* as 000821 added guards for wide character support
|
|
* mm 010116 Changes to make _strupr return pointer to beginning of string instead of end. Josef's fix.
|
|
* cc 010130 Changed _splitpath to support UNC pathnames
|
|
* mm 010412 Avoided setting errno to negative value.
|
|
* cc 010605 Made _itoa call __msl_itoa, _strrev call __msl_strrev, _itoa call __msl_itoa,and
|
|
* _strnicmp call __msl_strnicmp
|
|
* cc 010605 Added #include of file_io.h
|
|
* cc 010713 Made all the functions _ and non_
|
|
* cc 010714 Added strcmpi and strncmpi
|
|
* cc 010715 Removed makepath & splitpath
|
|
* cc 010725 Changed _strdup & strdup to call __msl_strdup
|
|
* cc 010924 Added Hisham's version of chsize
|
|
* ejs 011128 Added strcoll/wcscoll variants
|
|
* cc 011203 Added _MSL_CDECL for new name mangling
|
|
* cc 020130 Added changes for e68k group
|
|
* mm 020906 Rewrote strspnp and wcsspnp because of error reported in WB1-38641
|
|
* cc 021119 Moved watof from the C lib to extras
|
|
* cc 020106 Fixed chsize to change file size
|
|
* JWW 030224 Changed __NO_WIDE_CHAR flag into the new more configurable _MSL_WIDE_CHAR
|
|
* ejs 030428 Added change to avoid compiler warnings when CodeTEST enabled
|
|
* cc 030722 Moved underscored functions out of extras common headers/source.
|
|
* They now live in the extras_xxxx_win32.h headers/source.
|
|
* ejs 040108 Use <sys/stat.h>, not <stat.h>
|
|
*/ |