]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/CodeTools/TianoTools/Common/ParseInf.c
Restructuring for better separation of Tool packages.
[mirror_edk2.git] / Tools / CodeTools / TianoTools / 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
119 InputBuffer[CharsToCopy - 1] = '\0';\r
120\r
121 //\r
122 // Increment the current file pointer (include the 0x0A)\r
123 //\r
124 InputFile->CurrentFilePointer += CharsToCopy + 1;\r
125\r
126 //\r
127 // Strip any comments\r
128 //\r
129 CharPtr = strstr (InputBuffer, "//");\r
130 if (CharPtr != 0) {\r
131 CharPtr[0] = 0;\r
132 }\r
133 //\r
134 // Return the string\r
135 //\r
136 return InputBuffer;\r
137}\r
138\r
139BOOLEAN\r
140FindSection (\r
141 IN MEMORY_FILE *InputFile,\r
142 IN CHAR8 *Section\r
143 )\r
144/*++\r
145\r
146Routine Description:\r
147\r
148 This function parses a file from the beginning to find a section.\r
149 The section string may be anywhere within a line.\r
150\r
151Arguments:\r
152\r
153 InputFile Memory file image.\r
154 Section Section to search for\r
155\r
156Returns:\r
157\r
158 FALSE if error or EOF\r
159 TRUE if section found\r
160\r
161--*/\r
162{\r
163 CHAR8 InputBuffer[_MAX_PATH];\r
164 CHAR8 *CurrentToken;\r
165\r
166 //\r
167 // Verify input is not NULL\r
168 //\r
169 assert (InputFile->FileImage);\r
170 assert (InputFile->Eof);\r
171 assert (InputFile->CurrentFilePointer);\r
172 assert (Section);\r
173\r
174 //\r
175 // Rewind to beginning of file\r
176 //\r
177 InputFile->CurrentFilePointer = InputFile->FileImage;\r
178\r
179 //\r
180 // Read lines until the section is found\r
181 //\r
182 while (InputFile->CurrentFilePointer < InputFile->Eof) {\r
183 //\r
184 // Read a line\r
185 //\r
186 ReadLine (InputFile, InputBuffer, _MAX_PATH);\r
187\r
188 //\r
189 // Check if the section is found\r
190 //\r
191 CurrentToken = strstr (InputBuffer, Section);\r
192 if (CurrentToken != NULL) {\r
193 return TRUE;\r
194 }\r
195 }\r
196\r
197 return FALSE;\r
198}\r
199\r
200EFI_STATUS\r
201FindToken (\r
202 IN MEMORY_FILE *InputFile,\r
203 IN CHAR8 *Section,\r
204 IN CHAR8 *Token,\r
205 IN UINTN Instance,\r
206 OUT CHAR8 *Value\r
207 )\r
208/*++\r
209\r
210Routine Description:\r
211\r
212 Finds a token value given the section and token to search for.\r
213\r
214Arguments:\r
215\r
216 InputFile Memory file image.\r
217 Section The section to search for, a string within [].\r
218 Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.\r
219 Instance The instance of the token to search for. Zero is the first instance.\r
220 Value The string that holds the value following the =. Must be _MAX_PATH in size.\r
221\r
222Returns:\r
223\r
224 EFI_SUCCESS Value found.\r
225 EFI_ABORTED Format error detected in INF file.\r
226 EFI_INVALID_PARAMETER Input argument was null.\r
227 EFI_LOAD_ERROR Error reading from the file.\r
228 EFI_NOT_FOUND Section/Token/Value not found.\r
229\r
230--*/\r
231{\r
232 CHAR8 InputBuffer[_MAX_PATH];\r
233 CHAR8 *CurrentToken;\r
234 BOOLEAN ParseError;\r
235 BOOLEAN ReadError;\r
236 UINTN Occurrance;\r
237\r
238 //\r
239 // Check input parameters\r
240 //\r
241 if (InputFile->FileImage == NULL ||\r
242 InputFile->Eof == NULL ||\r
243 InputFile->CurrentFilePointer == NULL ||\r
244 Section == NULL ||\r
245 strlen (Section) == 0 ||\r
246 Token == NULL ||\r
247 strlen (Token) == 0 ||\r
248 Value == NULL\r
249 ) {\r
250 return EFI_INVALID_PARAMETER;\r
251 }\r
252 //\r
253 // Initialize error codes\r
254 //\r
255 ParseError = FALSE;\r
256 ReadError = FALSE;\r
257\r
258 //\r
259 // Initialize our instance counter for the search token\r
260 //\r
261 Occurrance = 0;\r
262\r
263 if (FindSection (InputFile, Section)) {\r
264 //\r
265 // Found the desired section, find and read the desired token\r
266 //\r
267 do {\r
268 //\r
269 // Read a line from the file\r
270 //\r
271 if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {\r
272 //\r
273 // Error reading from input file\r
274 //\r
275 ReadError = TRUE;\r
276 break;\r
277 }\r
278 //\r
279 // Get the first non-whitespace string\r
280 //\r
281 CurrentToken = strtok (InputBuffer, " \t\n");\r
282 if (CurrentToken == NULL) {\r
283 //\r
284 // Whitespace line found (or comment) so continue\r
285 //\r
286 CurrentToken = InputBuffer;\r
287 continue;\r
288 }\r
289 //\r
290 // Make sure we have not reached the end of the current section\r
291 //\r
292 if (CurrentToken[0] == '[') {\r
293 break;\r
294 }\r
295 //\r
296 // Compare the current token with the desired token\r
297 //\r
298 if (strcmp (CurrentToken, Token) == 0) {\r
299 //\r
300 // Found it\r
301 //\r
302 //\r
303 // Check if it is the correct instance\r
304 //\r
305 if (Instance == Occurrance) {\r
306 //\r
307 // Copy the contents following the =\r
308 //\r
309 CurrentToken = strtok (NULL, "= \t\n");\r
310 if (CurrentToken == NULL) {\r
311 //\r
312 // Nothing found, parsing error\r
313 //\r
314 ParseError = TRUE;\r
315 } else {\r
316 //\r
317 // Copy the current token to the output value\r
318 //\r
319 strcpy (Value, CurrentToken);\r
320 return EFI_SUCCESS;\r
321 }\r
322 } else {\r
323 //\r
324 // Increment the occurrance found\r
325 //\r
326 Occurrance++;\r
327 }\r
328 }\r
329 } while (\r
330 !ParseError &&\r
331 !ReadError &&\r
332 InputFile->CurrentFilePointer < InputFile->Eof &&\r
333 CurrentToken[0] != '[' &&\r
334 Occurrance <= Instance\r
335 );\r
336 }\r
337 //\r
338 // Distinguish between read errors and INF file format errors.\r
339 //\r
340 if (ReadError) {\r
341 return EFI_LOAD_ERROR;\r
342 }\r
343\r
344 if (ParseError) {\r
345 return EFI_ABORTED;\r
346 }\r
347\r
348 return EFI_NOT_FOUND;\r
349}\r
350\r
351EFI_STATUS\r
352StringToGuid (\r
353 IN CHAR8 *AsciiGuidBuffer,\r
354 OUT EFI_GUID *GuidBuffer\r
355 )\r
356/*++\r
357\r
358Routine Description: \r
359\r
360 Converts a string to an EFI_GUID. The string must be in the \r
361 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.\r
362\r
363Arguments: \r
364\r
365 AsciiGuidBuffer - pointer to ascii string\r
366 GuidBuffer - pointer to destination Guid\r
367\r
368Returns: \r
369\r
370 EFI_ABORTED Could not convert the string\r
371 EFI_SUCCESS The string was successfully converted\r
372 EFI_INVALID_PARAMETER Input parameter is invalid.\r
373\r
374--*/\r
375{\r
376 INT32 Index;\r
377 UINTN Data1;\r
378 UINTN Data2;\r
379 UINTN Data3;\r
380 UINTN Data4[8];\r
381\r
382 if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {\r
383 return EFI_INVALID_PARAMETER;\r
384 }\r
385 //\r
386 // Scan the guid string into the buffer\r
387 //\r
388 Index = sscanf (\r
389 AsciiGuidBuffer,\r
390 "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx",\r
391 &Data1,\r
392 &Data2,\r
393 &Data3,\r
394 &Data4[0],\r
395 &Data4[1],\r
396 &Data4[2],\r
397 &Data4[3],\r
398 &Data4[4],\r
399 &Data4[5],\r
400 &Data4[6],\r
401 &Data4[7]\r
402 );\r
403\r
404 //\r
405 // Verify the correct number of items were scanned.\r
406 //\r
407 if (Index != 11) {\r
408 printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer);\r
409 return EFI_ABORTED;\r
410 }\r
411 //\r
412 // Copy the data into our GUID.\r
413 //\r
414 GuidBuffer->Data1 = (UINT32) Data1;\r
415 GuidBuffer->Data2 = (UINT16) Data2;\r
416 GuidBuffer->Data3 = (UINT16) Data3;\r
417 GuidBuffer->Data4[0] = (UINT8) Data4[0];\r
418 GuidBuffer->Data4[1] = (UINT8) Data4[1];\r
419 GuidBuffer->Data4[2] = (UINT8) Data4[2];\r
420 GuidBuffer->Data4[3] = (UINT8) Data4[3];\r
421 GuidBuffer->Data4[4] = (UINT8) Data4[4];\r
422 GuidBuffer->Data4[5] = (UINT8) Data4[5];\r
423 GuidBuffer->Data4[6] = (UINT8) Data4[6];\r
424 GuidBuffer->Data4[7] = (UINT8) Data4[7];\r
425\r
426 return EFI_SUCCESS;\r
427}\r
428\r
429EFI_STATUS\r
430AsciiStringToUint64 (\r
431 IN CONST CHAR8 *AsciiString,\r
432 IN BOOLEAN IsHex,\r
433 OUT UINT64 *ReturnValue\r
434 )\r
435/*++\r
436\r
437Routine Description:\r
438\r
439 Converts a null terminated ascii string that represents a number into a \r
440 UINT64 value. A hex number may be preceeded by a 0x, but may not be \r
441 succeeded by an h. A number without 0x or 0X is considered to be base 10 \r
442 unless the IsHex input is true.\r
443\r
444Arguments:\r
445\r
446 AsciiString The string to convert.\r
447 IsHex Force the string to be treated as a hex number.\r
448 ReturnValue The return value.\r
449\r
450Returns:\r
451\r
452 EFI_SUCCESS Number successfully converted.\r
453 EFI_ABORTED Invalid character encountered.\r
454\r
455--*/\r
456{\r
457 UINT8 Index;\r
458 UINT64 HexNumber;\r
459 CHAR8 CurrentChar;\r
460\r
461 //\r
462 // Initialize the result\r
463 //\r
464 HexNumber = 0;\r
465\r
466 //\r
467 // Add each character to the result\r
468 //\r
469 if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {\r
470 //\r
471 // Verify string is a hex number\r
472 //\r
473 for (Index = 2; Index < strlen (AsciiString); Index++) {\r
474 if (isxdigit (AsciiString[Index]) == 0) {\r
475 return EFI_ABORTED;\r
476 }\r
477 }\r
478 //\r
479 // Convert the hex string.\r
480 //\r
481 for (Index = 2; AsciiString[Index] != '\0'; Index++) {\r
482 CurrentChar = AsciiString[Index];\r
483 HexNumber *= 16;\r
484 if (CurrentChar >= '0' && CurrentChar <= '9') {\r
485 HexNumber += CurrentChar - '0';\r
486 } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {\r
487 HexNumber += CurrentChar - 'a' + 10;\r
488 } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {\r
489 HexNumber += CurrentChar - 'A' + 10;\r
490 } else {\r
491 //\r
492 // Unrecognized character\r
493 //\r
494 return EFI_ABORTED;\r
495 }\r
496 }\r
497\r
498 *ReturnValue = HexNumber;\r
499 } else {\r
500 //\r
501 // Verify string is a number\r
502 //\r
503 for (Index = 0; Index < strlen (AsciiString); Index++) {\r
504 if (isdigit (AsciiString[Index]) == 0) {\r
505 return EFI_ABORTED;\r
506 }\r
507 }\r
508\r
509 *ReturnValue = atol (AsciiString);\r
510 }\r
511\r
512 return EFI_SUCCESS;\r
513};\r
514\r
515CHAR8 *\r
516ReadLineInStream (\r
517 IN FILE *InputFile,\r
518 IN OUT CHAR8 *InputBuffer\r
519 )\r
520/*++\r
521\r
522Routine Description:\r
523\r
524 This function reads a line, stripping any comments.\r
525 // BUGBUG: This is obsolete once genmake goes away...\r
526\r
527Arguments:\r
528\r
529 InputFile Stream pointer.\r
530 InputBuffer Buffer to read into, must be _MAX_PATH size.\r
531\r
532Returns:\r
533\r
534 NULL if error or EOF\r
535 InputBuffer otherwise\r
536\r
537--*/\r
538{\r
539 CHAR8 *CharPtr;\r
540\r
541 //\r
542 // Verify input parameters are not null\r
543 //\r
544 assert (InputFile);\r
545 assert (InputBuffer);\r
546\r
547 //\r
548 // Read a line\r
549 //\r
550 if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {\r
551 return NULL;\r
552 }\r
553 //\r
554 // Strip any comments\r
555 //\r
556 CharPtr = strstr (InputBuffer, "//");\r
557 if (CharPtr != 0) {\r
558 CharPtr[0] = 0;\r
559 }\r
560\r
561 CharPtr = strstr (InputBuffer, "#");\r
562 if (CharPtr != 0) {\r
563 CharPtr[0] = 0;\r
564 }\r
565 //\r
566 // Return the string\r
567 //\r
568 return InputBuffer;\r
569}\r
570\r
571BOOLEAN\r
572FindSectionInStream (\r
573 IN FILE *InputFile,\r
574 IN CHAR8 *Section\r
575 )\r
576/*++\r
577\r
578Routine Description:\r
579\r
580 This function parses a stream file from the beginning to find a section.\r
581 The section string may be anywhere within a line.\r
582 // BUGBUG: This is obsolete once genmake goes away...\r
583\r
584Arguments:\r
585\r
586 InputFile Stream pointer.\r
587 Section Section to search for\r
588\r
589Returns:\r
590\r
591 FALSE if error or EOF\r
592 TRUE if section found\r
593\r
594--*/\r
595{\r
596 CHAR8 InputBuffer[_MAX_PATH];\r
597 CHAR8 *CurrentToken;\r
598\r
599 //\r
600 // Verify input is not NULL\r
601 //\r
602 assert (InputFile);\r
603 assert (Section);\r
604\r
605 //\r
606 // Rewind to beginning of file\r
607 //\r
608 if (fseek (InputFile, 0, SEEK_SET) != 0) {\r
609 return FALSE;\r
610 }\r
611 //\r
612 // Read lines until the section is found\r
613 //\r
614 while (feof (InputFile) == 0) {\r
615 //\r
616 // Read a line\r
617 //\r
618 ReadLineInStream (InputFile, InputBuffer);\r
619\r
620 //\r
621 // Check if the section is found\r
622 //\r
623 CurrentToken = strstr (InputBuffer, Section);\r
624 if (CurrentToken != NULL) {\r
625 return TRUE;\r
626 }\r
627 }\r
628\r
629 return FALSE;\r
630}\r