]>
git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c
3 Copyright (c) 2004 - 2007, 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
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.
18 This module is used to process description files at a high level. For the
19 most part, it pre-parses the file to find and save off positions of all
20 the sections ([section.subsection.subsection]) in a linked list, then
21 provides services to find the sections by name, and read the lines from
22 the section until you run into the next section.
24 NOTE: DSC file is synonomous with section file. A DSC file is simply a file
25 containing bracketed section names [section.subsection.subsection...]
29 #include <stdio.h> // for file ops
32 #include <stdlib.h> // for malloc
36 #define MAX_INCLUDE_NEST_LEVEL 20
53 // Constructor for a DSC file
60 memset ((char *) DSC
, 0, sizeof (DSC_FILE
));
61 DSC
->SavedPositionIndex
= -1;
62 return STATUS_SUCCESS
;
65 // Destructor for a DSC file
72 DSC
->SavedPositionIndex
= -1;
74 return STATUS_SUCCESS
;
77 // Get the next line from a DSC file.
88 if (DSC
->CurrentLine
== NULL
) {
92 // Check for running into next section
94 if (DSC
->CurrentLine
->Line
[0] == '[') {
98 // Allow special case where the line starts with backslash-bracket. If we
99 // see this, then shift everything left one character.
101 if ((DSC
->CurrentLine
->Line
[0] == '\\') && (DSC
->CurrentLine
->Line
[1] == '[')) {
102 Cptr
= DSC
->CurrentLine
->Line
+ 1;
104 Cptr
= DSC
->CurrentLine
->Line
;
107 strncpy (Line
, Cptr
, LineLen
);
108 ParserSetPosition (DSC
->CurrentLine
->FileName
, DSC
->CurrentLine
->LineNum
);
109 DSC
->CurrentLine
= DSC
->CurrentLine
->Next
;
122 Pre-scan a section file to find all the sections. Then we can speed up
123 searching for the different sections.
127 DSC - pointer to a DSC structure (this pointer)
128 FileName - name of the file to process
132 STATUS_SUCCESS if everything went well.
139 // Called to open a new sectioned file.
141 Status
= DSCParseInclude (DSC
, FileName
, 1);
154 SECTION_LINE
*NewLine
;
155 DSC_FILE_NAME
*NewDscFileName
;
156 char Line
[MAX_LINE_LEN
];
161 char ShortHandSectionName
[MAX_LINE_LEN
];
162 char ThisSectionName
[MAX_LINE_LEN
];
170 // Make sure we haven't exceeded our maximum nesting level
172 if (NestLevel
> MAX_INCLUDE_NEST_LEVEL
) {
173 Error (NULL
, 0, 0, "application error", "maximum !include nesting level exceeded");
177 // Try to open the file
179 if ((FilePtr
= fopen (FileName
, "r")) == NULL
) {
181 // This function is called to handle the DSC file from the command line too,
182 // so differentiate whether this file is an include file or the main file
183 // by examining the nest level.
185 if (NestLevel
== 1) {
186 Error (NULL
, 0, 0, FileName
, "could not open DSC file for reading");
188 Error (NULL
, 0, 0, FileName
, "could not open !include DSC file for reading");
194 // We keep a linked list of files we parse for error reporting purposes.
196 NewDscFileName
= malloc (sizeof (DSC_FILE_NAME
));
197 if (NewDscFileName
== NULL
) {
198 Error (__FILE__
, __LINE__
, 0, "memory allocation failed", NULL
);
202 memset (NewDscFileName
, 0, sizeof (DSC_FILE_NAME
));
203 NewDscFileName
->FileName
= (INT8
*) malloc (strlen (FileName
) + 1);
204 if (NewDscFileName
->FileName
== NULL
) {
205 Error (__FILE__
, __LINE__
, 0, "memory allocation failed", NULL
);
209 strcpy (NewDscFileName
->FileName
, FileName
);
210 if (DSC
->FileName
== NULL
) {
211 DSC
->FileName
= NewDscFileName
;
213 DSC
->LastFileName
->Next
= NewDscFileName
;
216 DSC
->LastFileName
= NewDscFileName
;
218 // Read lines and process until done
220 Status
= STATUS_SUCCESS
;
223 if (fgets (Line
, sizeof (Line
), FilePtr
) == NULL
) {
228 ParserSetPosition (FileName
, LineNum
);
230 // Add the line to our list if it's not a !include line
232 if ((strncmp (Line
, "!include", 8) == 0) && (isspace (Line
[8]))) {
234 while (*Start
&& (*Start
!= '"')) {
239 Error (FileName
, LineNum
, 0, NULL
, "invalid format for !include");
240 Status
= STATUS_ERROR
;
245 for (End
= Start
; *End
&& (*End
!= '"'); End
++)
248 Error (FileName
, LineNum
, 0, NULL
, "invalid format for !include");
249 Status
= STATUS_ERROR
;
255 // Expand symbols. Use 'ThisSectionName' as scratchpad
257 ExpandSymbols (Start
, ThisSectionName
, sizeof (ThisSectionName
), EXPANDMODE_NO_UNDEFS
);
258 Status
= DSCParseInclude (DSC
, ThisSectionName
, NestLevel
+ 1);
259 if (Status
!= STATUS_SUCCESS
) {
260 Error (FileName
, LineNum
, 0, NULL
, "failed to parse !include file");
264 NewLine
= (SECTION_LINE
*) malloc (sizeof (SECTION_LINE
));
265 if (NewLine
== NULL
) {
266 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
267 Status
= STATUS_ERROR
;
271 memset ((char *) NewLine
, 0, sizeof (SECTION_LINE
));
272 NewLine
->LineNum
= LineNum
;
273 NewLine
->FileName
= NewDscFileName
->FileName
;
274 NewLine
->Line
= (char *) malloc (strlen (Line
) + 1);
275 if (NewLine
->Line
== NULL
) {
276 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
277 Status
= STATUS_ERROR
;
281 strcpy (NewLine
->Line
, Line
);
282 if (DSC
->Lines
== NULL
) {
283 DSC
->Lines
= NewLine
;
285 DSC
->LastLine
->Next
= NewLine
;
288 DSC
->LastLine
= NewLine
;
290 // Parse the line for []. Ignore [] and [----] delimiters. The
291 // line may have multiple definitions separated by commas, so
292 // take each separately
295 if ((Line
[0] == '[') && ((Line
[1] != ']') && (Line
[1] != '-'))) {
297 // Skip over open bracket and preceeding spaces
300 ShortHandSectionName
[0] = 0;
302 while (*Start
&& (*Start
!= ']')) {
303 while (isspace (*Start
)) {
307 // Hack off closing bracket or trailing spaces or comma separator.
308 // Also allow things like [section.subsection1|subsection2], which
309 // is shorthand for [section.subsection1,section.subsection2]
312 while (*End
&& (*End
!= ']') && !isspace (*End
) && (*End
!= ',') && (*End
!= '|')) {
316 // Save the character and null-terminate the string
321 // Now allocate space for a new section and add it to the linked list.
322 // If the previous section ended with the shorthand indicator, then
323 // the section name was saved off. Append this section name to it.
325 strcpy (ThisSectionName
, ShortHandSectionName
);
327 strcat (ThisSectionName
, Start
+ 1);
329 strcat (ThisSectionName
, Start
);
332 // Allocate memory for the section. Then clear it out.
334 NewSect
= (SECTION
*) malloc (sizeof (SECTION
));
335 if (NewSect
== NULL
) {
336 Error (NULL
, 0, 0, NULL
, "failed to allocation memory for sections");
337 Status
= STATUS_ERROR
;
341 memset ((char *) NewSect
, 0, sizeof (SECTION
));
342 NewSect
->FirstLine
= NewLine
;
343 NewSect
->Name
= (char *) malloc (strlen (ThisSectionName
) + 1);
344 if (NewSect
->Name
== NULL
) {
345 Error (NULL
, 0, 0, NULL
, "failed to allocation memory for sections");
346 Status
= STATUS_ERROR
;
350 strcpy (NewSect
->Name
, ThisSectionName
);
351 if (DSC
->Sections
== NULL
) {
352 DSC
->Sections
= NewSect
;
354 DSC
->LastSection
->Next
= NewSect
;
357 DSC
->LastSection
= NewSect
;
360 // If the name ended in a shorthand indicator, then save the
361 // section name and truncate it at the last dot.
363 if (SaveChar
== '|') {
364 strcpy (ShortHandSectionName
, ThisSectionName
);
365 for (TempCptr
= ShortHandSectionName
+ strlen (ShortHandSectionName
) - 1;
366 (TempCptr
!= ShortHandSectionName
) && (*TempCptr
!= '.');
371 // If we didn't find a dot, then hopefully they have [name1|name2]
372 // instead of [name1,name2].
374 if (TempCptr
== ShortHandSectionName
) {
375 ShortHandSectionName
[0] = 0;
378 // Truncate after the dot
384 // Kill the shorthand string
386 ShortHandSectionName
[0] = 0;
389 // Skip to next section name or closing bracket
391 while (*End
&& ((*End
== ',') || isspace (*End
) || (*End
== '|'))) {
401 // Look through all the sections to make sure we don't have any duplicates.
402 // Allow [----] and [====] section separators
404 CurrSect
= DSC
->Sections
;
405 while (CurrSect
!= NULL
) {
406 TempSect
= CurrSect
->Next
;
407 while (TempSect
!= NULL
) {
408 if (isalpha (CurrSect
->Name
[0]) && (_stricmp (CurrSect
->Name
, TempSect
->Name
) == 0)) {
410 TempSect
->FirstLine
->FileName
,
411 TempSect
->FirstLine
->LineNum
,
414 "duplicate section found"
417 CurrSect
->FirstLine
->FileName
,
418 CurrSect
->FirstLine
->LineNum
,
421 "first definition of duplicate section"
423 Status
= STATUS_ERROR
;
427 TempSect
= TempSect
->Next
;
430 CurrSect
= CurrSect
->Next
;
438 // Free up memory allocated for DSC file handling.
446 SECTION
*NextSection
;
447 SECTION_LINE
*NextLine
;
448 DSC_FILE_NAME
*NextName
;
450 while (DSC
->Sections
!= NULL
) {
451 NextSection
= DSC
->Sections
->Next
;
452 if (DSC
->Sections
->Name
!= NULL
) {
453 free (DSC
->Sections
->Name
);
456 free (DSC
->Sections
);
457 DSC
->Sections
= NextSection
;
460 while (DSC
->Lines
!= NULL
) {
461 NextLine
= DSC
->Lines
->Next
;
462 free (DSC
->Lines
->Line
);
464 DSC
->Lines
= NextLine
;
467 while (DSC
->FileName
!= NULL
) {
468 NextName
= DSC
->FileName
->Next
;
469 free (DSC
->FileName
->FileName
);
470 free (DSC
->FileName
);
471 DSC
->FileName
= NextName
;
484 // Look through all the sections to find one with this name (case insensitive)
486 Sect
= DSC
->Sections
;
487 while (Sect
!= NULL
) {
488 if (_stricmp (Name
, Sect
->Name
) == 0) {
490 // Position within file
492 DSC
->CurrentLine
= Sect
->FirstLine
->Next
;
503 DSCFileSavePosition (
508 // Advance to next slot
510 DSC
->SavedPositionIndex
++;
511 if (DSC
->SavedPositionIndex
>= MAX_SAVES
) {
512 DSC
->SavedPositionIndex
--;
513 Error (NULL
, 0, 0, "APP ERROR", "max nesting of saved section file positions exceeded");
517 DSC
->SavedPosition
[DSC
->SavedPositionIndex
] = DSC
->CurrentLine
;
518 return STATUS_SUCCESS
;
522 DSCFileRestorePosition (
526 if (DSC
->SavedPositionIndex
< 0) {
527 Error (NULL
, 0, 0, "APP ERROR", "underflow of saved positions in section file");
531 DSC
->CurrentLine
= DSC
->SavedPosition
[DSC
->SavedPositionIndex
];
532 DSC
->SavedPositionIndex
--;
533 return STATUS_SUCCESS
;