mirror of https://github.com/minexew/Shrine.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
686 lines
13 KiB
686 lines
13 KiB
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 |
|
_STRCPY:: |
|
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 |
|
_STRCMP:: |
|
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 |
|
_STRICMP:: |
|
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 |
|
_STRNCMP:: |
|
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 |
|
_STRNICMP:: |
|
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 _STRCMP I64 StrCmp( |
|
U8 *st1,U8 *st2); //Compare two strings. |
|
_extern _STRICMP I64 StrICmp( |
|
U8 *st1,U8 *st2); //Compare two strings, ignoring case. |
|
_extern _STRNCMP I64 StrNCmp( |
|
U8 *st1,U8 *st2,I64 n); //Compare N bytes in two strings. |
|
_extern _STRNICMP I64 StrNICmp( |
|
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 _STRCPY U0 StrCpy( |
|
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 *LstSub(I64 sub, U8 *lst) |
|
{//Point to lst entry. |
|
//Not efficient. Use an array of U8 ptrs for efficiency. |
|
if (!lst) return NULL; |
|
while (*lst && sub>0) { |
|
while (*lst) //Advance to end of cur entry. |
|
lst++; |
|
lst++; //Skip trailing zero. |
|
if (*lst=='@') //Check for '@' alias lst entry. |
|
lst++; |
|
else |
|
sub--; |
|
} |
|
if (sub||!*lst) |
|
return NULL; |
|
else |
|
return lst; |
|
} |
|
|
|
I64 LstMatch(U8 *needle, U8 *haystack_lst,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_lst) return -1; |
|
n=StrLen(needle); |
|
while (*haystack_lst) { |
|
if (*haystack_lst=='@') { //Check for '@' alias haystack_lst entry |
|
sub--; |
|
haystack_lst++; |
|
} |
|
ptr=needle; |
|
if (flags & LMF_IGNORE_CASE) |
|
while (*ptr && ToUpper(*ptr)==ToUpper(*haystack_lst)) { |
|
ptr++; |
|
haystack_lst++; |
|
} |
|
else |
|
while (*ptr && *ptr==*haystack_lst) { |
|
ptr++; |
|
haystack_lst++; |
|
} |
|
if (!*ptr) { //Did we reach end of needle? |
|
if (!*haystack_lst) //Did we reach end of haystack_lst? |
|
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_lst) //Advance to end of cur entry. |
|
haystack_lst++; |
|
haystack_lst++; //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_cnt,space_cnt2,col=0; |
|
if (*src) |
|
while (TRUE) { |
|
src2=src; |
|
while (*src2==CH_SPACE) |
|
src2++; |
|
space_cnt=src2-src; |
|
while (col+space_cnt>=8) { |
|
space_cnt2=8-col; |
|
if (space_cnt2==1) |
|
*dst++=CH_SPACE; |
|
else { |
|
*dst++='\t'; |
|
chged+=space_cnt2-1; |
|
} |
|
space_cnt-=space_cnt2; |
|
col=0; |
|
} |
|
if (*src2=='\t') { |
|
if (space_cnt==1 && col==7) |
|
*dst++=CH_SPACE; |
|
else |
|
chged+=space_cnt; |
|
*dst++='\t'; |
|
col=0; |
|
} else { |
|
while (space_cnt--) { |
|
*dst++=CH_SPACE; |
|
if (++col==8) |
|
col=0; |
|
} |
|
if (*src2) { |
|
*dst++=*src2; |
|
if (++col==8) |
|
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_SHIFT_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 *StrFirstRem(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) |
|
StrCpy(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 *StrLastRem(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) |
|
StrCpy(dst,ptr+1); |
|
*ptr=0; |
|
} else { |
|
if (dst) |
|
StrCpy(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; |
|
} |
|
|
|
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; |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|