ZealOS/src/Kernel/StrA.CC
TomAwezome db32fdb367 Reformatted entire codebase.
Reformatted DolDoc files, adjusted sprites in documentation to reflect naming changes, corrected keybinding labels in AutoComplete window, fixed formatting error in Tips.DD.

Added DVD Boot AHCI prototyping into Kernel, displays detected AHCI configuration and halts mid-boot.

Small modifications to standard font, slight increase to mouse X and Y speed.
2020-12-23 18:27:18 -05:00

761 lines
15 KiB
HolyC
Executable file

U8 *StrPrintHex(U8 *dst, I64 num; I64 width)
{
U8 *res = dst + width;
dst = res;
while (width--)
{
*--dst = "0123456789ABCDEF"(U8 *)[num & 15];
num >>= 4;
}
return res;
}
U0 PutHex(I64 num, I64 width)
{
U8 buf[17];
if (width > 16)
width = 16;
*StrPrintHex(buf, num, width) = 0;
"%s", buf;
}
asm {
// IN: RAX=NUM TO PRINT
PUT_HEX_U64::
PUSH_C_REGS
PUSH 16
PUSH RAX
CALL &PutHex
POP_C_REGS
RET
PUT_HEX_U32::
PUSH_C_REGS
PUSH 8
PUSH RAX
CALL &PutHex
POP_C_REGS
RET
PUT_HEX_U16::
PUSH_C_REGS
PUSH 4
PUSH RAX
CALL &PutHex
POP_C_REGS
RET
PUT_HEX_U8::
PUSH_C_REGS
PUSH 2
PUSH RAX
CALL &PutHex
POP_C_REGS
RET
PUT_CHARS::
// IN: RAX=Char
PUSH_C_REGS
PUSH RAX
CALL &PutChars
POP_C_REGS
RET
PUT_STR::
// IN: RSI=String
PUSH_C_REGS
PUSH RSI
CALL &PutS
POP_C_REGS
RET
_STRCOPY::
PUSH RBP
MOV RBP, RSP
PUSH RSI
PUSH RDI
MOV RDI, U64 SF_ARG1[RBP]
TEST RDI, RDI
JZ @@15
MOV RSI, U64 SF_ARG2[RBP]
TEST RSI, RSI
JNZ @@05
XOR RAX, RAX
JMP @@10
@@05: LODSB
@@10: STOSB
TEST AL, AL
JNZ @@05
@@15: POP RDI
POP RSI
POP RBP
RET1 16
_STRCOMPARE::
PUSH RBP
MOV RBP, RSP
PUSH RSI
PUSH RDI
MOV RSI, U64 SF_ARG2[RBP]
MOV RDI, U64 SF_ARG1[RBP]
@@05: LODSB
TEST AL, AL
JZ @@20
SCASB
JE @@05
JA @@15
@@10: MOV RAX, 1
JMP @@25
@@15: MOV RAX, -1
JMP @@25
@@20: SCASB
JNE @@10
XOR RAX, RAX
@@25: POP RDI
POP RSI
POP RBP
RET1 16
TO_UPPER::
CMP AL, 'a'
JB @@05
CMP AL, 'z'
JA @@05
ADD AL, 'A' - 'a'
@@05: RET
_STRICOMPARE::
PUSH RBP
MOV RBP, RSP
PUSH RSI
PUSH RDI
MOV RSI, U64 SF_ARG2[RBP]
MOV RDI, U64 SF_ARG1[RBP]
@@05: LODSB
TEST AL, AL
JZ @@30
CMP AL, 'a'
JB @@10
CMP AL, 'z'
JA @@10
ADD AL, 'A' - 'a'
@@10: MOV BL, U8 [RDI]
INC RDI
CMP BL, 'a'
JB @@15
CMP BL, 'z'
JA @@15
ADD BL, 'A' - 'a'
@@15: CMP AL, BL
JE @@05
JA @@25
@@20: MOV RAX, 1
JMP @@35
@@25: MOV RAX, -1
JMP @@35
@@30: MOV BL, U8 [RDI]
TEST BL, BL
JNE @@20
XOR RAX, RAX
@@35: POP RDI
POP RSI
POP RBP
RET1 16
_STRNCOMPARE::
PUSH RBP
MOV RBP, RSP
PUSH RSI
PUSH RDI
MOV RCX, U64 SF_ARG3[RBP]
MOV RSI, U64 SF_ARG2[RBP]
MOV RDI, U64 SF_ARG1[RBP]
@@05: TEST RCX, RCX
JZ @@25
DEC RCX
LODSB
TEST AL, AL
JZ @@20
SCASB
JE @@05
JA @@15
@@10: MOV RAX, 1
JMP @@30
@@15: MOV RAX, -1
JMP @@30
@@20: MOV BL, U8 [RDI]
TEST BL, BL
JNE @@10
@@25: XOR RAX, RAX
@@30: POP RDI
POP RSI
POP RBP
RET1 24
_STRNICOMPARE::
PUSH RBP
MOV RBP, RSP
PUSH RSI
PUSH RDI
MOV RCX, U64 SF_ARG3[RBP]
MOV RSI, U64 SF_ARG2[RBP]
MOV RDI, U64 SF_ARG1[RBP]
@@05: TEST RCX, RCX
JZ @@35
DEC RCX
LODSB
TEST AL, AL
JZ @@30
CMP AL, 'a'
JB @@10
CMP AL, 'z'
JA @@10
ADD AL, 'A' - 'a'
@@10: MOV BL, U8 [RDI]
INC RDI
CMP BL, 'a'
JB @@15
CMP BL, 'z'
JA @@15
ADD BL, 'A' - 'a'
@@15: CMP AL, BL
JE @@05
JA @@25
@@20: MOV RAX, 1
JMP @@40
@@25: MOV RAX, -1
JMP @@40
@@30: SCASB
JNE @@20
@@35: XOR RAX, RAX
@@40: POP RDI
POP RSI
POP RBP
RET1 24
_STRMATCH::
PUSH RBP
MOV RBP, RSP
PUSH RSI
PUSH RDI
MOV RSI, U64 SF_ARG2[RBP]
TEST RSI, RSI
JZ @@25
MOV RDI, U64 SF_ARG1[RBP]
TEST RDI, RDI
JZ @@25
MOV DL, U8 [RDI]
TEST DL, DL
JZ @@20
JMP @@10
@@05: INC RSI
@@10: LODSB
TEST AL, AL
JZ @@25
CMP AL, DL
JNE @@10
DEC RSI
MOV RCX, 1
@@15: MOV AL, U8 [RDI + RCX]
TEST AL, AL
JZ @@20
CMP AL, U8 [RSI + RCX]
JNE @@05
INC RCX
JMP @@15
DEC RSI
@@20: MOV RAX, RSI
JMP @@30
@@25: XOR RAX, RAX
@@30: POP RDI
POP RSI
POP RBP
RET1 16
_STRIMATCH::
PUSH RBP
MOV RBP, RSP
PUSH RSI
PUSH RDI
MOV RSI, U64 SF_ARG2[RBP]
TEST RSI, RSI
JZ @@25
MOV RDI, U64 SF_ARG1[RBP]
TEST RDI, RDI
JZ @@25
MOV AL, U8 [RDI]
CALL TO_UPPER
MOV DL, AL
TEST DL, DL
JZ @@20
JMP @@10
@@05: INC RSI
@@10: LODSB
CALL TO_UPPER
TEST AL, AL
JZ @@25
CMP AL, DL
JNE @@10
DEC RSI
MOV RCX, 1
@@15: MOV AL, U8 [RDI + RCX]
CALL TO_UPPER
TEST AL, AL
JZ @@20
MOV BL, U8 [RSI + RCX]
XCHG AL, BL
CALL TO_UPPER
CMP AL, BL
JNE @@05
INC RCX
JMP @@15
DEC RSI
@@20: MOV RAX, RSI
JMP @@30
@@25: XOR RAX, RAX
@@30: POP RDI
POP RSI
POP RBP
RET1 16
}
_extern _STRCOMPARE I64 StrCompare(U8 *st1, U8 *st2); //Compare two strings.
_extern _STRICOMPARE I64 StrICompare(U8 *st1, U8 *st2); //Compare two strings, ignoring case.
_extern _STRNCOMPARE I64 StrNCompare(U8 *st1, U8 *st2, I64 n); //Compare N bytes in two strings.
_extern _STRNICOMPARE I64 StrNICompare(U8 *st1, U8 *st2, I64 n); //Compare N bytes in two strings, ignoring case.
_extern _STRMATCH U8 *StrMatch(U8 *needle, U8 *haystack_str);//Scan for string in string.
_extern _STRIMATCH U8 *StrIMatch(U8 *needle, U8 *haystack_str);//Scan for string in string, ignoring case.
_extern _STRCOPY U0 StrCopy(U8 *dst, U8 *src); //Copy string.
//These bitmaps go to 0-511 so that $LK,"Lex",A="MN:Lex"$() can use them with $LK,"Token Codes",A="MN:TK_EOF"$.
U32
char_bmp_alpha[16] =
{0x0000000, 0x00000000, 0x87FFFFFF, 0x07FFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_alpha_numeric[16] =
{0x0000000, 0x03FF0000, 0x87FFFFFF, 0x07FFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_alpha_numeric_no_at[16] =
{0x0000000, 0x03FF0000, 0x87FFFFFE, 0x07FFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_word[16] =
{0x0000000, 0x03FF0080, 0x87FFFFFE, 0x07FFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_filename[16] =
{0x0000000, 0x03FF73FB, 0xEFFFFFFF, 0x6FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_dec_numeric[16] =
{0x0000000, 0x03FF0000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_hex_numeric[16] =
{0x0000000, 0x03FF0000, 0x7E, 0x7E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_white_space[16] =
{0x80002600, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_non_eol_white_space[16] =
{0x80000200, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_zero_cr_nl_cursor[16] =
{0x00002421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_zero_tab_cr_nl_cursor[16] =
{0x00002621, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_zero_tab_cr_nl_cursor_dollar[16] =
{0x00002621, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_macro[16] =
{0x80002600, 0xFFFFFFDF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_printable[16] =
{0x80002600, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_displayable[16] =
{0x80000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
char_bmp_safe_dollar[16] =
{0x80000000, 0xFFFFFFEF, 0xFFFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, 0, 0, 0, 0, 0},
//same but no dollar sign
char_bmp_non_eol[16] =
{0xFFFFDBFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
U8 *ListSub(I64 sub, U8 *list)
{//Point to list entry.
//Not efficient. Use an array of U8 ptrs for efficiency.
if (!list)
return NULL;
while (*list && sub > 0)
{
while (*list) //Advance to end of cur entry.
list++;
list++; //Skip trailing zero.
if (*list == '@') //Check for '@' alias list entry.
list++;
else
sub--;
}
if (sub || !*list)
return NULL;
else
return list;
}
I64 ListMatch(U8 *needle, U8 *haystack_list, I64 flags=0)
{//-2 if Ambiguous
// -1 if not found
// Not efficient. Use hash tables for efficiency.
I64 n, sub = 0, res = -1;
U8 *ptr;
Bool exact_match = FALSE;
if (!haystack_list)
return -1;
n = StrLen(needle);
while (*haystack_list)
{
if (*haystack_list == '@')
{ //Check for '@' alias haystack_list entry
sub--;
haystack_list++;
}
ptr = needle;
if (flags & LMF_IGNORE_CASE)
while (*ptr && ToUpper(*ptr) == ToUpper(*haystack_list))
{
ptr++;
haystack_list++;
}
else
while (*ptr && *ptr == *haystack_list)
{
ptr++;
haystack_list++;
}
if (!*ptr)
{ //Did we reach end of needle?
if (!*haystack_list) //Did we reach end of haystack_list?
return sub; //Found Exact match
else
{
if (res != -1)
{
if (!exact_match)
res = -2; //Ambiguous unless later exact match.
}
else
{
if (!(flags & LMF_EXACT))
res = sub;
}
}
}
while (*haystack_list) //Advance to end of cur entry.
haystack_list++;
haystack_list++; //Skip trailing zero
sub++;
}
return res;
}
I64 StrOcc(U8 *src, I64 ch)
{//Count occurrences of a char.
I64 i = 0;
if (!src)
return 0;
while (*src)
if (*src++ == ch)
i++;
return i;
}
I64 Spaces2Tabs(U8 *dst, U8 *src)
{//Src buf with spaces to dst buf without.
U8 *src2;
I64 chged = 0, space_count, space_count2, col = 0;
if (*src)
while (TRUE)
{
src2 = src;
while (*src2 == CH_SPACE)
src2++;
space_count = src2 - src;
while (col + space_count >= 4)
{
space_count2 = 4 - col;
if (space_count2 == 1)
*dst++ = CH_SPACE;
else
{
*dst++ = '\t';
chged += space_count2 - 1;
}
space_count -= space_count2;
col = 0;
}
if (*src2 == '\t')
{
if (space_count == 1 && col == 3)
*dst++ = CH_SPACE;
else
chged += space_count;
*dst++ = '\t';
col = 0;
}
else
{
while (space_count--)
{
*dst++ = CH_SPACE;
if (++col == 4)
col = 0;
}
if (*src2)
{
*dst++ = *src2;
if (++col == 4)
col = 0;
}
else
break;
}
src = ++src2;
}
*dst = 0;
return chged;
}
U8 *StrUtil(U8 *_src, I64 flags)
{//Modifies in place. See $LK,"flags",A="MN:SUF_REM_SPACES"$ for all the options.
U8 *src = _src, *dst = _src;
I64 ch;
if (flags & SUF_REM_LEADING)
while (Bt(char_bmp_white_space, *src))
src++;
while (ch = *src++)
if (Bt(char_bmp_white_space, ch))
{
if (!(flags & SUF_REM_SPACES))
{
if (flags & SUF_SINGLE_SPACE)
{
*dst++ = CH_SPACE;
while ((ch = *src++) && Bt(char_bmp_white_space, ch));
src--;
}
else
*dst++ = ch;
}
}
else if (!(flags & SUF_REM_CTRL_CHARS) || ch >= CH_SPACE)
*dst++ = ch;
*dst = 0;
if (flags & SUF_REM_TRAILING)
while (dst != _src && (!*dst || Bt(char_bmp_white_space, *dst)))
*dst-- = 0;
if (flags & SUF_TO_UPPER)
for (dst = _src; *dst; dst++)
{
ch = *dst;
if ('a' <= ch <= 'z')
*dst = ch - 0x20;
}
if (flags & SUF_TO_LOWER)
for (dst = _src; *dst; dst++)
{
ch = *dst;
if ('A' <= ch <= 'Z')
*dst = ch + 0x20;
}
if (flags & SUF_SAFE_DOLLAR)
for (dst = _src; *dst; dst++)
{
ch = *dst;
if (!Bt(char_bmp_safe_dollar, *dst))
*dst = '.';
}
if (flags & SUF_S2T)
Spaces2Tabs(_src, _src);
return _src;
}
U8 *StrFirstOcc(U8 *src, U8 *marker)
{//Point to 1st occurrence of marker set in str.
I64 ch;
while ((ch = *src++) && !StrOcc(marker, ch));
if (ch)
return src - 1;
else
return NULL;
}
U8 *StrFirstRemove(U8 *src, U8 *marker, U8 *dst=NULL)
{//Remove first str segment and place in dst buf or NULL.
I64 ch;
U8 *ptr = src, *res = dst;
if (dst)
{
while ((ch = *ptr++) && !StrOcc(marker, ch))
*dst++ = ch;
*dst = 0;
}
else
while ((ch = *ptr++) && !StrOcc(marker, ch));
if (ch)
StrCopy(src, ptr);
else
*src = 0;
return res;
}
U8 *StrLastOcc(U8 *src, U8 *marker)
{//Point to last occurrence of market set in str.
I64 ch;
U8 *res = NULL;
while (ch = *src++)
if (StrOcc(marker, ch))
res = src - 1;
return res;
}
U8 *StrLastRemove(U8 *src, U8 *marker, U8 *dst=NULL)
{//Remove last str segment and place in dst buf or NULL.
U8 *ptr;
if (ptr = StrLastOcc(src, marker))
{
if (dst)
StrCopy(dst, ptr + 1);
*ptr = 0;
}
else
{
if (dst)
StrCopy(dst, src);
*src = 0;
}
return dst;
}
U8 *StrFind(U8 *needle, U8 *haystack_str, I64 flags=0)
{//Find needle_str in haystack_str with options.
Bool cont;
U8 *saved_haystack_str = haystack_str;
I64 plen = StrLen(needle);
do
{
cont = FALSE;
if (flags & SFF_IGNORE_CASE)
haystack_str = StrIMatch(needle, haystack_str);
else
haystack_str = StrMatch(needle, haystack_str);
if (haystack_str && flags & SFF_WHOLE_LABELS_BEFORE && haystack_str != saved_haystack_str &&
Bt(char_bmp_alpha_numeric, *(haystack_str - 1)))
{
haystack_str++;
if (*haystack_str)
cont = TRUE;
else
haystack_str = NULL;
}
if (haystack_str && flags & SFF_WHOLE_LABELS_AFTER && Bt(char_bmp_alpha_numeric, *(haystack_str + plen)))
{
haystack_str++;
if (*haystack_str)
cont = TRUE;
else
haystack_str = NULL;
}
}
while (cont);
return haystack_str;
}
U8 *StrReplace(U8 *str, U8 *old, U8 *new, I64 sff_flags=NONE, Bool free_str=FALSE)
{//Replace all instances of old with new in str. New MAlloc()ed string. free_str aids in chain replacement.
U8 *str_start, *str_end = str, *str_loc, *tmpm = NULL;
if (!*old)
{
str_start = StrNew(new);
goto sr_end2;
}
if (!StrCompare(old, new))
goto sr_end;
while (str_loc = str_end = StrFind(old, str_end, sff_flags))
{
str_start = str;
str_end += StrLen(old); //Move start marker past old str, cutting it out
str_start[StrLen(str_start) - StrLen(str_loc)] = '\0'; //End str_start right before where old was
Free(tmpm);
tmpm = MStrPrint("%s%s%s", str_start, new, str_end);
str = tmpm;
}
sr_end:
str_start = StrNew(str);
sr_end2:
if (free_str)
Free(str);
return str_start;
}
Bool WildMatch(U8 *test_str, U8 *wild_str)
{//Wildcard match with '*' and '?'.
I64 ch1, ch2;
U8 *fall_back_src = NULL, *fall_back_wild = NULL;
while (TRUE)
{
if (!(ch1 = *test_str++))
{
if (*wild_str && *wild_str != '*')
return FALSE;
else
return TRUE;
}
else
{
if (!(ch2 = *wild_str++))
return FALSE;
else
{
if (ch2 == '*')
{
fall_back_wild = wild_str - 1;
fall_back_src = test_str;
if (!(ch2 = *wild_str++))
return TRUE;
while (ch2 != ch1)
if (!(ch1 = *test_str++))
return FALSE;
}
else
if (ch2 != '?' && ch1 != ch2)
{
if (fall_back_wild)
{
wild_str = fall_back_wild;
test_str = fall_back_src;
fall_back_wild = NULL;
fall_back_src = NULL;
}
else
return FALSE;
}
}
}
}
}