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.

370 lines
11 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /*++
  4. Copyright (c) 1991 Microsoft Corporation
  5. Module Name:
  6. infload1.c
  7. Abstract:
  8. Routines to load an INF file and proprocess it, eliminating
  9. comments and line continuations, and collapsing adjacent WS
  10. and NLs.
  11. The result is a series of NUL-terminated lines, with no blank lines
  12. or lines with only comments or whitespace, etc.
  13. Author:
  14. Ted Miller (tedm) 9-Spetember-1991
  15. --*/
  16. /*
  17. The purpose of the preprocessing step is to create a series of
  18. significant lines, with comments stripped out.
  19. The file is read from disk into a single large buffer. A destination
  20. buffer is allocated to hold the preprocessed file. This buffer
  21. is initially the size of the file image but will be reallocated
  22. when proprocessing is completed.
  23. The input image is considered to be a sequence of LF or CR/LF
  24. separated lines. One line in the input file is equivalent to
  25. one line in the output unless the lines are logically joined with
  26. line continuation characters.
  27. - A line continuation character is a non-quoted + which has no
  28. non-space, non-tab, or non-comment text after it on the line.
  29. Line continuation is accomplished by eliminating all characters
  30. from the + through adjacent spaces, tabs, comments, and EOLs.
  31. - Two consecutive double quote characters inside a quoted
  32. string are replaced by a single double quote.
  33. - Semantic double quuote chars (ie, those that begin and
  34. end strings) are replaced by DQUOTE. Double quotes
  35. that are actually part of the string (see first rule) are
  36. emitted as actual double quote chars. This is so that later
  37. steps can tell the difference between two adjacent quoted
  38. strings and a string containing a quoted double quote.
  39. - All strings of consecutive spaces and tabs are replaced
  40. by a single space. A single space is in turn eliminated
  41. if it occurs immediately adjacent to a comma.
  42. - All comments are eliminated. A comment is an unquoted
  43. semi-colon and consists of the rest of the line (to EOL).
  44. - CR/LF or LF are replaced by NUL. The EOL does not result
  45. in any implied actions being carried out -- ie, a terminating
  46. double quote being supplied if none exists in the input.
  47. - Adjacent NULs are never stored in the output. There will
  48. be at most a single consecutive NUL character in the output.
  49. Also, a space following a NUL is eliminated, as is a space
  50. preceeding a NUL.
  51. No syntax errors are reported from this step.
  52. */
  53. PUCHAR CurrentOut; // points to next cell in output image
  54. BOOL InsideQuotes; // self-explanatory flag
  55. #define IsWS(x) (((x) == ' ') || ((x) == '\t'))
  56. #define SkipWS(x) Preprocess_SkipChars(x," \t")
  57. #define SkipWSEOL(x) Preprocess_SkipChars(x," \t\r\n");
  58. #define SkipComment(x) Preprocess_SkipChars(x,"");
  59. #define CtN 0 // Normal char; NOTE: same as ZERO!
  60. #define CtS 1 // Space
  61. #define CtE 2 // EOL
  62. #define CtC 3 // Comma
  63. #define CtF 4 // EOF
  64. static BYTE charTypeTable [256] =
  65. {
  66. // 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
  67. // 0 1 2 3 4 5 6 7 8 9 11 12 13 13 14 15
  68. /////////////////////////////////////////////////////////////////////////////////////////
  69. /* 00 */ CtE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  70. /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CtF, 0, 0, 0, 0, 0,
  71. /* 20 */ CtS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CtC, 0, 0, 0,
  72. /* 30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  73. /* 40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  74. /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  75. /* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  76. /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  77. /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  78. /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  79. /* 0a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  80. /* 0b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  81. /* 0c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  82. /* 0d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  83. /* 0e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  84. /* 0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  85. };
  86. /*
  87. In: pointer to a char
  88. list of chars to skip
  89. Out: pointer to first char not in the skip list
  90. Also: skips comments.
  91. */
  92. VOID
  93. Preprocess_SkipChars(
  94. LPBYTE *StartingLoc,
  95. LPSTR CharList
  96. )
  97. {
  98. UCHAR c;
  99. PUCHAR p = *StartingLoc;
  100. PUCHAR pch;
  101. BOOL InList;
  102. while(1) {
  103. c = *p;
  104. InList = FALSE;
  105. for(pch=CharList; *pch; pch++) {
  106. if(*pch == c) {
  107. InList = TRUE;
  108. break;
  109. }
  110. }
  111. if(!InList) {
  112. /*
  113. We don't need to bother with seeing if we're in quotes
  114. because this routine is never called when we are.
  115. */
  116. if(c == ';') {
  117. while(*(++p) != NL) {
  118. ;
  119. } // at loop exit, p points to NL
  120. } else { // not in skip list and not a comment
  121. *StartingLoc = p;
  122. return;
  123. }
  124. } else { // c is in the list, so skip it
  125. p++;
  126. }
  127. }
  128. }
  129. /*
  130. Create a preprocessed in-memory version of an inf file as follows:
  131. The result is a series of NUL-terminated lines, with no blank lines
  132. or lines with only comments or whitespace, etc.
  133. */
  134. GRC
  135. PreprocessINFFile(
  136. LPSTR FileName,
  137. LPBYTE *ResultBuffer,
  138. UINT *ResultBufferSize
  139. )
  140. {
  141. HANDLE FileHandle;
  142. LONG FileSize;
  143. LPBYTE FileBuffer; // the input
  144. LPBYTE INFBuffer; // the output
  145. LPBYTE p,q; // current char in file image
  146. UCHAR c;
  147. register int iEmit ;
  148. int iEmit2 ;
  149. static UCHAR PreviousChar = EOL;
  150. static PUCHAR PreviousPos;
  151. if((FileHandle = (HANDLE)LongToHandle(_lopen(FileName,OF_READ))) == (HANDLE)(-1)) {
  152. return(grcBadINF);
  153. }
  154. FileSize = _llseek(HandleToUlong(FileHandle),0,2); // move to end of file
  155. _llseek(HandleToUlong(FileHandle),0,0); // move back to start of file
  156. if((FileBuffer = SAlloc(FileSize+2)) == NULL) {
  157. _lclose(HandleToUlong(FileHandle));
  158. return(grcOutOfMemory);
  159. }
  160. if(_lread(HandleToUlong(FileHandle),FileBuffer,(UINT)FileSize) == -1) {
  161. _lclose(HandleToUlong(FileHandle));
  162. SFree(FileBuffer);
  163. return(grcBadINF);
  164. }
  165. _lclose(HandleToUlong(FileHandle));
  166. FileBuffer[FileSize] = NL; // in case last line is incomplete
  167. FileBuffer[FileSize+1] = 0; // to terminate the image
  168. if((INFBuffer = SAlloc(FileSize)) == NULL) {
  169. SFree(FileBuffer);
  170. return(grcOutOfMemory);
  171. }
  172. p = FileBuffer;
  173. CurrentOut = INFBuffer;
  174. InsideQuotes = FALSE;
  175. iEmit = -1 ;
  176. iEmit2 = -1 ;
  177. while(c = *p)
  178. {
  179. if(c == CR) {
  180. p++;
  181. continue;
  182. } else if(c == NL) {
  183. iEmit = 0 ;
  184. p++;
  185. } else if(c == '"') {
  186. if(InsideQuotes && (*(p+1) == '"')) {
  187. // we've got a quoted quote
  188. iEmit = '"' ;
  189. p++; // skip first quote
  190. } else {
  191. InsideQuotes = !InsideQuotes;
  192. iEmit = DQUOTE ;
  193. }
  194. p++;
  195. } else if(InsideQuotes) {
  196. // just spit out the character
  197. iEmit = c ;
  198. p++;
  199. } else if (c == '+') { // line continuation
  200. p++; // skip the +
  201. q = p;
  202. SkipWS(&p);
  203. if((*p == CR) || (*p == NL)) { // line continuation
  204. SkipWSEOL(&p);
  205. } else { // ordinary character
  206. iEmit = '+' ; // p already advanced (above)
  207. if(p != q) { // preserve ws between + and
  208. iEmit2 = ' ' ; // char that follows
  209. }
  210. }
  211. } else if(IsWS(c)) {
  212. iEmit = ' ' ;
  213. SkipWS(&p);
  214. } else if(c == ';') {
  215. SkipComment(&p);
  216. } else {
  217. iEmit = c ; // plain old character
  218. p++;
  219. }
  220. /*
  221. Store a character in the output stream.
  222. Control-z's are eliminated.
  223. Consecutive NL's after the first are eliminated.
  224. WS immediately following a NL is eliminated.
  225. NL immediately following a WS is stored over the WS, eliminating it.
  226. WS immediately before and after a comma is eliminated.
  227. */
  228. if ( iEmit >= 0 )
  229. {
  230. switch ( charTypeTable[iEmit] )
  231. {
  232. case CtN: // Normal stuff
  233. break ;
  234. case CtS: // Space
  235. if( PreviousChar == EOL
  236. ||(!InsideQuotes && (PreviousChar == ',')))
  237. { // don't store WS after NL's or ,'s
  238. iEmit = -1 ;
  239. }
  240. break ;
  241. case CtE: // EOL
  242. if(PreviousChar == EOL) {
  243. iEmit = -1 ; // don't store adjacent NL's
  244. } else if(PreviousChar == ' ') { // WS/NL ==> collapse to NL
  245. CurrentOut = PreviousPos; // back up over the space first
  246. }
  247. InsideQuotes = FALSE; // reset quotes status
  248. break ;
  249. case CtC: // Comma
  250. if ( !InsideQuotes && (PreviousChar == ' ')) {
  251. CurrentOut = PreviousPos;
  252. }
  253. break ;
  254. case CtF: // 0x1a or Ctrl-Z
  255. iEmit= -1 ;
  256. break ;
  257. }
  258. if ( iEmit >= 0 )
  259. {
  260. PreviousChar = (UCHAR)iEmit ;
  261. PreviousPos = CurrentOut;
  262. *CurrentOut++ = (UCHAR)iEmit;
  263. if ( iEmit2 >= 0 )
  264. {
  265. PreviousChar = (UCHAR)iEmit2 ;
  266. PreviousPos = CurrentOut;
  267. *CurrentOut++ = (UCHAR)iEmit2 ;
  268. iEmit2 = -1 ;
  269. }
  270. iEmit = -1 ;
  271. }
  272. }
  273. }
  274. SFree(FileBuffer);
  275. *ResultBufferSize = (UINT)(CurrentOut - INFBuffer) ;
  276. *ResultBuffer = SRealloc(INFBuffer,*ResultBufferSize);
  277. Assert(*ResultBuffer); // it was shrinking!
  278. return(grcOkay);
  279. }