strgather.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,364 行 · 第 1/5 页

C
2,364
字号
  }

  //
  // Make sure we didn't exceed our maximum nesting depth
  //
  if (NestDepth > MAX_NEST_DEPTH) {
    Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);
    Status = STATUS_ERROR;
    goto Finish;
  }
  //
  // Try to open the file locally, and if that fails try along our include paths.
  //
  strcpy (FoundFileName, SourceFile->FileName);
  if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) {
    //
    // Try to find it among the paths if it has a parent (that is, it is included
    // by someone else).
    //
    if (ParentSourceFile == NULL) {
      Error (NULL, 0, 0, SourceFile->FileName, "file not found");
      return STATUS_ERROR;
    }

    SourceFile->Fptr = FindFile (SourceFile->FileName, FoundFileName, sizeof (FoundFileName));
    if (SourceFile->Fptr == NULL) {
      Error (ParentSourceFile->FileName, ParentSourceFile->LineNum, 0, SourceFile->FileName, "include file not found");
      return STATUS_ERROR;
    }
  }
  //
  // Process the file found
  //
  AddDependency (FoundFileName);
  ProcessFile (SourceFile);
Finish:
  //
  // Close open files and return status
  //
  if (SourceFile->Fptr != NULL) {
    fclose (SourceFile->Fptr);
  }

  return Status;
}

static
STATUS
ProcessFile (
  SOURCE_FILE *SourceFile
  )
{
  //
  // Get the file size, and then read the entire thing into memory.
  // Allocate space for a terminator character.
  //
  fseek (SourceFile->Fptr, 0, SEEK_END);
  SourceFile->FileSize = ftell (SourceFile->Fptr);
  fseek (SourceFile->Fptr, 0, SEEK_SET);
  SourceFile->FileBuffer = (WCHAR *) malloc (SourceFile->FileSize + sizeof (WCHAR));
  if (SourceFile->FileBuffer == NULL) {
    Error (NULL, 0, 0, "memory allocation failure", NULL);
    return STATUS_ERROR;
  }

  fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
  SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (WCHAR))] = UNICODE_NULL;
  //
  // Pre-process the file to replace comments with spaces
  //
  PreprocessFile (SourceFile);
  //
  // Parse the file
  //
  ParseFile (SourceFile);
  free (SourceFile->FileBuffer);
  return STATUS_SUCCESS;
}

static
STATUS
ParseFile (
  SOURCE_FILE *SourceFile
  )
{
  BOOLEAN InComment;
  UINT32  Len;

  //
  // First character of a unicode file is special. Make sure
  //
  if (SourceFile->FileBufferPtr[0] != UNICODE_FILE_START) {
    Error (SourceFile->FileName, 1, 0, SourceFile->FileName, "file does not appear to be a unicode file");
    return STATUS_ERROR;
  }

  SourceFile->FileBufferPtr++;
  InComment = FALSE;
  //
  // Print the first line if in verbose mode
  //
  if (mGlobals.Verbose) {
    printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);
  }
  //
  // Since the syntax is relatively straightforward, just switch on the next char
  //
  while (!EndOfFile (SourceFile)) {
    //
    // Check for whitespace
    //
    if (SourceFile->FileBufferPtr[0] == UNICODE_SPACE) {
      SourceFile->FileBufferPtr++;
    } else if (SourceFile->FileBufferPtr[0] == UNICODE_TAB) {
      SourceFile->FileBufferPtr++;
    } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {
      SourceFile->FileBufferPtr++;
    } else if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {
      SourceFile->FileBufferPtr++;
      SourceFile->LineNum++;
      if (mGlobals.Verbose) {
        printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);
      }

      InComment = FALSE;
    } else if (SourceFile->FileBufferPtr[0] == 0) {
      SourceFile->FileBufferPtr++;
    } else if (InComment) {
      SourceFile->FileBufferPtr++;
    } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) {
      SourceFile->FileBufferPtr += 2;
      InComment = TRUE;
    } else if (SourceFile->SkipToHash && (SourceFile->FileBufferPtr[0] != SourceFile->ControlCharacter)) {
      SourceFile->FileBufferPtr++;
    } else {
      SourceFile->SkipToHash = FALSE;
      if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
          ((Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"include")) > 0)
          ) {
        SourceFile->FileBufferPtr += Len + 1;
        ProcessTokenInclude (SourceFile);
      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"scope")) > 0
              ) {
        SourceFile->FileBufferPtr += Len + 1;
        ProcessTokenScope (SourceFile);
      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"language")) > 0
              ) {
        SourceFile->FileBufferPtr += Len + 1;
        ProcessTokenLanguage (SourceFile);
      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"langdef")) > 0
              ) {
        SourceFile->FileBufferPtr += Len + 1;
        ProcessTokenLangDef (SourceFile);
      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"string")) > 0
              ) {
        SourceFile->FileBufferPtr += Len + 1;
        ProcessTokenString (SourceFile);
      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
               (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"EFI_BREAKPOINT()")) > 0
              ) {
        SourceFile->FileBufferPtr += Len;
        EFI_BREAKPOINT ();
      } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) &&
               (SourceFile->FileBufferPtr[1] == UNICODE_EQUAL_SIGN)
              ) {
        SourceFile->ControlCharacter = SourceFile->FileBufferPtr[2];
        SourceFile->FileBufferPtr += 3;
      } else {
        Error (SourceFile->FileName, SourceFile->LineNum, 0, "unrecognized token", "%S", SourceFile->FileBufferPtr);
        //
        // Treat rest of line as a comment.
        //
        InComment = TRUE;
      }
    }
  }

  return STATUS_SUCCESS;
}

