687 lines
13 KiB
HolyC
687 lines
13 KiB
HolyC
|
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;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|