This commit is contained in:
簞純 2023-09-18 16:55:21 +08:00
parent b3258002d1
commit ee3965aa10
4 changed files with 99 additions and 432 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.obj
*.exe

486
crt.c
View File

@ -1,11 +1,6 @@
#include "crt.h"
#pragma optimize("", off)
#define _FILE_TEXT 0x0001
#define _FILE_EOF 0x0002
#define _FILE_ERROR 0x0004
#define EOF (-1)
#define _MAX_CMD_LINE_ARGS 32
char* _argv[_MAX_CMD_LINE_ARGS + 1];
@ -101,7 +96,7 @@ void _term_args()
}
void* xmalloc(size_t size) {
return HeapAlloc(GetProcessHeap(), 0, size);
return HeapAlloc(GetProcessHeap(), 0, size);
}
void* xrealloc(void* ptr, size_t size) {
@ -109,7 +104,7 @@ void* xrealloc(void* ptr, size_t size) {
}
void xfree(void* ptr) {
HeapFree(GetProcessHeap(), 0, ptr);
HeapFree(GetProcessHeap(),0, ptr);
}
unsigned int rand_seed;
@ -273,7 +268,31 @@ char* xstrcat(char* dst, const char* src)
return lstrcatA(dst, src);
}
const char* xxstrstr(const char* str, const char* substr)
int xstrncat_s(char * dest, size_t num, const char * source, size_t count)
{
size_t i, j;
if (!dest || !source)
return 22;
for(i = 0; i < num; i++)
{
if(dest[i] == '\0')
{
for(j = 0; (j + i) < num; j++)
{
if(j == count || (dest[j + i] = source[j]) == '\0')
{
dest[j + i] = '\0';
return 0;
}
}
}
}
return 34;
}
char* xstrstr(char* str, const char* substr)
{
int i;
int str_len = xstrlen(str);
@ -285,11 +304,19 @@ const char* xxstrstr(const char* str, const char* substr)
for (i = 0; i < (int)(str_len - substr_len + 1); i++)
{
if (!xstrcmp(&str[i], substr))
return (const char*)(&str[i]);
return (char*)(&str[i]);
}
return 0;
}
char* xstrtok(char* s, const char* delm)
{
HMODULE msvcrt = LoadLibraryA("msvcrt.dll");
char* (__cdecl *func)(char* s, const char* delm) = NULL;
func = (char* (__cdecl *)(char* s, const char* delm))GetProcAddress(msvcrt, "strtok");
return (*func)(s, delm);
}
size_t xwcslen(const wchar_t* str)
{
return lstrlenW(str);
@ -557,393 +584,6 @@ int xwtoi(const wchar_t* str)
return (int)xwtol(str);
}
FILE* __cdecl xfopen(const char* path, const char* attrs)
{
FILE* file;
HANDLE hFile;
DWORD access, disp;
if (xstrchr(attrs, 'w'))
{
access = GENERIC_WRITE;
disp = CREATE_ALWAYS;
}
else
{
access = GENERIC_READ;
disp = OPEN_EXISTING;
}
hFile = CreateFileA(path, access, 0, 0, disp, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
return 0;
file = (FILE*)xmalloc(sizeof(FILE));
__stosb((PBYTE)file, 0, sizeof(FILE));
file->_base = (char*)hFile;
if (xstrchr(attrs, 't')) {
file->_flag |= _FILE_TEXT;
}
return file;
}
FILE* __cdecl _xwfopen(const wchar_t* path, const wchar_t* attrs)
{
HANDLE hFile;
DWORD access, disp;
FILE* file;
if (xwcschr(attrs, L'w')) {
access = GENERIC_WRITE;
disp = CREATE_ALWAYS;
}
else
{
access = GENERIC_READ;
disp = OPEN_EXISTING;
}
hFile = CreateFileW(path, access, 0, 0, disp, 0, 0);
if (hFile == INVALID_HANDLE_VALUE) {
return 0;
}
file = (FILE*)xmalloc(sizeof(FILE));
__stosb((PBYTE)file, 0, sizeof(FILE));
file->_base = (char*)hFile;
if (xwcschr(attrs, L't')) {
file->_flag |= _FILE_TEXT;
}
return file;
}
size_t __cdecl xfwrite(const void* buffer, size_t size, size_t count, FILE* str)
{
DWORD bw = 0, bw2 = 0;
HANDLE hFile;
int textMode;
if (size * count == 0)
return 0;
hFile = str->_base;
textMode = str->_flag & _FILE_TEXT;
// Text-mode translation is always ANSI!
if (textMode) // text mode -> translate LF -> CRLF
{
const char* src = (const char*)buffer;
size_t startpos = 0, i = 0;
for (i = 0; i < size * count; i++) {
const char* crlf;
if (src[i] != '\n')
continue;
if (i > 0 && src[i - 1] == '\r') // don't translate CRLF
continue;
if (i > startpos)
{
WriteFile(hFile, &src[startpos], i - startpos, &bw2, 0);
bw += bw2;
}
crlf = "\r\n";
WriteFile(hFile, crlf, 2, &bw2, 0);
bw++; // one '\n' written
startpos = i + 1;
}
if (i > startpos)
{
WriteFile(hFile, &src[startpos], i - startpos, &bw2, 0);
bw += bw2;
}
}
else
WriteFile(hFile, buffer, (DWORD)(size * count), &bw, 0);
return bw / size;
}
int __cdecl xfprintf(FILE* fp, const char* s, ...)
{
va_list args;
char bfr[1024];
int len;
va_start(args, s);
len = wvsprintfA(bfr, s, args);
va_end(args);
xfwrite(bfr, len + 1, sizeof(char), fp);
return len;
}
int __cdecl vfprintf(FILE* fp, const char* s, va_list args)
{
char bfr[1024];
int len;
len = wvsprintfA(bfr, s, args);
xfwrite(bfr, len + 1, sizeof(char), fp);
return len;
}
int __cdecl fwprintf(FILE* fp, const wchar_t* s, ...)
{
va_list args;
wchar_t bfr[1024];
int len;
char ansibfr[1024];
va_start(args, s);
len = wvsprintfW(bfr, s, args);
va_end(args);
WideCharToMultiByte(CP_ACP, 0, bfr, -1, ansibfr, sizeof(ansibfr), 0, 0);
xfwrite(ansibfr, len + 1, sizeof(char), fp);
return len;
}
int __cdecl xfclose(FILE* fp)
{
CloseHandle(fp->_base);
xfree(fp);
return 0;
}
int __cdecl xfeof(FILE* fp)
{
return (fp->_flag & _FILE_EOF) ? 1 : 0;
}
int __cdecl xfseek(FILE* str, long offset, int origin)
{
DWORD meth = FILE_BEGIN;
if (origin == SEEK_CUR)
meth = FILE_CURRENT;
else if (origin == SEEK_END)
meth = FILE_END;
SetFilePointer(str->_base, offset, 0, meth);
str->_flag &= ~_FILE_EOF;
return 0;
}
long __cdecl xftell(FILE* fp)
{
return SetFilePointer(fp->_base, 0, 0, FILE_CURRENT);
}
size_t __cdecl xfread(void* buffer, size_t size, size_t count, FILE* str)
{
HANDLE hFile;
int textMode;
char* src;
DWORD br;
if (size * count == 0)
return 0;
if (xfeof(str))
return 0;
hFile = str->_base;
textMode = str->_flag & _FILE_TEXT;
if (textMode)
src = (char*)xmalloc(size * count);
else
src = (char*)buffer;
if (!ReadFile(hFile, src, (DWORD)(size * count), &br, 0))
str->_flag |= _FILE_ERROR;
else if (!br) // nonzero return value and no bytes read = EOF
str->_flag |= _FILE_EOF;
if (!br)
return 0;
// Text-mode translation is always ANSI
if (textMode) { // text mode: must translate CR -> LF
char* dst = (char*)buffer;
DWORD i;
for (i = 0; i < br; i++) {
if (src[i] != '\r')
{
*dst++ = src[i];
continue;
}
// If next char is LF -> convert CR to LF
if (i + 1 < br)
{
if (src[i + 1] == '\n')
{
*dst++ = '\n';
i++;
}
else
*dst++ = src[i];
}
else if (br > 1)
{
// This is the hard part: must peek ahead one byte
DWORD br2 = 0;
char peekChar = 0;
ReadFile(hFile, &peekChar, 1, &br2, 0);
if (!br2)
*dst++ = src[i];
else if (peekChar == '\n')
*dst++ = '\n';
else
{
xfseek(str, -1, SEEK_CUR);
*dst++ = src[i];
}
}
else
*dst++ = src[i];
}
xfree(src);
}
return br / size;
}
char* __cdecl xfgets(char* str, int n, FILE* s)
{
int i;
if (xfeof(s))
return 0;
for (i = 0; i < n - 1; i++)
{
if (!xfread(&str[i], 1, sizeof(char), s))
break;
if (str[i] == '\r')
{
i--;
continue;
}
if (str[i] == '\n')
{
i++;
break;
}
}
str[i] = 0;
return str;
}
wchar_t* __cdecl xfgetws(wchar_t* str, int n, FILE* s)
{
int i;
// Text-mode fgetws converts MBCS->Unicode
if (s->_flag & _FILE_TEXT)
{
char* bfr = (char*)xmalloc(n);
xfgets(bfr, n, s);
MultiByteToWideChar(CP_ACP, 0, bfr, -1, str, n);
xfree(bfr);
return str;
}
// Binary fgetws reads as Unicode
if (xfeof(s))
return 0;
for (i = 0; i < n - 1; i++)
{
if (!xfread(&str[i], 1, sizeof(wchar_t), s))
break;
if (str[i] == L'\r')
{
i--;
continue; // does i++
}
if (str[i] == L'\n')
{
i++;
break;
}
}
str[i] = 0;
return str;
}
int __cdecl xfgetc(FILE* s)
{
char c;
if (s == 0 || xfeof(s))
return EOF;
xfread(&c, 1, sizeof(char), s);
return (int)c;
}
int __cdecl xfputc(int ch, FILE* s)
{
char c;
if (s == 0 || xfeof(s))
return EOF;
xfwrite(&c, 1, sizeof(char), s);
return (int)c;
}
wint_t __cdecl xfgetwc(FILE* s)
{
wint_t c;
if (s == 0 || xfeof(s))
return (wint_t)EOF;
// text-mode fgetwc reads and converts MBCS
if (s->_flag & _FILE_TEXT)
{
char ch = (char)xfgetc(s);
wint_t wch;
MultiByteToWideChar(CP_ACP, 0, &ch, 1, (LPWSTR)&wch, 1);
return wch;
}
// binary fgetwc reads unicode
xfread(&c, 1, sizeof(wint_t), s);
return c;
}
int __cdecl xfflush(FILE* stream)
{
return (FlushFileBuffers(stream->_base) ? 0 : 1);
}
int __cdecl xfileno(FILE* stream)
{
//_VALIDATE_RETURN((stream != NULL), EINVAL, -1);
return stream->_file;
}
int x_vscprintf(const char *format, va_list argptr)
{
HMODULE msvcrt = LoadLibraryA("msvcrt.dll");
@ -960,6 +600,14 @@ int x_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
return (*func)(buffer, count, format, argptr);
}
int xvsprintf_s(char *buffer, size_t numberOfElements, const char *format, va_list argptr)
{
HMODULE msvcrt = LoadLibraryA("msvcrt.dll");
int (__cdecl *func)(char *buffer, size_t numberOfElements, const char *format, va_list argptr) = NULL;
func = (int (__cdecl *)(char *buffer, size_t numberOfElements, const char *format, va_list argptr))GetProcAddress(msvcrt, "vsprintf_s");
return (*func)(buffer, numberOfElements, format, argptr);
}
int xsnprintf(char *s, size_t n, const char *format, ...)
{
size_t r;
@ -971,7 +619,7 @@ int xsnprintf(char *s, size_t n, const char *format, ...)
va_end(vl);
va_start(vl, format);
r = _vsnprintf(s, n, format, vl);
r = x_vsnprintf(s, n, format, vl);
va_end(vl);
if (r >= n)
@ -983,4 +631,48 @@ int xsnprintf(char *s, size_t n, const char *format, ...)
return calculated_size;
}
int xputenv(const char *str)
{
char *name, *value;
char *dst;
int ret;
if (!str)
return -1;
name = xmalloc(strlen(str) + 1);
if (!name)
return -1;
dst = name;
while (*str && *str != '=')
*dst++ = *str++;
if (!*str++)
{
ret = -1;
goto finish;
}
*dst++ = '\0';
value = dst;
while (*str)
*dst++ = *str++;
*dst = '\0';
ret = SetEnvironmentVariableA(name, value[0] ? value : NULL) ? 0 : -1;
/* _putenv returns success on deletion of nonexistent variable, unlike [Rtl]SetEnvironmentVariable */
if ((ret == -1) && (GetLastError() == ERROR_ENVVAR_NOT_FOUND)) ret = 0;
finish:
HeapFree(GetProcessHeap(), 0, name);
return ret;
}
time_t xtime( time_t *destTime )
{
HMODULE msvcrt = LoadLibraryA("msvcrt.dll");
time_t (__cdecl *func)(time_t *destTime) = NULL;
func = (time_t (__cdecl *)(time_t *destTime))GetProcAddress(msvcrt, "time");
return (*func)(destTime);
}
#pragma optimize("", on)

40
crt.h
View File

@ -1,20 +1,5 @@
#include <windows.h>
#ifndef _FILE_DEFINED
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
#define _FILE_DEFINED
#endif
int _init_args();
void _term_args();
void* xmalloc(size_t size);
@ -39,7 +24,9 @@ char* xstrncpy(char* dest, const char* src, size_t n);
const char* xstrchr(const char* str, int ch);
const char* xstrrchr(const char* str, int ch);
char* xstrcat(char* dst, const char* src);
const char* xxstrstr(const char* str, const char* substr);
int xstrncat_s(char * dest, size_t num, const char * source, size_t count);
char* xstrstr(char* str, const char* substr);
char* xstrtok(char* s, const char* delm);
size_t xwcslen(const wchar_t* str);
wchar_t* xwcscpy(wchar_t* dest, const wchar_t* src);
int xwcsicmp(const wchar_t* s1, const wchar_t* s2);
@ -82,24 +69,9 @@ long xatol(const char* str);
int xatoi(const char* str);
long xwtol(const wchar_t* str);
int xwtoi(const wchar_t* str);
FILE* __cdecl xfopen(const char* path, const char* attrs);
FILE* __cdecl _xwfopen(const wchar_t* path, const wchar_t* attrs);
size_t __cdecl xfwrite(const void* buffer, size_t size, size_t count, FILE* str);
int __cdecl xfprintf(FILE* fp, const char* s, ...);
int __cdecl vfprintf(FILE* fp, const char* s, va_list args);
int __cdecl fwprintf(FILE* fp, const wchar_t* s, ...);
int __cdecl xfclose(FILE* fp);
int __cdecl xfeof(FILE* fp);
int __cdecl xfseek(FILE* str, long offset, int origin);
long __cdecl xftell(FILE* fp);
size_t __cdecl xfread(void* buffer, size_t size, size_t count, FILE* str);
char* __cdecl xfgets(char* str, int n, FILE* s);
wchar_t* __cdecl xfgetws(wchar_t* str, int n, FILE* s);
int __cdecl xfgetc(FILE* s);
int __cdecl xfputc(int ch, FILE* s);
wint_t __cdecl xfgetwc(FILE* s);
int __cdecl xfflush(FILE* stream);
int __cdecl xfileno(FILE* stream);
int x_vscprintf(const char *format, va_list argptr);
int x_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr);
int xsnprintf(char *s, size_t n, const char *format, ...);
int xvsprintf_s(char *buffer, size_t numberOfElements, const char *format, va_list argptr);
int xputenv(const char *str);
time_t xtime( time_t *destTime );

View File

@ -1,4 +1,4 @@
#include "../crt.h"
#include "../crt.c"
int main()
{