mirror of https://github.com/lianthony/NT4.0
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.
315 lines
8.5 KiB
315 lines
8.5 KiB
#include "cmd.h"
|
|
|
|
/***
|
|
*
|
|
* This file contains routines for finding the last character and the
|
|
* penultimate (next to last) character of a string. And finally, a routine
|
|
* (prevc) to return a pointer to the previous character given a pointer
|
|
* to an entire string and a pointer to a character within the string.
|
|
*
|
|
* John Tupper, Microsoft
|
|
*/
|
|
|
|
//
|
|
// DbcsLeadCharTable contains 256 BOOL entries. Each entry signifies
|
|
// whether the character used to look-up the table is a DBCS lead byte.
|
|
// This table needs to be updated whenever Cmd's codepage is changed.
|
|
// Dbcsleadchar is accessed by the is_dbcsleadchar macro defined in Cmd.h.
|
|
//
|
|
|
|
//
|
|
// BUGBUG davegi Call this routine whenever the codepage changes i.e. call
|
|
// the (currently non-existent) NLS API to get the lead byte ranges for
|
|
// the current code page. This is currently being done whenever Cmd.exe
|
|
// starts (cmd.c) and probably needs to be done whenever the (currently
|
|
// non-existent) Chcp command is executed. What will we do if someone else
|
|
// (e.g. Mode) changes the code page.
|
|
|
|
BOOLEAN DbcsLeadCharTable[ 256 ];
|
|
|
|
//
|
|
// AnyDbcsLeadChars is an optimization. It tells us of there are any DBCS
|
|
// lead chars currently defined in DbcsLeadCharTable. If it is FALSE, then
|
|
// we don't have to use DBCS aware string functions.
|
|
//
|
|
|
|
extern CPINFO CurrentCPInfo;
|
|
extern UINT CurrentCP;
|
|
BOOLEAN AnyDbcsLeadChars = FALSE;
|
|
|
|
VOID
|
|
InitializeDbcsLeadCharTable(
|
|
)
|
|
|
|
{
|
|
|
|
UINT i, k;
|
|
|
|
if (! GetCPInfo((CurrentCP=GetConsoleOutputCP()), &CurrentCPInfo )) {
|
|
//
|
|
// GetCPInfo failed. What should we do ?
|
|
//
|
|
#ifdef JAPAN
|
|
CurrentCPInfo.LeadByte[0] = 0x81;
|
|
CurrentCPInfo.LeadByte[1] = 0x9f;
|
|
CurrentCPInfo.LeadByte[2] = 0xe0;
|
|
CurrentCPInfo.LeadByte[3] = 0xfc;
|
|
CurrentCPInfo.LeadByte[4] = 0;
|
|
CurrentCPInfo.LeadByte[5] = 0;
|
|
#else /* not JAPAN */
|
|
CurrentCPInfo.LeadByte[0] = 0;
|
|
CurrentCPInfo.LeadByte[1] = 0;
|
|
#endif /* JAPAN */
|
|
}
|
|
|
|
memset( DbcsLeadCharTable, 0, 256 * sizeof (BOOLEAN) );
|
|
for (k=0 ; CurrentCPInfo.LeadByte[k] && CurrentCPInfo.LeadByte[k+1]; k+=2) {
|
|
for (i=CurrentCPInfo.LeadByte[k] ; i<=CurrentCPInfo.LeadByte[k+1] ; i++)
|
|
DbcsLeadCharTable[i] = TRUE;
|
|
}
|
|
if ( CurrentCPInfo.LeadByte[0] && CurrentCPInfo.LeadByte[1] )
|
|
AnyDbcsLeadChars = TRUE;
|
|
else
|
|
AnyDbcsLeadChars = FALSE;
|
|
|
|
}
|
|
|
|
/***
|
|
* mystrchr(string, c) - search a string for a character
|
|
*
|
|
* mystrchr will search through string and return a pointer to the first
|
|
* occurance of the character c. This version of mystrchr knows about
|
|
* double byte characters. Note that c must be a single byte character.
|
|
*
|
|
*/
|
|
|
|
TCHAR *
|
|
mystrchr(TCHAR const *string, TCHAR c)
|
|
{
|
|
int c0;
|
|
|
|
/* handle null seperatly to make main loop easier to code */
|
|
if (string == NULL)
|
|
return(NULL);
|
|
|
|
if (c == NULLC)
|
|
return((TCHAR *)(string + mystrlen(string)));
|
|
|
|
return _tcschr( string, c );
|
|
}
|
|
|
|
|
|
/***
|
|
* mystrrchr(string, c) - search a string for a character
|
|
*
|
|
* mystrchr will search through string and return a pointer to the last
|
|
* occurance of the character c. This version of mystrrchr knows about
|
|
* double byte characters. Note that c must be a single byte character.
|
|
*
|
|
*/
|
|
|
|
TCHAR *
|
|
mystrrchr(TCHAR const *string, TCHAR c)
|
|
{
|
|
int c0;
|
|
TCHAR const *finger = NULL;
|
|
|
|
/* handle null seperatly to make main loop easier to code */
|
|
if ((TCHAR *)string == NULL)
|
|
return(NULL);
|
|
|
|
if ((char)c == NULLC)
|
|
return((TCHAR *)(string + mystrlen(string)));
|
|
|
|
return _tcsrchr( string, c );
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
* mystrcspn (str1, str2) will find the first character of str1 that is also
|
|
* in str2.
|
|
* Return value:
|
|
* if a match is found return the position in str1 where the matching
|
|
* character was found (the first position is 0).
|
|
* If nomatch is found, return the position of the trailing null.
|
|
*/
|
|
|
|
size_t
|
|
mystrcspn(str1, str2)
|
|
TCHAR const *str1;
|
|
TCHAR const *str2;
|
|
{
|
|
TCHAR c;
|
|
int position = 0;
|
|
|
|
if ((str1 == NULL) || (str2 == NULL))
|
|
return (0);
|
|
|
|
/* Since str2 may not contain any double byte characters,
|
|
when we see a double byte character in str1, we just skip it.
|
|
Otherwise, use mystrchr to see if we have a match */
|
|
while (c = *str1++) {
|
|
if (mystrchr(str2, c))
|
|
break;
|
|
position++;
|
|
}
|
|
|
|
return(position);
|
|
}
|
|
|
|
|
|
/***
|
|
* lastc - return a pointer to the last character of the argument string
|
|
* not including the trailing null. If a pointer to a zero length string
|
|
* is passed, a pointer to the original string is returned.
|
|
*/
|
|
TCHAR *lastc(str)
|
|
TCHAR *str;
|
|
{
|
|
TCHAR *last = str;
|
|
|
|
while(*str)
|
|
last = str++;
|
|
|
|
return(last);
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
*
|
|
* penulc returns a pointer to the penultimate (next to last) character
|
|
* of the argument string not including the trailing null.
|
|
* If a pointer to a zero or one length string is passed, a pointer to
|
|
* the orignial string is returned.
|
|
*/
|
|
TCHAR *penulc(str)
|
|
TCHAR *str;
|
|
{
|
|
TCHAR *last = str;
|
|
TCHAR *penul = str;
|
|
|
|
while(*str) {
|
|
penul = last;
|
|
last = str;
|
|
str++;
|
|
}
|
|
return(penul);
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
*
|
|
* prevc(str1, str2) assumes that str2 points to a character within
|
|
* str1. prevc will return a pointer to the previous character (right
|
|
* before str2). If str2 points outside of str1, NULL is returned.
|
|
*/
|
|
|
|
TCHAR *prevc(str1, str2)
|
|
TCHAR *str1, *str2;
|
|
{
|
|
TCHAR *prev = str1;
|
|
|
|
while (str1 != str2) {
|
|
if (!*str1)
|
|
return(NULL);
|
|
prev = str1;
|
|
str1++;
|
|
}
|
|
|
|
return(prev);
|
|
}
|
|
|
|
/****************************************************************
|
|
*
|
|
* ZScan - scan data in an arbitrary segment for ^Zs
|
|
*
|
|
* Purpose:
|
|
* If flag is on, scan buffer for a ^Z. If it is found, update the
|
|
* buffer length and return 0. Otherwise return -1.
|
|
* Double byte characters are taken into account.
|
|
*
|
|
* int ZScan(int flag, long buffer, unsigned *buflenptr, int *skip_first)
|
|
*
|
|
* Args:
|
|
* flag - nonzero if any scanning is to be done
|
|
* buffer - a long pointer to the buffer to use
|
|
* buflenptr - ptr to the length of buffer
|
|
* skip_first - ptr to an integer. The initial value of *skip_first
|
|
* must be 0 on the first call when scanning a file. There
|
|
* after, the caller leaves *skip_first alone. ZScan uses
|
|
* the variable to remember if the first byte of the next
|
|
* buffer is going to be the second have of a double
|
|
* byte character.
|
|
*
|
|
* Returns:
|
|
* See above.
|
|
*
|
|
* Notes:
|
|
* This routine will need to be modified once the MMU code is in the DOS.
|
|
* macro is defined in cmd.h.
|
|
*
|
|
*
|
|
* ZScan
|
|
* if (flag) then
|
|
* buffer = buffer + *skip_first
|
|
* dbcs_flag = 0
|
|
* count = *buflenptr - *skip_first
|
|
* use rep scanb to find first ^Z in buffer
|
|
* if (no ^z was found)
|
|
* goto FZSNoZ
|
|
* do {
|
|
* count++;
|
|
* buffer--;
|
|
* } until (*buffer < 0x80 || count = *buflenptr);
|
|
* while (--count > 0) loop
|
|
* if (dbcs_flag == 0) then
|
|
* if (*buffer == ^Z) then
|
|
* *buflenptr = count
|
|
* return(0)
|
|
* else if (*buffer is a dbcs_lead_char) then
|
|
* dbcs_flag = 1
|
|
* endif
|
|
* endif
|
|
* else
|
|
* dbcs_flag = 0
|
|
* buffer = buffer + 1
|
|
* count = count - 1
|
|
* end loop
|
|
* *skip_first = dbcs_flag
|
|
* endif
|
|
*FZSNoZ:
|
|
* return(-1)
|
|
*----
|
|
****************************************************************/
|
|
|
|
|
|
int
|
|
ZScan(BOOL flag, PTCHAR buf, PULONG buflen, PULONG skip)
|
|
{
|
|
PTCHAR pbuf = buf,
|
|
bufend;
|
|
|
|
TCHAR c0;
|
|
|
|
if ( flag ) {
|
|
pbuf += *skip;
|
|
bufend = buf + *buflen - *skip;
|
|
|
|
while ((pbuf < bufend) && ((c0 = *pbuf) != CTRLZ)) {
|
|
pbuf++;
|
|
}
|
|
|
|
if (c0 == CTRLZ) {
|
|
// *buflen = pbuf+1 - buf;
|
|
*buflen = pbuf - buf;
|
|
*skip = 0;
|
|
return(0);
|
|
} else {
|
|
*skip = pbuf - bufend;
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|