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