Source code of Windows XP (NT5)
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.

313 lines
7.6 KiB

  1. //---------------------------------------------------------------------------
  2. // Scanner.cpp - supports parsing general text files & lines with
  3. // a ";" style comment (rest of line is comment)
  4. //---------------------------------------------------------------------------
  5. #include "stdafx.h"
  6. #include "scanner.h"
  7. #include "utils.h"
  8. //---------------------------------------------------------------------------
  9. CScanner::CScanner(LPCWSTR pszTextToScan)
  10. {
  11. ResetAll(FALSE);
  12. _p = pszTextToScan;
  13. _pSymbol = NULL;
  14. }
  15. //---------------------------------------------------------------------------
  16. CScanner::~CScanner()
  17. {
  18. ResetAll(TRUE);
  19. }
  20. //---------------------------------------------------------------------------
  21. void CScanner::UseSymbol(LPCWSTR pszSymbol)
  22. {
  23. if (pszSymbol == NULL)
  24. {
  25. if (_pSymbol && *_p)
  26. {
  27. _p = _pSymbol;
  28. }
  29. _pSymbol = NULL;
  30. }
  31. else
  32. {
  33. _pSymbol = _p;
  34. _p = pszSymbol;
  35. }
  36. }
  37. //---------------------------------------------------------------------------
  38. BOOL CScanner::ReadNextLine()
  39. {
  40. if ((! _pszMultiLineBuffer) || (! *_pszMultiLineBuffer)) // end of multiple lines
  41. {
  42. _fEndOfFile = TRUE;
  43. return FALSE;
  44. }
  45. WCHAR *q = _szLineBuff;
  46. while ((*_pszMultiLineBuffer) && (*_pszMultiLineBuffer != '\r') && (*_pszMultiLineBuffer != '\n'))
  47. *q++ = *_pszMultiLineBuffer++;
  48. *q = 0;
  49. if (*_pszMultiLineBuffer == '\r')
  50. _pszMultiLineBuffer++;
  51. if (*_pszMultiLineBuffer == '\n')
  52. _pszMultiLineBuffer++;
  53. _p = _szLineBuff;
  54. _fBlankSoFar = TRUE;
  55. _iLineNum++;
  56. return TRUE;
  57. }
  58. //---------------------------------------------------------------------------
  59. BOOL CScanner::SkipSpaces()
  60. {
  61. while (1)
  62. {
  63. while (IsSpace(*_p))
  64. _p++;
  65. if ((! *_p) || (*_p == ';')) // end of line
  66. {
  67. if ((_fBlankSoFar) && (! _fEndOfFile))
  68. {
  69. ReadNextLine();
  70. continue;
  71. }
  72. if (*_p == ';') // comment
  73. _p += lstrlen(_p); // skip to end of line
  74. return FALSE;
  75. }
  76. //---- good chars on this line ----
  77. _fBlankSoFar = FALSE;
  78. break;
  79. }
  80. return (*_p != 0);
  81. }
  82. //---------------------------------------------------------------------------
  83. BOOL CScanner::GetId(LPWSTR pszIdBuff, DWORD dwMaxLen)
  84. {
  85. if (! dwMaxLen) // must have at least 1 space for NULL terminator
  86. return FALSE;
  87. SkipSpaces();
  88. WCHAR *v = pszIdBuff;
  89. while ((IsNameChar(FALSE)) && (--dwMaxLen))
  90. *v++ = *_p++;
  91. *v = 0;
  92. if (v == pszIdBuff) // no chars found
  93. return FALSE;
  94. if (IsNameChar(FALSE)) // ran out of room
  95. return FALSE;
  96. return TRUE;
  97. }
  98. //---------------------------------------------------------------------------
  99. BOOL CScanner::GetIdPair(LPWSTR pszIdBuff, LPWSTR pszValueBuff, DWORD dwMaxLen)
  100. {
  101. if (! dwMaxLen) // must have at least 1 space for NULL terminator
  102. return FALSE;
  103. if (!GetId(pszIdBuff, dwMaxLen))
  104. return FALSE;
  105. if (!GetChar('='))
  106. return FALSE;
  107. SkipSpaces();
  108. // Take everything until the end of line
  109. lstrcpyn(pszValueBuff, _p, dwMaxLen);
  110. return TRUE;
  111. }
  112. //---------------------------------------------------------------------------
  113. BOOL CScanner::GetFileName(LPWSTR pszFileNameBuff, DWORD dwMaxLen)
  114. {
  115. if (! dwMaxLen) // must have at least 1 space for NULL terminator
  116. return FALSE;
  117. SkipSpaces();
  118. WCHAR *v = pszFileNameBuff;
  119. while ((IsFileNameChar(FALSE)) && (--dwMaxLen))
  120. *v++ = *_p++;
  121. *v = 0;
  122. if (v == pszFileNameBuff) // no chars found
  123. return FALSE;
  124. if (IsFileNameChar(FALSE)) // ran out of room
  125. return FALSE;
  126. return TRUE;
  127. }
  128. //---------------------------------------------------------------------------
  129. BOOL CScanner::GetNumber(int *piVal)
  130. {
  131. SkipSpaces();
  132. if (! IsNumStart())
  133. return FALSE;
  134. *piVal = string2number(_p);
  135. if ((_p[0] == '0') && ((_p[1] == 'x') || (_p[1] == 'X'))) // hex num
  136. _p += 2;
  137. else
  138. _p++; // skip over digit or sign
  139. //---- skip over number ---
  140. while (IsHexDigit(*_p))
  141. _p++;
  142. return TRUE;
  143. }
  144. //---------------------------------------------------------------------------
  145. BOOL CScanner::IsNameChar(BOOL fOkToSkip)
  146. {
  147. if (fOkToSkip)
  148. SkipSpaces();
  149. return ((IsCharAlphaNumericW(*_p)) || (*_p == '_') || (*_p == '-'));
  150. }
  151. //---------------------------------------------------------------------------
  152. BOOL CScanner::IsFileNameChar(BOOL fOkToSkip)
  153. {
  154. if (fOkToSkip)
  155. SkipSpaces();
  156. return ((IsCharAlphaNumericW(*_p)) || (*_p == '_') || (*_p == '-') ||
  157. (*_p == ':') || (*_p == '\\') || (*_p == '.'));
  158. }
  159. //---------------------------------------------------------------------------
  160. BOOL CScanner::IsNumStart()
  161. {
  162. SkipSpaces();
  163. return ((IsDigit(*_p)) || (*_p == '-') || (*_p == '+'));
  164. }
  165. //---------------------------------------------------------------------------
  166. BOOL CScanner::GetChar(const WCHAR val)
  167. {
  168. SkipSpaces();
  169. if (*_p != val)
  170. return FALSE;
  171. _p++; // skip over WCHAR
  172. return TRUE;
  173. }
  174. //---------------------------------------------------------------------------
  175. BOOL CScanner::GetKeyword(LPCWSTR pszKeyword)
  176. {
  177. SkipSpaces();
  178. int len = lstrlenW(pszKeyword);
  179. LPWSTR p = (LPWSTR)alloca( (len+1)*sizeof(WCHAR));
  180. if (! p)
  181. return FALSE;
  182. lstrcpynW(p, _p, len);
  183. if (AsciiStrCmpI(p, pszKeyword)==0)
  184. {
  185. _p += len;
  186. return TRUE;
  187. }
  188. return FALSE;
  189. }
  190. //---------------------------------------------------------------------------
  191. BOOL CScanner::EndOfLine()
  192. {
  193. SkipSpaces();
  194. return (*_p == 0);
  195. }
  196. //---------------------------------------------------------------------------
  197. BOOL CScanner::EndOfFile()
  198. {
  199. return _fEndOfFile;
  200. }
  201. //---------------------------------------------------------------------------
  202. BOOL CScanner::AttachLine(LPCWSTR pszLine)
  203. {
  204. ResetAll(TRUE);
  205. _p = pszLine;
  206. return TRUE;
  207. }
  208. //---------------------------------------------------------------------------
  209. BOOL CScanner::AttachMultiLineBuffer(LPCWSTR pszBuffer, LPCWSTR pszFileName)
  210. {
  211. ResetAll(TRUE);
  212. _p = _szLineBuff;
  213. _pszMultiLineBuffer = pszBuffer;
  214. lstrcpy_truncate(_szFileName, pszFileName, ARRAYSIZE(_szFileName));
  215. return TRUE;
  216. }
  217. //---------------------------------------------------------------------------
  218. HRESULT CScanner::AttachFile(LPCWSTR pszFileName)
  219. {
  220. ResetAll(TRUE);
  221. HRESULT hr = AllocateTextFile(pszFileName, &_pszFileText, NULL);
  222. if (FAILED(hr))
  223. return hr;
  224. _pszMultiLineBuffer = _pszFileText;
  225. lstrcpy_truncate(_szFileName, pszFileName, ARRAYSIZE(_szFileName));
  226. return S_OK;
  227. }
  228. //---------------------------------------------------------------------------
  229. void CScanner::ResetAll(BOOL fPossiblyAllocated)
  230. {
  231. _iLineNum = 0;
  232. _fEndOfFile = FALSE;
  233. _pszMultiLineBuffer = NULL;
  234. _fUnicodeInput = TRUE;
  235. _fBlankSoFar = TRUE;
  236. *_szFileName = 0;
  237. *_szLineBuff = 0;
  238. _p = _szLineBuff;
  239. if (fPossiblyAllocated)
  240. {
  241. if (_pszFileText)
  242. {
  243. LocalFree(_pszFileText);
  244. _pszFileText = NULL;
  245. }
  246. }
  247. else
  248. _pszFileText = NULL;
  249. }
  250. //---------------------------------------------------------------------------
  251. BOOL CScanner::ForceNextLine()
  252. {
  253. ReadNextLine();
  254. if (! SkipSpaces())
  255. return FALSE;
  256. return TRUE;
  257. }
  258. //---------------------------------------------------------------------------