static
void
PreprocessFile (
  SOURCE_FILE *SourceFile
  )
/*++

Routine Description:
  Preprocess a file to replace all carriage returns with NULLs so
  we can print lines from the file to the screen.
  
Arguments:
  SourceFile - structure that we use to keep track of an input file.

Returns:
  Nothing.
  
--*/
{
  BOOLEAN InComment;

  RewindFile (SourceFile);
  InComment = FALSE;
  while (!EndOfFile (SourceFile)) {
    //
    // If a line-feed, then no longer in a comment
    //
    if (SourceFile->FileBufferPtr[0] == UNICODE_LF) {
      SourceFile->FileBufferPtr++;
      SourceFile->LineNum++;
      InComment = 0;
    } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {
      //
      // Replace all carriage returns with a NULL so we can print stuff
      //
      SourceFile->FileBufferPtr[0] = 0;
      SourceFile->FileBufferPtr++;
    } else if (InComment) {
      SourceFile->FileBufferPtr[0] = UNICODE_SPACE;
      SourceFile->FileBufferPtr++;
    } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) {
      SourceFile->FileBufferPtr += 2;
      InComment = TRUE;
    } else {
      SourceFile->FileBufferPtr++;
    }
  }
  //
  // Could check for end-of-file and still in a comment, but
  // should not be necessary. So just restore the file pointers.
  //
  RewindFile (SourceFile);
}

static
WCHAR *
GetPrintableLanguageName (
  IN SOURCE_FILE  *SourceFile
  )
{
  WCHAR   *String;
  WCHAR   *Start;
  WCHAR   *Ptr;
  UINT32  Len;

  SkipWhiteSpace (SourceFile);
  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
    Error (
      SourceFile->FileName,
      SourceFile->LineNum,
      0,
      "expected quoted printable language name",
      "%S",
      SourceFile->FileBufferPtr
      );
    SourceFile->SkipToHash = TRUE;
    return NULL;
  }

  Len = 0;
  SourceFile->FileBufferPtr++;
  Start = Ptr = SourceFile->FileBufferPtr;
  while (!EndOfFile (SourceFile)) {
    if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {
      Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
      break;
    } else if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {
      break;
    }

    SourceFile->FileBufferPtr++;
    Len++;
  }

  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
    Warning (
      SourceFile->FileName,
      SourceFile->LineNum,
      0,
      "missing closing quote on printable language name string",
      "%S",
      Start
      );
  } else {
    SourceFile->FileBufferPtr++;
  }
  //
  // Now allocate memory for the string and save it off
  //
  String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR));
  if (String == NULL) {
    Error (NULL, 0, 0, "memory allocation failed", NULL);
    return NULL;
  }
  //
  // Copy the string from the file buffer to the local copy.
  // We do no reformatting of it whatsoever at this point.
  //
  Ptr = String;
  while (Len > 0) {
    *Ptr = *Start;
    Start++;
    Ptr++;
    Len--;
  }

  *Ptr = 0;
  //
  // Now format the string to convert \wide and \narrow controls
  //
  StringDBFormatString (String);
  return String;
}

