Windows NT 4.0 source code leak
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

4 years ago
  1. #include "cmd.h"
  2. /***
  3. *
  4. * This file contains routines for finding the last character and the
  5. * penultimate (next to last) character of a string. And finally, a routine
  6. * (prevc) to return a pointer to the previous character given a pointer
  7. * to an entire string and a pointer to a character within the string.
  8. *
  9. * John Tupper, Microsoft
  10. */
  11. //
  12. // DbcsLeadCharTable contains 256 BOOL entries. Each entry signifies
  13. // whether the character used to look-up the table is a DBCS lead byte.
  14. // This table needs to be updated whenever Cmd's codepage is changed.
  15. // Dbcsleadchar is accessed by the is_dbcsleadchar macro defined in Cmd.h.
  16. //
  17. //
  18. // BUGBUG davegi Call this routine whenever the codepage changes i.e. call
  19. // the (currently non-existent) NLS API to get the lead byte ranges for
  20. // the current code page. This is currently being done whenever Cmd.exe
  21. // starts (cmd.c) and probably needs to be done whenever the (currently
  22. // non-existent) Chcp command is executed. What will we do if someone else
  23. // (e.g. Mode) changes the code page.
  24. BOOLEAN DbcsLeadCharTable[ 256 ];
  25. //
  26. // AnyDbcsLeadChars is an optimization. It tells us of there are any DBCS
  27. // lead chars currently defined in DbcsLeadCharTable. If it is FALSE, then
  28. // we don't have to use DBCS aware string functions.
  29. //
  30. extern CPINFO CurrentCPInfo;
  31. extern UINT CurrentCP;
  32. BOOLEAN AnyDbcsLeadChars = FALSE;
  33. VOID
  34. InitializeDbcsLeadCharTable(
  35. )
  36. {
  37. UINT i, k;
  38. if (! GetCPInfo((CurrentCP=GetConsoleOutputCP()), &CurrentCPInfo )) {
  39. //
  40. // GetCPInfo failed. What should we do ?
  41. //
  42. #ifdef JAPAN
  43. CurrentCPInfo.LeadByte[0] = 0x81;
  44. CurrentCPInfo.LeadByte[1] = 0x9f;
  45. CurrentCPInfo.LeadByte[2] = 0xe0;
  46. CurrentCPInfo.LeadByte[3] = 0xfc;
  47. CurrentCPInfo.LeadByte[4] = 0;
  48. CurrentCPInfo.LeadByte[5] = 0;
  49. #else /* not JAPAN */
  50. CurrentCPInfo.LeadByte[0] = 0;
  51. CurrentCPInfo.LeadByte[1] = 0;
  52. #endif /* JAPAN */
  53. }
  54. memset( DbcsLeadCharTable, 0, 256 * sizeof (BOOLEAN) );
  55. for (k=0 ; CurrentCPInfo.LeadByte[k] && CurrentCPInfo.LeadByte[k+1]; k+=2) {
  56. for (i=CurrentCPInfo.LeadByte[k] ; i<=CurrentCPInfo.LeadByte[k+1] ; i++)
  57. DbcsLeadCharTable[i] = TRUE;
  58. }
  59. if ( CurrentCPInfo.LeadByte[0] && CurrentCPInfo.LeadByte[1] )
  60. AnyDbcsLeadChars = TRUE;
  61. else
  62. AnyDbcsLeadChars = FALSE;
  63. }
  64. /***
  65. * mystrchr(string, c) - search a string for a character
  66. *
  67. * mystrchr will search through string and return a pointer to the first
  68. * occurance of the character c. This version of mystrchr knows about
  69. * double byte characters. Note that c must be a single byte character.
  70. *
  71. */
  72. TCHAR *
  73. mystrchr(TCHAR const *string, TCHAR c)
  74. {
  75. int c0;
  76. /* handle null seperatly to make main loop easier to code */
  77. if (string == NULL)
  78. return(NULL);
  79. if (c == NULLC)
  80. return((TCHAR *)(string + mystrlen(string)));
  81. return _tcschr( string, c );
  82. }
  83. /***
  84. * mystrrchr(string, c) - search a string for a character
  85. *
  86. * mystrchr will search through string and return a pointer to the last
  87. * occurance of the character c. This version of mystrrchr knows about
  88. * double byte characters. Note that c must be a single byte character.
  89. *
  90. */
  91. TCHAR *
  92. mystrrchr(TCHAR const *string, TCHAR c)
  93. {
  94. int c0;
  95. TCHAR const *finger = NULL;
  96. /* handle null seperatly to make main loop easier to code */
  97. if ((TCHAR *)string == NULL)
  98. return(NULL);
  99. if ((char)c == NULLC)
  100. return((TCHAR *)(string + mystrlen(string)));
  101. return _tcsrchr( string, c );
  102. }
  103. /***
  104. * mystrcspn (str1, str2) will find the first character of str1 that is also
  105. * in str2.
  106. * Return value:
  107. * if a match is found return the position in str1 where the matching
  108. * character was found (the first position is 0).
  109. * If nomatch is found, return the position of the trailing null.
  110. */
  111. size_t
  112. mystrcspn(str1, str2)
  113. TCHAR const *str1;
  114. TCHAR const *str2;
  115. {
  116. TCHAR c;
  117. int position = 0;
  118. if ((str1 == NULL) || (str2 == NULL))
  119. return (0);
  120. /* Since str2 may not contain any double byte characters,
  121. when we see a double byte character in str1, we just skip it.
  122. Otherwise, use mystrchr to see if we have a match */
  123. while (c = *str1++) {
  124. if (mystrchr(str2, c))
  125. break;
  126. position++;
  127. }
  128. return(position);
  129. }
  130. /***
  131. * lastc - return a pointer to the last character of the argument string
  132. * not including the trailing null. If a pointer to a zero length string
  133. * is passed, a pointer to the original string is returned.
  134. */
  135. TCHAR *lastc(str)
  136. TCHAR *str;
  137. {
  138. TCHAR *last = str;
  139. while(*str)
  140. last = str++;
  141. return(last);
  142. }
  143. /***
  144. *
  145. * penulc returns a pointer to the penultimate (next to last) character
  146. * of the argument string not including the trailing null.
  147. * If a pointer to a zero or one length string is passed, a pointer to
  148. * the orignial string is returned.
  149. */
  150. TCHAR *penulc(str)
  151. TCHAR *str;
  152. {
  153. TCHAR *last = str;
  154. TCHAR *penul = str;
  155. while(*str) {
  156. penul = last;
  157. last = str;
  158. str++;
  159. }
  160. return(penul);
  161. }
  162. /***
  163. *
  164. * prevc(str1, str2) assumes that str2 points to a character within
  165. * str1. prevc will return a pointer to the previous character (right
  166. * before str2). If str2 points outside of str1, NULL is returned.
  167. */
  168. TCHAR *prevc(str1, str2)
  169. TCHAR *str1, *str2;
  170. {
  171. TCHAR *prev = str1;
  172. while (str1 != str2) {
  173. if (!*str1)
  174. return(NULL);
  175. prev = str1;
  176. str1++;
  177. }
  178. return(prev);
  179. }
  180. /****************************************************************
  181. *
  182. * ZScan - scan data in an arbitrary segment for ^Zs
  183. *
  184. * Purpose:
  185. * If flag is on, scan buffer for a ^Z. If it is found, update the
  186. * buffer length and return 0. Otherwise return -1.
  187. * Double byte characters are taken into account.
  188. *
  189. * int ZScan(int flag, long buffer, unsigned *buflenptr, int *skip_first)
  190. *
  191. * Args:
  192. * flag - nonzero if any scanning is to be done
  193. * buffer - a long pointer to the buffer to use
  194. * buflenptr - ptr to the length of buffer
  195. * skip_first - ptr to an integer. The initial value of *skip_first
  196. * must be 0 on the first call when scanning a file. There
  197. * after, the caller leaves *skip_first alone. ZScan uses
  198. * the variable to remember if the first byte of the next
  199. * buffer is going to be the second have of a double
  200. * byte character.
  201. *
  202. * Returns:
  203. * See above.
  204. *
  205. * Notes:
  206. * This routine will need to be modified once the MMU code is in the DOS.
  207. * macro is defined in cmd.h.
  208. *
  209. *
  210. * ZScan
  211. * if (flag) then
  212. * buffer = buffer + *skip_first
  213. * dbcs_flag = 0
  214. * count = *buflenptr - *skip_first
  215. * use rep scanb to find first ^Z in buffer
  216. * if (no ^z was found)
  217. * goto FZSNoZ
  218. * do {
  219. * count++;
  220. * buffer--;
  221. * } until (*buffer < 0x80 || count = *buflenptr);
  222. * while (--count > 0) loop
  223. * if (dbcs_flag == 0) then
  224. * if (*buffer == ^Z) then
  225. * *buflenptr = count
  226. * return(0)
  227. * else if (*buffer is a dbcs_lead_char) then
  228. * dbcs_flag = 1
  229. * endif
  230. * endif
  231. * else
  232. * dbcs_flag = 0
  233. * buffer = buffer + 1
  234. * count = count - 1
  235. * end loop
  236. * *skip_first = dbcs_flag
  237. * endif
  238. *FZSNoZ:
  239. * return(-1)
  240. *----
  241. ****************************************************************/
  242. int
  243. ZScan(BOOL flag, PTCHAR buf, PULONG buflen, PULONG skip)
  244. {
  245. PTCHAR pbuf = buf,
  246. bufend;
  247. TCHAR c0;
  248. if ( flag ) {
  249. pbuf += *skip;
  250. bufend = buf + *buflen - *skip;
  251. while ((pbuf < bufend) && ((c0 = *pbuf) != CTRLZ)) {
  252. pbuf++;
  253. }
  254. if (c0 == CTRLZ) {
  255. // *buflen = pbuf+1 - buf;
  256. *buflen = pbuf - buf;
  257. *skip = 0;
  258. return(0);
  259. } else {
  260. *skip = pbuf - bufend;
  261. }
  262. }
  263. return(-1);
  264. }