]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/CCode/Source/Common/ParseInf.c
Update ParseInf to resolve different line separator between WINDOWS and LINUX (\r...
[mirror_edk2.git] / Tools / CCode / Source / Common / ParseInf.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2004, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 ParseInf.c\r
15\r
16Abstract:\r
17\r
18 This contains some useful functions for parsing INF files.\r
19\r
20--*/\r
21\r
878ddf1f 22#include <assert.h>\r
23#include <string.h>\r
24#include <ctype.h>\r
25#include <stdlib.h>\r
ce53a8c3 26#include "ParseInf.h"\r
878ddf1f 27\r
28#ifndef _MAX_PATH\r
29#define _MAX_PATH 500\r
30#endif\r
31\r
32CHAR8 *\r
33ReadLine (\r
34 IN MEMORY_FILE *InputFile,\r
35 IN OUT CHAR8 *InputBuffer,\r
36 IN UINTN MaxLength\r
37 )\r
38/*++\r
39\r
40Routine Description:\r
41\r
42 This function reads a line, stripping any comments.\r
43 The function reads a string from the input stream argument and stores it in \r
44 the input string. ReadLine reads characters from the current file position \r
45 to and including the first newline character, to the end of the stream, or \r
46 until the number of characters read is equal to MaxLength - 1, whichever \r
47 comes first. The newline character, if read, is replaced with a \0. \r
48\r
49Arguments:\r
50\r
51 InputFile Memory file image.\r
52 InputBuffer Buffer to read into, must be _MAX_PATH size.\r
53 MaxLength The maximum size of the input buffer.\r
54\r
55Returns:\r
56\r
57 NULL if error or EOF\r
58 InputBuffer otherwise\r
59\r
60--*/\r
61{\r
62 CHAR8 *CharPtr;\r
63 CHAR8 *EndOfLine;\r
64 UINTN CharsToCopy;\r
65\r
66 //\r
67 // Verify input parameters are not null\r
68 //\r
69 assert (InputBuffer);\r
70 assert (InputFile->FileImage);\r
71 assert (InputFile->Eof);\r
72 assert (InputFile->CurrentFilePointer);\r
73\r
74 //\r
75 // Check for end of file condition\r
76 //\r
77 if (InputFile->CurrentFilePointer >= InputFile->Eof) {\r
78 return NULL;\r
79 }\r
80 //\r
81 // Find the next newline char\r
82 //\r
83 EndOfLine = strchr (InputFile->CurrentFilePointer, '\n');\r
84\r
85 //\r
86 // Determine the number of characters to copy.\r
87 //\r
88 if (EndOfLine == 0) {\r
89 //\r
90 // If no newline found, copy to the end of the file.\r
91 //\r
92 CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;\r
93 } else if (EndOfLine >= InputFile->Eof) {\r
94 //\r
95 // If the newline found was beyond the end of file, copy to the eof.\r
96 //\r
97 CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;\r
98 } else {\r
99 //\r
100 // Newline found in the file.\r
101 //\r
102 CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;\r
103 }\r
104 //\r
105 // If the end of line is too big for the current buffer, set it to the max\r
106 // size of the buffer (leaving room for the \0.\r
107 //\r
108 if (CharsToCopy > MaxLength - 1) {\r
109 CharsToCopy = MaxLength - 1;\r
110 }\r
111 //\r
112 // Copy the line.\r
113 //\r
114 memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy);\r
115\r
116 //\r
117 // Add the null termination over the 0x0D\r
118 //\r
1d940d05 119 if (InputBuffer[CharsToCopy - 1] == '\r') {\r
120\r
121 InputBuffer[CharsToCopy - 1] = '\0';\r
122\r
123 } else {\r
124\r
125 InputBuffer[CharsToCopy] = '\0';\r
126\r
127 }\r
878ddf1f 128\r
129 //\r
130 // Increment the current file pointer (include the 0x0A)\r
131 //\r
132 InputFile->CurrentFilePointer += CharsToCopy + 1;\r
133\r
134 //\r
135 // Strip any comments\r
136 //\r
137 CharPtr = strstr (InputBuffer, "//");\r
138 if (CharPtr != 0) {\r
139 CharPtr[0] = 0;\r
140 }\r
141 //\r
142 // Return the string\r
143 //\r
144 return InputBuffer;\r
145}\r
146\r
147BOOLEAN\r
148FindSection (\r
149 IN MEMORY_FILE *InputFile,\r
150 IN CHAR8 *Section\r
151 )\r
152/*++\r
153\r
154Routine Description:\r
155\r
156 This function parses a file from the beginning to find a section.\r
157 The section string may be anywhere within a line.\r
158\r
159Arguments:\r
160\r
161 InputFile Memory file image.\r
162 Section Section to search for\r
163\r
164Returns:\r
165\r
166 FALSE if error or EOF\r
167 TRUE if section found\r
168\r
169--*/\r
170{\r
171 CHAR8 InputBuffer[_MAX_PATH];\r
172 CHAR8 *CurrentToken;\r
173\r
174 //\r
175 // Verify input is not NULL\r
176 //\r
177 assert (InputFile->FileImage);\r
178 assert (InputFile->Eof);\r
179 assert (InputFile->CurrentFilePointer);\r
180 assert (Section);\r
181\r
182 //\r
183 // Rewind to beginning of file\r
184 //\r
185 InputFile->CurrentFilePointer = InputFile->FileImage;\r
186\r
187 //\r
188 // Read lines until the section is found\r
189 //\r
190 while (InputFile->CurrentFilePointer < InputFile->Eof) {\r
191 //\r
192 // Read a line\r
193 //\r
194 ReadLine (InputFile, InputBuffer, _MAX_PATH);\r
195\r
196 //\r
197 // Check if the section is found\r
198 //\r
199 CurrentToken = strstr (InputBuffer, Section);\r
200 if (CurrentToken != NULL) {\r
201 return TRUE;\r
202 }\r
203 }\r
204\r
205 return FALSE;\r
206}\r
207\r
208EFI_STATUS\r
209FindToken (\r
210 IN MEMORY_FILE *InputFile,\r
211 IN CHAR8 *Section,\r
212 IN CHAR8 *Token,\r
213 IN UINTN Instance,\r
214 OUT CHAR8 *Value\r
215 )\r
216/*++\r
217\r
218Routine Description:\r
219\r
220 Finds a token value given the section and token to search for.\r
221\r
222Arguments:\r
223\r
224 InputFile Memory file image.\r
225 Section The section to search for, a string within [].\r
226 Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.\r
227 Instance The instance of the token to search for. Zero is the first instance.\r
228 Value The string that holds the value following the =. Must be _MAX_PATH in size.\r
229\r
230Returns:\r
231\r
232 EFI_SUCCESS Value found.\r
233 EFI_ABORTED Format error detected in INF file.\r
234 EFI_INVALID_PARAMETER Input argument was null.\r
235 EFI_LOAD_ERROR Error reading from the file.\r
236 EFI_NOT_FOUND Section/Token/Value not found.\r
237\r
238--*/\r
239{\r
240 CHAR8 InputBuffer[_MAX_PATH];\r
241 CHAR8 *CurrentToken;\r
242 BOOLEAN ParseError;\r
243 BOOLEAN ReadError;\r
244 UINTN Occurrance;\r
245\r
246 //\r
247 // Check input parameters\r
248 //\r
249 if (InputFile->FileImage == NULL ||\r
250 InputFile->Eof == NULL ||\r
251 InputFile->CurrentFilePointer == NULL ||\r
252 Section == NULL ||\r
253 strlen (Section) == 0 ||\r
254 Token == NULL ||\r
255 strlen (Token) == 0 ||\r
256 Value == NULL\r
257 ) {\r
258 return EFI_INVALID_PARAMETER;\r
259 }\r
260 //\r
261 // Initialize error codes\r
262 //\r
263 ParseError = FALSE;\r
264 ReadError = FALSE;\r
265\r
266 //\r
267 // Initialize our instance counter for the search token\r
268 //\r
269 Occurrance = 0;\r
270\r
271 if (FindSection (InputFile, Section)) {\r
272 //\r
273 // Found the desired section, find and read the desired token\r
274 //\r
275 do {\r
276 //\r
277 // Read a line from the file\r
278 //\r
279 if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {\r
280 //\r
281 // Error reading from input file\r
282 //\r
283 ReadError = TRUE;\r
284 break;\r
285 }\r
286 //\r
287 // Get the first non-whitespace string\r
288 //\r
289 CurrentToken = strtok (InputBuffer, " \t\n");\r
290 if (CurrentToken == NULL) {\r
291 //\r
292 // Whitespace line found (or comment) so continue\r
293 //\r
294 CurrentToken = InputBuffer;\r
295 continue;\r
296 }\r
297 //\r
298 // Make sure we have not reached the end of the current section\r
299 //\r
300 if (CurrentToken[0] == '[') {\r
301 break;\r
302 }\r
303 //\r
304 // Compare the current token with the desired token\r
305 //\r
306 if (strcmp (CurrentToken, Token) == 0) {\r
307 //\r
308 // Found it\r
309 //\r
310 //\r
311 // Check if it is the correct instance\r
312 //\r
313 if (Instance == Occurrance) {\r
314 //\r
315 // Copy the contents following the =\r
316 //\r
317 CurrentToken = strtok (NULL, "= \t\n");\r
318 if (CurrentToken == NULL) {\r
319 //\r
320 // Nothing found, parsing error\r
321 //\r
322 ParseError = TRUE;\r
323 } else {\r
324 //\r
325 // Copy the current token to the output value\r
326 //\r
327 strcpy (Value, CurrentToken);\r
328 return EFI_SUCCESS;\r
329 }\r
330 } else {\r
331 //\r
332 // Increment the occurrance found\r
333 //\r
334 Occurrance++;\r
335 }\r
336 }\r
337 } while (\r
338 !ParseError &&\r
339 !ReadError &&\r
340 InputFile->CurrentFilePointer < InputFile->Eof &&\r
341 CurrentToken[0] != '[' &&\r
342 Occurrance <= Instance\r
343 );\r
344 }\r
345 //\r
346 // Distinguish between read errors and INF file format errors.\r
347 //\r
348 if (ReadError) {\r
349 return EFI_LOAD_ERROR;\r
350 }\r
351\r
352 if (ParseError) {\r
353 return EFI_ABORTED;\r
354 }\r
355\r
356 return EFI_NOT_FOUND;\r
357}\r
358\r
359EFI_STATUS\r
360StringToGuid (\r
361 IN CHAR8 *AsciiGuidBuffer,\r
362 OUT EFI_GUID *GuidBuffer\r
363 )\r
364/*++\r
365\r
366Routine Description: \r
367\r
368 Converts a string to an EFI_GUID. The string must be in the \r
369 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.\r
370\r
371Arguments: \r
372\r
373 AsciiGuidBuffer - pointer to ascii string\r
374 GuidBuffer - pointer to destination Guid\r
375\r
376Returns: \r
377\r
378 EFI_ABORTED Could not convert the string\r
379 EFI_SUCCESS The string was successfully converted\r
380 EFI_INVALID_PARAMETER Input parameter is invalid.\r
381\r
382--*/\r
383{\r
384 INT32 Index;\r
385 UINTN Data1;\r
386 UINTN Data2;\r
387 UINTN Data3;\r
388 UINTN Data4[8];\r
389\r
390 if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {\r
391 return EFI_INVALID_PARAMETER;\r
392 }\r
393 //\r
394 // Scan the guid string into the buffer\r
395 //\r
396 Index = sscanf (\r
397 AsciiGuidBuffer,\r
398 "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx",\r
399 &Data1,\r
400 &Data2,\r
401 &Data3,\r
402 &Data4[0],\r
403 &Data4[1],\r
404 &Data4[2],\r
405 &Data4[3],\r
406 &Data4[4],\r
407 &Data4[5],\r
408 &Data4[6],\r
409 &Data4[7]\r
410 );\r
411\r
412 //\r
413 // Verify the correct number of items were scanned.\r
414 //\r
415 if (Index != 11) {\r
416 printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer);\r
417 return EFI_ABORTED;\r
418 }\r
419 //\r
420 // Copy the data into our GUID.\r
421 //\r
422 GuidBuffer->Data1 = (UINT32) Data1;\r
423 GuidBuffer->Data2 = (UINT16) Data2;\r
424 GuidBuffer->Data3 = (UINT16) Data3;\r
425 GuidBuffer->Data4[0] = (UINT8) Data4[0];\r
426 GuidBuffer->Data4[1] = (UINT8) Data4[1];\r
427 GuidBuffer->Data4[2] = (UINT8) Data4[2];\r
428 GuidBuffer->Data4[3] = (UINT8) Data4[3];\r
429 GuidBuffer->Data4[4] = (UINT8) Data4[4];\r
430 GuidBuffer->Data4[5] = (UINT8) Data4[5];\r
431 GuidBuffer->Data4[6] = (UINT8) Data4[6];\r
432 GuidBuffer->Data4[7] = (UINT8) Data4[7];\r
433\r
434 return EFI_SUCCESS;\r
435}\r
436\r
437EFI_STATUS\r
438AsciiStringToUint64 (\r
439 IN CONST CHAR8 *AsciiString,\r
440 IN BOOLEAN IsHex,\r
441 OUT UINT64 *ReturnValue\r
442 )\r
443/*++\r
444\r
445Routine Description:\r
446\r
447 Converts a null terminated ascii string that represents a number into a \r
448 UINT64 value. A hex number may be preceeded by a 0x, but may not be \r
449 succeeded by an h. A number without 0x or 0X is considered to be base 10 \r
450 unless the IsHex input is true.\r
451\r
452Arguments:\r
453\r
454 AsciiString The string to convert.\r
455 IsHex Force the string to be treated as a hex number.\r
456 ReturnValue The return value.\r
457\r
458Returns:\r
459\r
460 EFI_SUCCESS Number successfully converted.\r
461 EFI_ABORTED Invalid character encountered.\r
462\r
463--*/\r
464{\r
465 UINT8 Index;\r
466 UINT64 HexNumber;\r
467 CHAR8 CurrentChar;\r
468\r
469 //\r
470 // Initialize the result\r
471 //\r
472 HexNumber = 0;\r
473\r
474 //\r
475 // Add each character to the result\r
476 //\r
477 if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {\r
478 //\r
479 // Verify string is a hex number\r
480 //\r
481 for (Index = 2; Index < strlen (AsciiString); Index++) {\r
482 if (isxdigit (AsciiString[Index]) == 0) {\r
483 return EFI_ABORTED;\r
484 }\r
485 }\r
486 //\r
487 // Convert the hex string.\r
488 //\r
489 for (Index = 2; AsciiString[Index] != '\0'; Index++) {\r
490 CurrentChar = AsciiString[Index];\r
491 HexNumber *= 16;\r
492 if (CurrentChar >= '0' && CurrentChar <= '9') {\r
493 HexNumber += CurrentChar - '0';\r
494 } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {\r
495 HexNumber += CurrentChar - 'a' + 10;\r
496 } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {\r
497 HexNumber += CurrentChar - 'A' + 10;\r
498 } else {\r
499 //\r
500 // Unrecognized character\r
501 //\r
502 return EFI_ABORTED;\r
503 }\r
504 }\r
505\r
506 *ReturnValue = HexNumber;\r
507 } else {\r
508 //\r
509 // Verify string is a number\r
510 //\r
511 for (Index = 0; Index < strlen (AsciiString); Index++) {\r
512 if (isdigit (AsciiString[Index]) == 0) {\r
513 return EFI_ABORTED;\r
514 }\r
515 }\r
516\r
517 *ReturnValue = atol (AsciiString);\r
518 }\r
519\r
520 return EFI_SUCCESS;\r
521};\r
522\r
523CHAR8 *\r
524ReadLineInStream (\r
525 IN FILE *InputFile,\r
526 IN OUT CHAR8 *InputBuffer\r
527 )\r
528/*++\r
529\r
530Routine Description:\r
531\r
532 This function reads a line, stripping any comments.\r
533 // BUGBUG: This is obsolete once genmake goes away...\r
534\r
535Arguments:\r
536\r
537 InputFile Stream pointer.\r
538 InputBuffer Buffer to read into, must be _MAX_PATH size.\r
539\r
540Returns:\r
541\r
542 NULL if error or EOF\r
543 InputBuffer otherwise\r
544\r
545--*/\r
546{\r
547 CHAR8 *CharPtr;\r
548\r
549 //\r
550 // Verify input parameters are not null\r
551 //\r
552 assert (InputFile);\r
553 assert (InputBuffer);\r
554\r
555 //\r
556 // Read a line\r
557 //\r
558 if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {\r
559 return NULL;\r
560 }\r
561 //\r
562 // Strip any comments\r
563 //\r
564 CharPtr = strstr (InputBuffer, "//");\r
565 if (CharPtr != 0) {\r
566 CharPtr[0] = 0;\r
567 }\r
568\r
569 CharPtr = strstr (InputBuffer, "#");\r
570 if (CharPtr != 0) {\r
571 CharPtr[0] = 0;\r
572 }\r
573 //\r
574 // Return the string\r
575 //\r
576 return InputBuffer;\r
577}\r
578\r
579BOOLEAN\r
580FindSectionInStream (\r
581 IN FILE *InputFile,\r
582 IN CHAR8 *Section\r
583 )\r
584/*++\r
585\r
586Routine Description:\r
587\r
588 This function parses a stream file from the beginning to find a section.\r
589 The section string may be anywhere within a line.\r
590 // BUGBUG: This is obsolete once genmake goes away...\r
591\r
592Arguments:\r
593\r
594 InputFile Stream pointer.\r
595 Section Section to search for\r
596\r
597Returns:\r
598\r
599 FALSE if error or EOF\r
600 TRUE if section found\r
601\r
602--*/\r
603{\r
604 CHAR8 InputBuffer[_MAX_PATH];\r
605 CHAR8 *CurrentToken;\r
606\r
607 //\r
608 // Verify input is not NULL\r
609 //\r
610 assert (InputFile);\r
611 assert (Section);\r
612\r
613 //\r
614 // Rewind to beginning of file\r
615 //\r
616 if (fseek (InputFile, 0, SEEK_SET) != 0) {\r
617 return FALSE;\r
618 }\r
619 //\r
620 // Read lines until the section is found\r
621 //\r
622 while (feof (InputFile) == 0) {\r
623 //\r
624 // Read a line\r
625 //\r
626 ReadLineInStream (InputFile, InputBuffer);\r
627\r
628 //\r
629 // Check if the section is found\r
630 //\r
631 CurrentToken = strstr (InputBuffer, Section);\r
632 if (CurrentToken != NULL) {\r
633 return TRUE;\r
634 }\r
635 }\r
636\r
637 return FALSE;\r
638}\r