static
WCHAR *
GetQuotedString (
  SOURCE_FILE *SourceFile,
  BOOLEAN     Optional
  )
{
  WCHAR   *String;
  WCHAR   *Start;
  WCHAR   *Ptr;
  UINT32  Len;
  BOOLEAN PreviousBackslash;

  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
    if (!Optional) {
      Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);
    }

    return NULL;
  }

  Len = 0;
  SourceFile->FileBufferPtr++;
  Start             = Ptr = SourceFile->FileBufferPtr;
  PreviousBackslash = FALSE;
  while (!EndOfFile (SourceFile)) {
    if ((SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) && (!PreviousBackslash)) {
      break;
    } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) {
      Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
      PreviousBackslash = FALSE;
    } else if (SourceFile->FileBufferPtr[0] == UNICODE_BACKSLASH) {
      PreviousBackslash = TRUE;
    } else {
      PreviousBackslash = FALSE;
    }

    SourceFile->FileBufferPtr++;
    Len++;
  }

  if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) {
    Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);
  } else {
    SourceFile->FileBufferPtr++;
  }
  //
  // Now allocate memory for the string and save it off
  //
  String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR));
  if (String == NULL) {
    Error (NULL, 0, 0, "memory allocation failed", NULL);
    return NULL;
  }
  //
  // Copy the string from the file buffer to the local copy.
  // We do no reformatting of it whatsoever at this point.
  //
  Ptr = String;
  while (Len > 0) {
    *Ptr = *Start;
    Start++;
    Ptr++;
    Len--;
  }

  *Ptr = 0;
  return String;
}
//
// Parse:
//    #string STR_ID_NAME
//
// All we can do is call the string database to add the string identifier. Unfortunately
// he'll have to keep track of the last identifier we added.
//
static
void
ProcessTokenString (
  SOURCE_FILE *SourceFile
  )
{
  WCHAR   StringIdentifier[MAX_STRING_IDENTIFIER_NAME];
  UINT16  StringId;
  //
  // Extract the string identifier name and add it to the database.
  //
  if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) {
    StringId = STRING_ID_INVALID;
    StringDBAddStringIdentifier (StringIdentifier, &StringId, 0);
  } else {
    //
    // Error recovery -- skip to the next #
    //
    SourceFile->SkipToHash = TRUE;
  }
}

static
BOOLEAN
EndOfFile (
  SOURCE_FILE *SourceFile
  )
{
  //
  // The file buffer pointer will typically get updated before the End-of-file flag in the
  // source file structure, so check it first.
  //
  if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (WCHAR)) {
    SourceFile->EndOfFile = TRUE;
    return TRUE;
  }

  if (SourceFile->EndOfFile) {
    return TRUE;
  }

  return FALSE;
}

static
UINT32
GetStringIdentifierName (
  IN SOURCE_FILE  *SourceFile,
  IN OUT WCHAR    *StringIdentifierName,
  IN UINT32       StringIdentifierNameLen
  )
{
  UINT32  Len;
  WCHAR   *From;
  WCHAR   *Start;

  //
  // Skip whitespace
  //
  SkipWhiteSpace (SourceFile);
  if (SourceFile->EndOfFile) {
    Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-file encountered", "expected string identifier");
    return 0;
  }
  //
  // Verify first character of name is [A-Za-z]
  //
  Len = 0;
  StringIdentifierNameLen /= 2;
  From  = SourceFile->FileBufferPtr;
  Start = SourceFile->FileBufferPtr;
  if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) ||
      ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z))
      ) {
    //
    // Do nothing
    //
  } else {
    Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid character in string identifier name", "%S", Start);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?