Match and link sscanf, string and mbstring

This commit is contained in:
Phillip Stephens 2023-01-18 21:16:39 -08:00
parent a8f8ef18e5
commit eb14c6e0ad
8 changed files with 369 additions and 8 deletions

View File

@ -9,8 +9,9 @@
"cStandard": "c99",
"cppStandard": "c++98",
"intelliSenseMode": "linux-clang-x86",
"compilerPath": ""
"compilerPath": "",
"configurationProvider": "ms-vscode.makefile-tools"
}
],
"version": 4
}
}

View File

@ -57,7 +57,8 @@
"gxpriv.h": "c",
"osfastcast.h": "c",
"osfont.h": "c",
"arq.h": "c"
"arq.h": "c",
"string.h": "c"
},
"files.autoSave": "onFocusChange",
"files.insertFinalNewline": true,

View File

@ -872,15 +872,15 @@ LIBS = [
["Runtime/file_io", True],
["Runtime/errno", True],
["Runtime/FILE_POS", True],
"Runtime/mbstring",
["Runtime/mbstring", True],
["Runtime/mem", True],
["Runtime/mem_funcs", True],
["Runtime/misc_io", True],
"Runtime/printf",
["Runtime/qsort", False],
["Runtime/rand", True],
"Runtime/sscanf",
"Runtime/string",
["Runtime/sscanf", True],
["Runtime/string", True],
["Runtime/float", True],
"Runtime/strtold",
["Runtime/uart_console_io", True],

View File

@ -10,8 +10,9 @@ extern int errno;
#define ENOERR 0
#define EDOM 33
#define ERANGE 34
#define EFPOS 40
#define ESIGPARM 36
#define EFPOS 40
#define EILSEQ 84
#ifdef __cplusplus
}

View File

@ -99,6 +99,21 @@ typedef struct _IO_FILE {
struct _IO_FILE* next_file_struct;
} FILE;
typedef struct {
char* CharStr;
size_t MaxCharCount;
size_t CharsWritten;
} __OutStrCtrl;
typedef struct {
char* NextChar;
int NullCharDetected;
} __InStrCtrl;
#define EOF -1L
enum __ReadProcActions { __GetChar, __UngetChar, __CheckForError };
#define _IONBF 0
#define _IOLBF 1
#define _IOFBF 2
@ -110,7 +125,7 @@ int vprintf(const char* format, va_list arg);
int vsprintf(char* s, const char* format, va_list arg);
size_t fread(const void*, size_t memb_size, size_t num_memb, FILE*);
size_t fwrite(const void*, size_t memb_size, size_t num_memb, FILE*);
int fseek(FILE * file, long offset, int mode);
int fseek(FILE* file, long offset, int mode);
size_t __fwrite(const void*, size_t, size_t, FILE*);
#ifdef __cplusplus

116
src/Runtime/mbstring.c Normal file
View File

@ -0,0 +1,116 @@
#include "errno.h"
#include "stdio.h"
#include "string.h"
#include "wstring.h"
#pragma ANSI_strict off
#ifndef __WINT_TYPE__
#define __WINT_TYPE__ unsigned int
#endif
typedef struct {
int __count;
union {
__WINT_TYPE__ __wch;
char __wchb[4];
} __value; /* Value so far. */
} mbstate_t;
static int is_utf8_complete(const char* s, size_t n);
static int is_utf8_complete(const char* s, size_t n) {
if (n <= 0) /* 0 or fewer characters do not form a valid multibyte character */
return (-1);
if (*s == 0x00)
return (0);
if ((*s & 0x80) == 0x00)
return (1);
else if ((*s & 0xe0) == 0xc0) /* need 2 bytes */
if (n >= 2)
if (((*(s + 1) & 0x80) == 0x80))
return (2);
else
return (-1);
else
return (-2);
else if ((*s & 0xf0) == 0xe0)
if (n >= 3)
if (((*(s + 1) & 0x80) == 0x80) && ((*(s + 2) & 0x80) == 0x80))
return (3);
else
return (-1);
else if (((n == 2) && ((*(s + 1) & 0x80) == 0x80)) || (n == 1))
return (-2);
else
return (-1);
else
return (-1);
}
#pragma dont_inline on
static int unicode_to_UTF8(char* s, wchar_t wchar) {
int number_of_bytes;
wchar_t wide_char;
char* target_ptr;
char first_byte_mark[4] = {0x00, 0x00, 0xc0, 0xe0};
if (!s) {
return 0;
}
wide_char = wchar;
if (wide_char < 0x0080)
number_of_bytes = 1;
else if (wide_char < 0x0800)
number_of_bytes = 2;
else
number_of_bytes = 3;
target_ptr = s + number_of_bytes;
switch (number_of_bytes) {
case 3:
*--target_ptr = (wide_char & 0x003f) | 0x80;
wide_char >>= 6;
case 2:
*--target_ptr = (wide_char & 0x003f) | 0x80;
wide_char >>= 6;
case 1:
*--target_ptr = wide_char | first_byte_mark[number_of_bytes];
}
return (number_of_bytes);
}
#pragma dont_inline reset
int wctomb(char* s, wchar_t wchar) { return (unicode_to_UTF8(s, wchar)); }
size_t wcstombs(char* s, const wchar_t* pwcs, size_t n) {
int chars_written = 0;
int result;
char temp[3];
wchar_t* source;
if (!s || !pwcs)
return (0);
source = (wchar_t*)pwcs;
while (chars_written <= n) {
if (!*source) {
*(s + chars_written) = '\0';
break;
} else {
result = wctomb(temp, *source++);
if ((chars_written + result) <= n) {
strncpy(s + chars_written, temp, result);
chars_written += result;
} else
break;
}
}
return (chars_written);
}

