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