📄 vfrcompile.g
字号:
//
// -od OutputDirectory to define a common directory for output files
//
} else if (_stricmp (Argv[0], "-od") == 0) {
if ((Argc < 2) || (Argv[1][0] == '-')) {
Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output directory name");
return STATUS_ERROR;
}
Argc--;
Argv++;
strcpy (gOptions.OutputDirectory, Argv[0]);
} else if (_stricmp (Argv[0], "-ibin") == 0) {
gOptions.CreateIfrBinFile = 1;
} else if (_stricmp (Argv[0], "-nostrings") == 0) {
// deprecated option
//
// -ppflag C-preprocessor-flag option for passing options to the C preprocessor.
// Turn them all into a single string.
//
} else if (_stricmp (Argv[0], "-ppflag") == 0) {
if (Argc < 2) {
Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument");
return STATUS_ERROR;
}
Argc--;
Argv++;
Len = strlen (Argv[0]) + 2;
if (gOptions.CPreprocessorOptions != NULL) {
Len += strlen (gOptions.CPreprocessorOptions);
}
CPreprocessorOptions = (INT8 *)malloc (Len);
if (CPreprocessorOptions == NULL) {
Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure");
return STATUS_ERROR;
}
CPreprocessorOptions[0] = 0;
if (gOptions.CPreprocessorOptions != NULL) {
strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions);
free (gOptions.CPreprocessorOptions);
}
strcat (CPreprocessorOptions, " ");
strcat (CPreprocessorOptions, Argv[0]);
gOptions.CPreprocessorOptions = CPreprocessorOptions;
} else {
Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option");
return STATUS_ERROR;
}
Argc--;
Argv++;
}
//
// Must specify at least the vfr file name
//
if (Argc > 1) {
Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name");
return STATUS_ERROR;
} else if (Argc < 1) {
Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name");
return STATUS_ERROR;
}
strcpy (gOptions.VfrFileName, Argv[0]);
//
// We run the preprocessor on the VFR file to manage #include statements.
// Unfortunately the preprocessor does not allow you to specify the
// output name or path of the resultant .i file, so we have to do
// some work. Here we'll extract the basename of the VFR file, then
// append .i on the end.
//
strcpy (CopyStr, gOptions.VfrFileName);
Cptr = CopyStr + strlen (CopyStr) - 1;
for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':'); Cptr--);
if (Cptr == CopyStr) {
strcpy (gOptions.PreprocessorOutputFileName, Cptr);
strcpy (gOptions.VfrBaseFileName, Cptr);
} else {
strcpy (gOptions.PreprocessorOutputFileName, Cptr+1);
strcpy (gOptions.VfrBaseFileName, Cptr+1);
}
for (Cptr = gOptions.PreprocessorOutputFileName; *Cptr && (*Cptr != '.'); Cptr++);
strcpy (Cptr, ".i");
//
// Terminate the vfr file basename at the extension
//
for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) {
}
*Cptr = 0;
//
// If they defined an output directory, prepend all output files
// with the working directory. Output files of interest:
// VfrListFileName -- list file
// IfrOutputFileName -- IFR bytes
// StringOutputFileName -- string bytes
// StringListFileName -- not used
// StringDefineFileName -- #defines of string identifiers
//
// We have two cases:
// 1. Output directory (-od) not specified, in which case output files
// go to the current working directory.
// 2. Output directory specified, in which case the output files
// go directly to the specified directory.
//
if (gOptions.OutputDirectory[0] == 0) {
CopyStr[0] = 0;
_getcwd (CopyStr, sizeof (CopyStr));
strcpy (gOptions.OutputDirectory, CopyStr);
}
//
// Make sure output directory has a trailing backslash
//
if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\') {
strcat (gOptions.OutputDirectory, "\\");
}
//
// Create the base output file name as: path\base, copy it to all the output
// filenames, and then add the appropriate extension to each.
//
strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory);
strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName);
strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName);
strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION);
strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION);
//
// We set a default list file name, so if they do not
// want a list file, null out the name now.
//
if (gOptions.CreateListFile == 0) {
gOptions.VfrListFileName[0] = 0;
}
return STATUS_SUCCESS;
}
static
VOID
Usage ()
/*++
Routine Description:
Print utility usage instructions
Arguments:
None
Returns:
None
--*/
{
int Index;
const char *Help[] = {
" ",
"VfrCompile version " VFR_COMPILER_VERSION,
" ",
" Usage: VfrCompile {options} [VfrFile]",
" ",
" where options include:",
" -? or -h prints this help",
" -l create an output IFR listing file",
" -i IncPath add IncPath to the search path for VFR included files",
" -od OutputDir deposit all output files to directory OutputDir (default=cwd)",
" -ibin create an IFR HII pack file",
" where parameters include:",
" VfrFile name of the input VFR script file",
" ",
NULL
};
for (Index = 0; Help[Index] != NULL; Index++) {
fprintf (stdout, "%s\n", Help[Index]);
}
}
>>
#lexaction
<<
#include "EfiVfr.h"
PARSER_LINE_DEFINITION *gLineDefinition = NULL;
PARSER_LINE_DEFINITION *gLastLineDefinition = NULL;
VOID
AddFileLine (
char *TokenString,
UINT32 TokenLine
)
/*++
Routine Description:
During the lexer phase, if we encounter a #line statement output by
the preprocessor, this function gets called. We'll save off the info
for error reporting purposes. The preprocessor line information has the
form:
#line 3 "FileName.c"
Arguments:
TokenString - the parsed string as shown above
TokenLine - the line number in the preprocessed output file
Returns:
NA
--*/
{
PARSER_LINE_DEFINITION *LineDef;
INT8 *Cptr;
//
// Allocate a structure in which we can keep track of this line information.
//
LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION));
memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION));
LineDef->TokenLineNum = TokenLine;
LineDef->HashLineNum = atoi (TokenString + 6);
//
// Find the quotes in the filename, then allocate space in the line
// def structure for a copy of the filename. Finally, copy it without
// quotes to the line def.
//
for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++);
if (*Cptr == '"') {
LineDef->FileName = (INT8 *)malloc (strlen (Cptr));
Cptr++;
strcpy (LineDef->FileName, Cptr);
for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++);
*Cptr = 0;
//
// Now add this new one to the list
//
if (gLineDefinition == NULL) {
gLineDefinition = LineDef;
} else {
gLastLineDefinition->Next = LineDef;
}
gLastLineDefinition = LineDef;
} else {
Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString);
free (LineDef);
return;
}
}
char *
ConvertLineNumber (
UINT32 *LineNum
)
/*++
Routine Description:
Given the line number in the preprocessor-output file, use the line number
information we've saved to determine the source file name and line number
where the code originally came from. This is required for error reporting.
Arguments:
LineNum - the line number in the preprocessor-output file.
Returns:
Returns a pointer to the source file name. Also returns the line number
in the provided LineNum argument
--*/
{
PARSER_LINE_DEFINITION *LineDef;
//
// Step through our linked list of #line information we saved off.
// For each one, look at its line number, and the line number of the
// next record, and see if the passed-in line number is in the range.
// If it is, then convert the line number to the appropriate line number
// of the original source file.
//
for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) {
//
// The given LineNum is the line number from the .i file.
// Find a line definition whose range includes this line number,
// convert the line number, and return the filename.
//
if (LineDef->TokenLineNum <= *LineNum) {
if (LineDef->Next != NULL) {
if (LineDef->Next->TokenLineNum > *LineNum) {
*LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
return LineDef->FileName;
}
} else {
//
// Last one in the list of line definitions, so has to be right
//
*LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum;
return LineDef->FileName;
}
}
}
return NULL;
}
>>
//
// Define a lexical class for parsing quoted strings. Basically
// starts with a double quote, and ends with a double quote that
// is not preceeded with a backslash.
//
#lexclass QUOTED_STRING
#token TheString "~[\"]*\"" << mode (START); >>
//
// Define a lexical class for parsing "#pragma pack" statements.
// We do this just for convenience (since we skip them here) so
// that users can include some minimal .h files.
//
#lexclass PRAGMA_PACK
#token "pack" << skip (); >>
#token "[\ \t]" << skip (); >>
#token "\(" << skip (); >>
#token "[0-9]*" << skip (); >>
#token "\)" << skip (); mode (START); >>
//
// Define a lexclass for skipping over C++ style comments
//
#lexclass CPP_COMMENT
#token "~[\n]*" << skip (); >>
#token "\n" << skip (); mode (START); newline (); >>
//
// Standard lexclass is START
//
#lexclass START
//
// Find start of C++ style comments
//
#token "//" << skip (); mode (CPP_COMMENT); >>
//
// Skip whitespace
//
#token "[\ \t]" << skip (); >>
//
// Skip over newlines, but count them
//
#token "\n" << skip (); newline (); >>
//
// Skip pragma pack statements
//
#token "\#pragma" << skip (); mode(PRAGMA_PACK); >>
//
// Skip over 'extern' in any included .H file
//
#token "extern" << skip (); >>
//
// Tokens for the different keywords. Syntax is:
// TokenName("ErrorMessageText") "TokenString"
// where:
// TokenName is the token name (must be capitalized) that is used in the rules
// ErrorMessageText is the string the compiler emits when it detects a syntax error
// TokenString is the actual matching string used in the user script
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -