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.

800 lines
24 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /*++
  4. Copyright (c) 1991 Microsoft Corporation
  5. Module Name:
  6. infload2.c
  7. Abstract:
  8. Routines to lex and preparse a preprocessed INF file, breaking it up
  9. into a series of tokens and overlaying a field-oriented structure
  10. on top of it.
  11. Author:
  12. Ted Miller (tedm) 10-Spetember-1991
  13. --*/
  14. /*
  15. The purpose of this step is to create a tokenized description of
  16. an INF file and to overlay an indexing structure on top of it.
  17. The input is a preprocessed INF file (see infload1.c). Items
  18. referenced in the input in the discussion below are assumed to be
  19. items in the preprocessed version of an INF file. The output
  20. is a buffer with a series of NUL-terminated byte strings that
  21. represent fields, and an array with line indexing information.
  22. The indexing structure is a array of structures. Each struct contains
  23. a pointer to the first field on the line and some flags. The flags and
  24. their functions are described below. Fields are stored such that all
  25. the characters in the output between the pointer to line n and the
  26. pointer to line n+1 are part of line n. Thus locating field x on line
  27. n is a matter of locating the pointer to line n from the indexing array,
  28. and counting x NULs between that pointer and the pointer to line n+1.
  29. A dummy line is placed at the end of the output to eliminate a special
  30. case for the last line in the file.
  31. A field is delineated by a space or comma not inside an operator or
  32. quotes, or by the EOL. Fields thus may not span lines in the input.
  33. A field may contain one or more syntactic structures (operators with
  34. arguments or strings) which are considered logically concatenated.
  35. An operator is a reserved character followed by a left parenthesis,
  36. followed by one or more comma- or space- delineated arguements,
  37. followed by a right parenthesis. This step does not check for the
  38. correct number of arguments. See IsOperatorChar() and GetToken()
  39. below for the current list of reserved characters/operators.
  40. A syntax error will be reported if EOL is encountered before the
  41. operator structure is complete (ie before the balancing right paren).
  42. A right paren that doesn't close an operator has no special semantics.
  43. It's a regular character like any other, as are operators chars that
  44. are not followed by a left parenthesis.
  45. A list is a curly-bracket enclosed set of comma or space-delineated
  46. items (operators and text).
  47. A text string is any sequence of characters that does not include
  48. operator or other reserved characters. Strings, operators, and lists
  49. may be arbitrarily concatenated within fields, list items, and operator
  50. arguments.
  51. The parsing is fully recursive such that lists and operators may
  52. enclose each other to arbitrary depths.
  53. Operators, lists, commas, spaces, right parenthesis, list terminator
  54. characters, and strings are tokenized. There are certain exceptions
  55. which work in concert with the flags in the indexing array to allow
  56. efficient section lookups and key searching.
  57. A section title line is recognized when the first character in an input
  58. line is the left bracket. All characters through the terminating
  59. right bracket form the section name. The sewction name is not
  60. tokenized and there are no special semantics associated with any character
  61. in a section name (including double quotes). A syntax error is
  62. reported if there is no right bracket on the line or if there are
  63. characters on the line beyond the terminating right bracket. This scheme
  64. allows for striaght string compares between a section being searched for
  65. and the strings pointed to by entries in the indexing array marked as
  66. section lines.
  67. A key line is recognized when an unquoted equals sign is seen as the final
  68. character of the first field on a line, or as the first character
  69. of the second field on the line if the fields are separated by a
  70. space. The equals sign is discarded and the text from the beginning of
  71. the line to the character preceeding the equals sign is (literally)
  72. the key. This scheme allows for striaght string compares between a
  73. key being searched for and the strings pointed to by entries in the
  74. indexing array marked as key lines.
  75. The output buffer grows as necessary to hold the preparsed image.
  76. */
  77. #define CtO 1 // Operator
  78. #define CtT 2 // String terminator
  79. #define CtS 4 // Separator
  80. #define CtB (CtO|CtT|CtS) // String Terminator composite
  81. static BYTE charTypeTable [256] =
  82. {
  83. // 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
  84. // 0 1 2 3 4 5 6 7 8 9 11 12 13 13 14 15
  85. /////////////////////////////////////////////////////////////////////////////////////////
  86. /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  87. /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  88. /* 20 */ CtS, 0, 0, CtO, CtO, 0, 0, 0, CtT, CtT, CtO, 0, CtS, 0, 0, 0,
  89. /* 30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CtT, 0,
  90. /* 40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  91. /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CtO, 0,
  92. /* 60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  93. /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CtT, CtO, 0,
  94. /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  95. /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  96. /* 0a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  97. /* 0b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  98. /* 0c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  99. /* 0d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  100. /* 0e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  101. /* 0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  102. };
  103. #define OPERATOR_CHAR(c) (charTypeTable[c] & CtO)
  104. #define SEPARATOR_CHAR(c) (charTypeTable[c] & CtS)
  105. #define STRING_TERMINATOR(c,cNext) (\
  106. (OPERATOR_CHAR(c) && (cNext == '(')) \
  107. || SEPARATOR_CHAR(c) \
  108. || (InOp && (c == ')')) \
  109. || (InList && (c == '}')) )
  110. #define TkVA TOKEN_VARIABLE // $
  111. #define TkLN TOKEN_LIST_FROM_SECTION_NTH_ITEM // ^
  112. #define TkFA TOKEN_FIELD_ADDRESSOR // #
  113. #define TkAI TOKEN_APPEND_ITEM_TO_LIST // >
  114. #define TkNI TOKEN_NTH_ITEM_FROM_LIST // *
  115. #define TkLI TOKEN_LOCATE_ITEM_IN_LIST // ~
  116. #define TkLS TOKEN_LIST_START // {
  117. #define TkLE TOKEN_LIST_END // }
  118. #define TkSP TOKEN_SPACE // ' '
  119. #define TkCM TOKEN_COMMA // ,
  120. #define TkRP TOKEN_RIGHT_PAREN // )
  121. #define Tk__ TOKEN_UNKNOWN // 255
  122. #define TkEL TOKEN_EOL // NUL
  123. // Table used for general token determination
  124. static BYTE tokTypeTable1 [256] =
  125. {
  126. // 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
  127. // 0 1 2 3 4 5 6 7 8 9 11 12 13 13 14 15
  128. /////////////////////////////////////////////////////////////////////////////////////////
  129. /* 00 */TkEL,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  130. /* 10 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  131. /* 20 */TkSP,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,TkRP,Tk__,Tk__,TkCM,Tk__,Tk__,Tk__,
  132. /* 30 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  133. /* 40 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  134. /* 50 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  135. /* 60 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  136. /* 70 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,TkLS,Tk__,TkLE,Tk__,Tk__,
  137. /* 80 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  138. /* 90 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  139. /* 0a */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  140. /* 0b */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  141. /* 0c */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  142. /* 0d */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  143. /* 0e */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  144. /* 0f */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__
  145. };
  146. // Table used for operator determination
  147. static BYTE tokTypeTable2 [256] =
  148. {
  149. // 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
  150. // 0 1 2 3 4 5 6 7 8 9 11 12 13 13 14 15
  151. /////////////////////////////////////////////////////////////////////////////////////////
  152. /* 00 */TkEL,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  153. /* 10 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  154. /* 20 */Tk__,Tk__,Tk__,TkFA,TkVA,Tk__,Tk__,Tk__,Tk__,Tk__,TkNI,Tk__,Tk__,Tk__,Tk__,Tk__,
  155. /* 30 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,TkAI,Tk__,
  156. /* 40 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  157. /* 50 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,TkLN,Tk__,
  158. /* 60 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  159. /* 70 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,TkLI,Tk__,
  160. /* 80 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  161. /* 90 */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  162. /* 0a */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  163. /* 0b */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  164. /* 0c */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  165. /* 0d */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  166. /* 0e */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,
  167. /* 0f */Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__,Tk__
  168. };
  169. #define PREPARSE_MAX_TOKEN 10000
  170. /*
  171. Values used in creating and enlarging the preparse output buffer.
  172. */
  173. #define PREPARSE_BUFFER_INITIAL 65536
  174. #define PREPARSE_BUFFER_DELTA 8192
  175. UINT OutputBufferSize;
  176. UINT OutputImageSize;
  177. PUCHAR OutputBuffer;
  178. UINT INFLineCount;
  179. PINFLINE INFLineArray;
  180. GRC Preparse_Error;
  181. PUCHAR Inputp;
  182. UINT InOp;
  183. UINT InList;
  184. /*
  185. necessary function prototypes
  186. */
  187. BYTE GetToken(VOID);
  188. BYTE PreparseSectionNameLine(VOID);
  189. BYTE PreparseString(VOID);
  190. BYTE PreparseOperator(BYTE OpToken);
  191. BYTE PreparseNextToken(VOID);
  192. BYTE PreparseList(VOID);
  193. USHORT TraverseCountAndEmitString( PUCHAR *pp, PUCHAR pbuff );
  194. BYTE HandleKey(UINT Line);
  195. /*
  196. Set up the output buffer by allocating it to its initial size
  197. and setting up size vars.
  198. Also initialize global vars.
  199. */
  200. BOOL
  201. InitPreparsing(
  202. VOID
  203. )
  204. {
  205. BOOL rc = FALSE;
  206. if((OutputBuffer = SAlloc(PREPARSE_BUFFER_INITIAL)) != NULL) {
  207. rc = TRUE;
  208. OutputBufferSize = PREPARSE_BUFFER_INITIAL;
  209. OutputImageSize = 0;
  210. InOp = 0;
  211. InList = 0;
  212. } else {
  213. Preparse_Error = grcOutOfMemory;
  214. }
  215. return(rc);
  216. }
  217. VOID
  218. Preparse_ErrorTermination(
  219. VOID
  220. )
  221. {
  222. SFree(INFLineArray);
  223. SFree(OutputBuffer);
  224. return;
  225. }
  226. /*
  227. Place a character in the output buffer, making sure that the
  228. output buffer grows as necessary.
  229. */
  230. #define EMIT(c) Preparse_StoreChar(c)
  231. BOOL
  232. Preparse_StoreChar(
  233. UCHAR c
  234. )
  235. {
  236. PUCHAR p;
  237. if(OutputBufferSize == OutputImageSize) {
  238. p = SRealloc(OutputBuffer,
  239. OutputBufferSize + PREPARSE_BUFFER_DELTA
  240. );
  241. if(p == NULL) {
  242. SFree(OutputBuffer);
  243. Preparse_Error = grcOutOfMemory;
  244. return(FALSE);
  245. }
  246. OutputBufferSize += PREPARSE_BUFFER_DELTA;
  247. OutputBuffer = p;
  248. }
  249. OutputBuffer[OutputImageSize++] = c;
  250. return(TRUE);
  251. }
  252. /*
  253. Count the # of NULs in an image. If the image is a preprocessed
  254. INF file (from PreprocessINFFile), then this counts lines.
  255. */
  256. UINT
  257. CountNULs(
  258. PUCHAR Image,
  259. UINT ImageSize
  260. )
  261. {
  262. PUCHAR p;
  263. UINT NULCount = 0;
  264. for(p=Image; p<Image+ImageSize; p++) {
  265. if(*p == '\0') {
  266. NULCount++;
  267. }
  268. }
  269. return(NULCount);
  270. }
  271. GRC
  272. PreparseINFFile(
  273. PUCHAR INFFile,
  274. UINT INFFileSize,
  275. PUCHAR *PreparsedINFFile,
  276. UINT *PreparsedINFFileBufferSize,
  277. PINFLINE *LineArray,
  278. UINT *LineCount
  279. )
  280. {
  281. UINT Line; // current line being processed
  282. BYTE Token;
  283. INFLineCount = CountNULs(INFFile,INFFileSize);
  284. if((INFLineArray = (PINFLINE)SAlloc((INFLineCount+1) * sizeof(INFLINE))) == NULL) {
  285. return(grcOutOfMemory);
  286. }
  287. if(!InitPreparsing()) {
  288. return(Preparse_Error);
  289. }
  290. Inputp = INFFile;
  291. for(Line = 0; Line < INFLineCount; Line++) {
  292. INFLineArray[Line].flags = INFLINE_NORMAL;
  293. INFLineArray[Line].text.offset = OutputImageSize;
  294. if(*Inputp == '[') {
  295. INFLineArray[Line].flags |= INFLINE_SECTION;
  296. if(PreparseSectionNameLine() == TOKEN_ERROR) {
  297. Preparse_ErrorTermination();
  298. return(Preparse_Error);
  299. } else {
  300. continue; // EOL will have been skipped.
  301. }
  302. } else if(HandleKey(Line) == TOKEN_ERROR) {
  303. Preparse_ErrorTermination();
  304. return(Preparse_Error);
  305. }
  306. while(((Token = PreparseNextToken()) != TOKEN_EOL)
  307. && (Token != TOKEN_ERROR))
  308. {
  309. if((Token == TOKEN_COMMA) || (Token == TOKEN_SPACE)) {
  310. if(!EMIT(NUL)) { // terminate field
  311. Preparse_ErrorTermination();
  312. return(Preparse_Error);
  313. }
  314. }
  315. }
  316. if(Token == TOKEN_ERROR) {
  317. Preparse_ErrorTermination();
  318. return(Preparse_Error);
  319. }
  320. Assert(Token == TOKEN_EOL);
  321. if(!EMIT(NUL)) { // terminate field
  322. Preparse_ErrorTermination();
  323. return(Preparse_Error);
  324. }
  325. } // for Line
  326. // place dummy section at end
  327. INFLineArray[INFLineCount].flags = INFLINE_SECTION;
  328. INFLineArray[INFLineCount].text.offset = OutputImageSize;
  329. if(!EMIT(EOL)) {
  330. Preparse_ErrorTermination();
  331. return(Preparse_Error);
  332. }
  333. OutputBuffer = SRealloc(OutputBuffer,OutputImageSize);
  334. Assert(OutputBuffer != NULL); // it was shrinking!
  335. // now xlate offsets into pointers
  336. for(Line = 0; Line < INFLineCount+1; Line++) {
  337. INFLineArray[Line].text.addr = INFLineArray[Line].text.offset + OutputBuffer;
  338. }
  339. *PreparsedINFFileBufferSize = OutputImageSize;
  340. *PreparsedINFFile = OutputBuffer;
  341. *LineArray = INFLineArray;
  342. *LineCount = INFLineCount;
  343. return(grcOkay);
  344. }
  345. BYTE
  346. GetToken(
  347. VOID
  348. )
  349. {
  350. register BYTE Token = TOKEN_UNKNOWN;
  351. if(*Inputp == '\0') {
  352. Inputp++;
  353. return(TOKEN_EOL);
  354. }
  355. // See if it's an operator
  356. if(*(Inputp+1) == '(')
  357. {
  358. Token = tokTypeTable2[*Inputp] ;
  359. }
  360. if(Token != TOKEN_UNKNOWN)
  361. {
  362. Inputp += 2; // skip operator
  363. if(*Inputp == ' ') {
  364. Inputp++; // preprocess is supposed to eliminate
  365. Assert(*Inputp != ' '); // multiple spaces
  366. }
  367. } else {
  368. Assert(*Inputp);
  369. switch ( Token = tokTypeTable1[*Inputp++] )
  370. {
  371. case TOKEN_UNKNOWN: // fast break for most common case
  372. break ;
  373. case TOKEN_LIST_START:
  374. if(*Inputp == ' ') { // eliminate space after {
  375. Inputp++;
  376. Assert(*Inputp != ' '); // preprocess is supposed to eliminate
  377. } // multiple spaces
  378. break;
  379. case TOKEN_RIGHT_PAREN:
  380. if(!InOp)
  381. Token = TOKEN_UNKNOWN;
  382. break;
  383. case TOKEN_LIST_END:
  384. if(!InList)
  385. Token = TOKEN_UNKNOWN;
  386. break;
  387. }
  388. if ( Token == TOKEN_UNKNOWN )
  389. {
  390. Token = TOKEN_STRING ;
  391. Inputp-- ;
  392. }
  393. }
  394. Assert(Token != TOKEN_UNKNOWN);
  395. return(Token);
  396. }
  397. BYTE
  398. PreparseNextToken(
  399. VOID
  400. )
  401. {
  402. BYTE Token;
  403. Token = GetToken();
  404. if(IS_OPERATOR_TOKEN(Token)) {
  405. if((Token = PreparseOperator(Token)) == TOKEN_ERROR) {
  406. return(TOKEN_ERROR);
  407. }
  408. } else if(Token == TOKEN_STRING) {
  409. if((Token = PreparseString()) == TOKEN_ERROR) {
  410. return(TOKEN_ERROR);
  411. }
  412. } else {
  413. switch(Token) {
  414. case TOKEN_LIST_START:
  415. if((Token = PreparseList()) == TOKEN_ERROR) {
  416. return(TOKEN_ERROR);
  417. }
  418. break;
  419. case TOKEN_LIST_END:
  420. case TOKEN_RIGHT_PAREN:
  421. case TOKEN_SPACE:
  422. case TOKEN_COMMA:
  423. if(!EMIT(Token)) {
  424. return(TOKEN_ERROR);
  425. }
  426. break;
  427. }
  428. }
  429. return(Token);
  430. }
  431. BYTE
  432. PreparseOperator(
  433. BYTE OpToken
  434. )
  435. {
  436. BYTE Token;
  437. if(!EMIT(OpToken)) {
  438. return(TOKEN_ERROR);
  439. }
  440. InOp++;
  441. Token = PreparseNextToken();
  442. while((Token != TOKEN_ERROR) && (Token != TOKEN_EOL) && (Token != TOKEN_RIGHT_PAREN)) {
  443. Token = PreparseNextToken();
  444. }
  445. if(Token == TOKEN_RIGHT_PAREN) {
  446. InOp--;
  447. } else if(Token == TOKEN_EOL) {
  448. Preparse_Error = grcBadINF;
  449. }
  450. return((BYTE)(((Token == TOKEN_ERROR) || (Token == TOKEN_EOL))
  451. ? TOKEN_ERROR
  452. : !TOKEN_ERROR
  453. )
  454. );
  455. }
  456. BYTE
  457. PreparseList(
  458. VOID
  459. )
  460. {
  461. BYTE Token;
  462. if(!EMIT(TOKEN_LIST_START)) {
  463. return(TOKEN_ERROR);
  464. }
  465. InList++;
  466. Token = PreparseNextToken();
  467. while((Token != TOKEN_ERROR) && (Token != TOKEN_EOL) && (Token != TOKEN_LIST_END)) {
  468. Token = PreparseNextToken();
  469. }
  470. if(Token == TOKEN_LIST_END) {
  471. InList--;
  472. } else if(Token == TOKEN_EOL) {
  473. Preparse_Error = grcINFBadLine;
  474. }
  475. return((BYTE)(((Token == TOKEN_ERROR) || (Token == TOKEN_EOL))
  476. ? TOKEN_ERROR
  477. : !TOKEN_ERROR
  478. )
  479. );
  480. }
  481. BYTE
  482. PreparseString(
  483. VOID
  484. )
  485. {
  486. PUCHAR p = Inputp;
  487. USHORT StringOutputLength;
  488. int cMarker = 1 ;
  489. int cMark ;
  490. UINT NewImageSize ;
  491. BYTE MarkerBuffer [4] ;
  492. static BYTE StringBuffer [ PREPARSE_MAX_TOKEN ] ;
  493. StringOutputLength = TraverseCountAndEmitString(&p,StringBuffer);
  494. if(StringOutputLength == (USHORT)(-1)) {
  495. return(TOKEN_ERROR);
  496. } else if(StringOutputLength < 100) {
  497. MarkerBuffer[0] = (BYTE)TOKEN_SHORT_STRING + (BYTE)StringOutputLength;
  498. } else if (StringOutputLength <= 355) { // actually 100-355
  499. MarkerBuffer[0] = TOKEN_STRING;
  500. MarkerBuffer[1] = (BYTE)(StringOutputLength - (USHORT)100);
  501. cMarker = 2 ;
  502. } else {
  503. MarkerBuffer[0] = TOKEN_LONG_STRING;
  504. MarkerBuffer[1] = (BYTE)(StringOutputLength / 256);
  505. MarkerBuffer[2] = (BYTE)(StringOutputLength % 256);
  506. cMarker = 3 ;
  507. }
  508. // See if we can do it the fast way
  509. if ( (NewImageSize = OutputImageSize + StringOutputLength + cMarker) < OutputBufferSize )
  510. {
  511. BYTE * pOut = & OutputBuffer[OutputImageSize] ;
  512. for ( cMark = 0 ; cMark < cMarker ; )
  513. *pOut++ = MarkerBuffer[cMark++] ;
  514. memcpy( pOut, StringBuffer, StringOutputLength ) ;
  515. OutputImageSize = NewImageSize ;
  516. Inputp = p ;
  517. }
  518. else // Otherwise, let's do it the slow way
  519. {
  520. for ( cMark = 0 ; cMark < cMarker ; )
  521. {
  522. if ( ! EMIT( MarkerBuffer[cMark++] ) )
  523. return(TOKEN_ERROR);
  524. }
  525. EvalAssert( TraverseCountAndEmitString( & Inputp, NULL ) == StringOutputLength ) ;
  526. }
  527. return(TOKEN_STRING);
  528. }
  529. USHORT
  530. TraverseCountAndEmitString(
  531. PUCHAR *pp,
  532. PUCHAR pbuff
  533. )
  534. {
  535. BOOL InsideQuotes = FALSE;
  536. BOOL Overrun = FALSE ;
  537. USHORT OutputCount = 0;
  538. PUCHAR pbufflimit ;
  539. PUCHAR p = *pp;
  540. if ( pbuff )
  541. {
  542. pbufflimit = pbuff + PREPARSE_MAX_TOKEN ;
  543. }
  544. while((*p != EOL) && (InsideQuotes || !STRING_TERMINATOR(*p,*(p+1))))
  545. {
  546. if(*p == DQUOTE) {
  547. if(InsideQuotes && (*(p+1) == DQUOTE)) {
  548. p += 2;
  549. } else {
  550. InsideQuotes = !InsideQuotes;
  551. p++;
  552. }
  553. } else {
  554. // ordinary character
  555. if(!pbuff)
  556. {
  557. if(!EMIT(*p)) {
  558. return((USHORT)(-1));
  559. }
  560. }
  561. else
  562. {
  563. *pbuff = *p ;
  564. if ( ++pbuff >= pbufflimit )
  565. {
  566. Overrun = TRUE ;
  567. break ;
  568. }
  569. }
  570. OutputCount++;
  571. p++;
  572. }
  573. }
  574. *pp = p;
  575. if ( InsideQuotes || Overrun )
  576. {
  577. Preparse_Error = grcBadINF;
  578. }
  579. return(InsideQuotes ? (USHORT)(-1) : OutputCount);
  580. }
  581. /*
  582. A section name does not use tokens. The name is emitted without the
  583. surrounding [], and terminated by a NUL.
  584. */
  585. BYTE
  586. PreparseSectionNameLine(
  587. VOID
  588. )
  589. {
  590. Assert(*Inputp == '[');
  591. Inputp++; // skip [
  592. while((*Inputp != EOL) && (*Inputp != ']')) {
  593. if(!EMIT(*Inputp)) {
  594. return(TOKEN_ERROR);
  595. }
  596. Inputp++;
  597. }
  598. if(*Inputp == EOL) {
  599. Preparse_Error = grcINFBadSectionLabel;
  600. return(TOKEN_ERROR);
  601. }
  602. Assert(*Inputp == ']');
  603. if(*(++Inputp) == EOL) {
  604. Inputp++;
  605. if(!EMIT(EOL)) {
  606. return(TOKEN_ERROR);
  607. }
  608. return(!TOKEN_ERROR);
  609. } else {
  610. Preparse_Error = grcINFBadSectionLabel;
  611. return(TOKEN_ERROR);
  612. }
  613. }
  614. BYTE
  615. HandleKey(
  616. UINT Line
  617. )
  618. {
  619. BOOL InsideQuotes = FALSE;
  620. UCHAR c;
  621. PUCHAR e,
  622. p = Inputp;
  623. while(c = *p++) {
  624. if(InsideQuotes && (c != DQUOTE)) {
  625. continue;
  626. }
  627. if(c == DQUOTE) {
  628. InsideQuotes = !InsideQuotes;
  629. continue;
  630. }
  631. if(((c == ' ') && (*p == '=')) || (c == '=')) {
  632. INFLineArray[Line].flags |= INFLINE_KEY;
  633. for(e=Inputp; e<=p-2; e++) {
  634. if(*e != DQUOTE) {
  635. if(!EMIT(*e)) {
  636. return(TOKEN_ERROR);
  637. }
  638. }
  639. }
  640. if(!EMIT(NUL)) {
  641. return(TOKEN_ERROR);
  642. }
  643. if(c == ' ') {
  644. p++; // p now is one char beyond = in either case
  645. }
  646. if(*p == ' ') {
  647. p++; // skip trailing space if any
  648. }
  649. Inputp = p;
  650. return(!TOKEN_ERROR);
  651. }
  652. if((c == ' ') || (c == ',')) {
  653. return(!TOKEN_ERROR); // success but no key
  654. }
  655. }
  656. return(!TOKEN_ERROR); // don't bother with syntax checks here
  657. }