26
src/Runtime/sscanf.c Normal file
View File

@ -0,0 +1,26 @@
#include "stdio.h"
int __StringRead(void* isc, int ch, int Action) {
char ret;
__InStrCtrl* iscp = (__InStrCtrl*)isc;
switch (Action) {
case __GetChar:
ret = *(iscp->NextChar);
if (ret == '\0') {
iscp->NullCharDetected = 1;
return (EOF);
} else {
iscp->NextChar++;
return ((unsigned char)ret);
}
case __UngetChar:
if (!iscp->NullCharDetected)
iscp->NextChar--;
else
iscp->NullCharDetected = 0;
return (ch);
case __CheckForError:
return (iscp->NullCharDetected);
}
return 0;
}

201
src/Runtime/string.c Normal file
View File

@ -0,0 +1,201 @@
#include "string.h"
size_t strlen(const char* str) {
size_t len = -1;
unsigned char* p = (unsigned char*)str - 1;
do {
len++;
} while (*++p);
return len;
}
char*(strcpy)(char* dst, const char* src) {
unsigned char *destb, *fromb;
unsigned int w, t, align;
unsigned int k1;
unsigned int k2;
fromb = (unsigned char*)src;
destb = (unsigned char*)dst;
if ((align = ((int)fromb & 3)) != ((int)destb & 3)) {
goto bytecopy;
}
if (align) {
if ((*destb = *fromb) == 0) {
return dst;
}
for (align = 3 - align; align; align--) {
if ((*(++destb) = *(++fromb)) == 0) {
return dst;
}
}
++destb;
++fromb;
}
k1 = 0x80808080;
k2 = 0xfefefeff;
w = *((int*)(fromb));
t = w + k2;
t &= k1;
if (t) {
goto bytecopy;
}
--((int*)(destb));
do {
*(++((int*)(destb))) = w;
w = *(++((int*)(fromb)));
t = w + k2;
t &= k1;
if (t)
goto adjust;
} while (1);
adjust:
++((int*)(destb));
bytecopy:
if ((*destb = *fromb) == 0)
return (dst);
do {
if ((*(++destb) = *(++fromb)) == 0)
return dst;
} while (1);
return dst;
}
char* strncpy(char* dst, const char* src, size_t n) {
const unsigned char* p = (const unsigned char*)src - 1;
unsigned char* q = (unsigned char*)dst - 1;
unsigned char zero = 0;
n++;
while (--n)
if (!(*++q = *++p)) {
while (--n)
*++q = 0;
break;
}
return dst;
}
int strcmp(const char* str1, const char* str2) {
unsigned char* left = (unsigned char*)str1;
unsigned char* right = (unsigned char*)str2;
unsigned int k1, k2, align, l1, r1, x;
l1 = *left;
r1 = *right;
if (l1 - r1) {
return l1 - r1;
}
if ((align = ((int)left & 3)) != ((int)right & 3)) {
goto bytecopy;
}
if (align) {
if (l1 == 0) {
return 0;
}
for (align = 3 - align; align; align--) {
l1 = *(++left);
r1 = *(++right);
if (l1 - r1) {
return l1 - r1;
}
if (l1 == 0) {
return 0;
}
}
left++;
right++;
}
k1 = 0x80808080;
k2 = 0xfefefeff;
l1 = *(int*)left;
r1 = *(int*)right;
x = l1 + k2;
if (x & k1) {
goto adjust;
}
while (l1 == r1) {
l1 = *(++((int*)(left)));
r1 = *(++((int*)(right)));
x = l1 + k2;
if (x & k1) {
goto adjust;
}
}
if (l1 > r1) {
return 1;
}
return -1;
adjust:
l1 = *left;
r1 = *right;
if (l1 - r1) {
return l1 - r1;
}
bytecopy:
if (l1 == 0) {
return 0;
}
do {
l1 = *(++left);
r1 = *(++right);
if (l1 - r1) {
return l1 - r1;
}
if (l1 == 0) {
return 0;
}
} while (1);
}
int strncmp(const char* str1, const char* str2, size_t n) {
const unsigned char* p1 = (unsigned char*)str1 - 1;
const unsigned char* p2 = (unsigned char*)str2 - 1;
unsigned long c1, c2;
n++;
while (--n) {
if ((c1 = *++p1) != (c2 = *++p2)) {
return (c1 - c2);
} else if (!c1) {
break;
}
}
return 0;
}
char* strchr(const char* str, int chr) {
const unsigned char* p = (unsigned char*)str - 1;
unsigned long c = (chr & 0xff);
unsigned long ch;
while (ch = *++p) {
if (ch == c)
return ((char*)p);
}
return (c ? 0 : (char*)p);
}