|
|
#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); }
|