// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace UnrealBuildTool { /// /// Parses include directives from cpp source files, to make dedicated PCHs /// static class CppIncludeParser { /// /// Copies include directives from one file to another, until an unsafe directive (or non-#include line) is found. /// /// Stream to read from /// Stream to write directives to public static void CopyIncludeDirectives(StreamReader Reader, StringWriter Writer) { StringBuilder Token = new StringBuilder(); while(TryReadToken(Reader, Token)) { if(Token.Length > 1 || Token[0] != '\n') { if(Token.Length != 1 || Token[0] != '#') { break; } if(!TryReadToken(Reader, Token)) { break; } string Directive = Token.ToString(); if(Directive == "pragma") { if(!TryReadToken(Reader, Token) || Token.ToString() != "once") { break; } if(!TryReadToken(Reader, Token) || Token.ToString() != "\n") { break; } } else if(Directive == "include") { if(!TryReadToken(Reader, Token) || Token[0] != '\"') { break; } string IncludeFile = Token.ToString(); if(!IncludeFile.EndsWith(".h\"") && !IncludeFile.EndsWith(".h>")) { break; } if(IncludeFile.Equals("\"RequiredProgramMainCPPInclude.h\"", StringComparison.OrdinalIgnoreCase)) { break; } if(!TryReadToken(Reader, Token) || Token.ToString() != "\n") { break; } Writer.WriteLine("#include {0}", IncludeFile); } else { break; } } } } /// /// Reads an individual token from the input stream /// /// Stream to read from /// Buffer to store token read from the stream /// True if a token was read, false otherwise static bool TryReadToken(StreamReader Reader, StringBuilder Token) { Token.Clear(); int NextChar; for(;;) { NextChar = Reader.Read(); if(NextChar == -1) { return false; } if(NextChar != ' ' && NextChar != '\t' && NextChar != '\r') { if(NextChar != '/') { break; } else if(Reader.Peek() == '/') { Reader.Read(); for(;;) { NextChar = Reader.Read(); if(NextChar == -1) { return false; } if(NextChar == '\n') { break; } } } else if(Reader.Peek() == '*') { Reader.Read(); for(;;) { NextChar = Reader.Read(); if(NextChar == -1) { return false; } if(NextChar == '*' && Reader.Peek() == '/') { break; } } Reader.Read(); } else { break; } } } Token.Append((char)NextChar); if(Char.IsLetterOrDigit((char)NextChar)) { for(;;) { NextChar = Reader.Read(); if(NextChar == -1 || !Char.IsLetterOrDigit((char)NextChar)) { break; } Token.Append((char)NextChar); } } else if(NextChar == '\"' || NextChar == '<') { for(;;) { NextChar = Reader.Read(); if(NextChar == -1) { break; } Token.Append((char)NextChar); if(NextChar == '\"' || NextChar == '>') { break; } } } return true; } } }