mirror of https://github.com/mono/CppSharp.git
27 changed files with 8 additions and 4386 deletions
@ -1,48 +0,0 @@
@@ -1,48 +0,0 @@
|
||||
//===----- CXXABI.h - Interface to C++ ABIs ---------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This provides an abstract class for C++ AST support. Concrete
|
||||
// subclasses of this implement AST support for specific C++ ABIs.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_CXXABI_H |
||||
#define LLVM_CLANG_AST_CXXABI_H |
||||
|
||||
#include "clang/AST/Type.h" |
||||
|
||||
namespace clang { |
||||
|
||||
class ASTContext; |
||||
class MemberPointerType; |
||||
|
||||
/// Implements C++ ABI-specific semantic analysis functions.
|
||||
class CXXABI { |
||||
public: |
||||
virtual ~CXXABI(); |
||||
|
||||
/// Returns the size of a member pointer in multiples of the target
|
||||
/// pointer size.
|
||||
virtual unsigned getMemberPointerSize(const MemberPointerType *MPT) const = 0; |
||||
|
||||
/// Returns the default calling convention for C++ methods.
|
||||
virtual CallingConv getDefaultMethodCallConv() const = 0; |
||||
|
||||
// Returns whether the given class is nearly empty, with just virtual pointers
|
||||
// and no data except possibly virtual bases.
|
||||
virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0; |
||||
}; |
||||
|
||||
/// Creates an instance of a C++ ABI class.
|
||||
CXXABI *CreateARMCXXABI(ASTContext &Ctx); |
||||
CXXABI *CreateItaniumCXXABI(ASTContext &Ctx); |
||||
CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx); |
||||
} |
||||
|
||||
#endif |
@ -1,268 +0,0 @@
@@ -1,268 +0,0 @@
|
||||
/************************************************************************
|
||||
* |
||||
* CppSharp |
||||
* Licensed under the simplified BSD license. All rights reserved. |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#include "Parser.h" |
||||
#include "Interop.h" |
||||
|
||||
#include <clang/AST/ASTContext.h> |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
static CppSharp::AST::RawCommentKind |
||||
ConvertCommentKind(clang::RawComment::CommentKind Kind) |
||||
{ |
||||
using clang::RawComment; |
||||
using namespace CppSharp::AST; |
||||
|
||||
switch(Kind) |
||||
{ |
||||
case RawComment::RCK_Invalid: return RawCommentKind::Invalid; |
||||
case RawComment::RCK_OrdinaryBCPL: return RawCommentKind::OrdinaryBCPL; |
||||
case RawComment::RCK_OrdinaryC: return RawCommentKind::OrdinaryC; |
||||
case RawComment::RCK_BCPLSlash: return RawCommentKind::BCPLSlash; |
||||
case RawComment::RCK_BCPLExcl: return RawCommentKind::BCPLExcl; |
||||
case RawComment::RCK_JavaDoc: return RawCommentKind::JavaDoc; |
||||
case RawComment::RCK_Qt: return RawCommentKind::Qt; |
||||
case RawComment::RCK_Merged: return RawCommentKind::Merged; |
||||
} |
||||
|
||||
llvm_unreachable("Unknown comment kind"); |
||||
} |
||||
|
||||
CppSharp::AST::RawComment^ Parser::WalkRawComment(const clang::RawComment* RC) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
auto &SM = C->getSourceManager(); |
||||
auto Comment = gcnew CppSharp::AST::RawComment(); |
||||
Comment->Kind = ConvertCommentKind(RC->getKind()); |
||||
Comment->Text = marshalString<E_UTF8>(RC->getRawText(SM)); |
||||
Comment->BriefText = marshalString<E_UTF8>(RC->getBriefText(*AST)); |
||||
|
||||
return Comment; |
||||
} |
||||
|
||||
static CppSharp::AST::InlineCommandComment::RenderKind |
||||
ConvertRenderKind(clang::comments::InlineCommandComment::RenderKind Kind) |
||||
{ |
||||
using namespace clang::comments; |
||||
switch(Kind) |
||||
{ |
||||
case InlineCommandComment::RenderNormal: |
||||
return CppSharp::AST::InlineCommandComment::RenderKind::RenderNormal; |
||||
case InlineCommandComment::RenderBold: |
||||
return CppSharp::AST::InlineCommandComment::RenderKind::RenderBold; |
||||
case InlineCommandComment::RenderMonospaced: |
||||
return CppSharp::AST::InlineCommandComment::RenderKind::RenderMonospaced; |
||||
case InlineCommandComment::RenderEmphasized: |
||||
return CppSharp::AST::InlineCommandComment::RenderKind::RenderEmphasized; |
||||
} |
||||
llvm_unreachable("Unknown render kind"); |
||||
} |
||||
|
||||
static CppSharp::AST::ParamCommandComment::PassDirection |
||||
ConvertParamPassDirection(clang::comments::ParamCommandComment::PassDirection Dir) |
||||
{ |
||||
using namespace clang::comments; |
||||
switch(Dir) |
||||
{ |
||||
case ParamCommandComment::In: |
||||
return CppSharp::AST::ParamCommandComment::PassDirection::In; |
||||
case ParamCommandComment::Out: |
||||
return CppSharp::AST::ParamCommandComment::PassDirection::Out; |
||||
case ParamCommandComment::InOut: |
||||
return CppSharp::AST::ParamCommandComment::PassDirection::InOut; |
||||
} |
||||
llvm_unreachable("Unknown parameter pass direction"); |
||||
} |
||||
|
||||
static void HandleBlockCommand(const clang::comments::BlockCommandComment *CK, |
||||
CppSharp::AST::BlockCommandComment^ BC) |
||||
{ |
||||
using namespace clix; |
||||
|
||||
BC->CommandId = CK->getCommandID(); |
||||
for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I) |
||||
{ |
||||
auto Arg = CppSharp::AST::BlockCommandComment::Argument(); |
||||
Arg.Text = marshalString<E_UTF8>(CK->getArgText(I)); |
||||
BC->Arguments->Add(Arg); |
||||
} |
||||
} |
||||
|
||||
static CppSharp::AST::Comment^ ConvertCommentBlock(clang::comments::Comment* C) |
||||
{ |
||||
using namespace clang; |
||||
using clang::comments::Comment; |
||||
|
||||
using namespace clix; |
||||
using namespace CppSharp::AST; |
||||
|
||||
// This needs to have an underscore else we get an ICE under VS2012.
|
||||
CppSharp::AST::Comment^ _Comment; |
||||
|
||||
switch(C->getCommentKind()) |
||||
{ |
||||
case Comment::BlockCommandCommentKind: |
||||
{ |
||||
auto CK = cast<const clang::comments::BlockCommandComment>(C); |
||||
auto BC = gcnew BlockCommandComment(); |
||||
_Comment = BC; |
||||
HandleBlockCommand(CK, BC); |
||||
break; |
||||
} |
||||
case Comment::ParamCommandCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::ParamCommandComment>(C); |
||||
auto PC = gcnew ParamCommandComment(); |
||||
_Comment = PC; |
||||
HandleBlockCommand(CK, PC); |
||||
PC->Direction = ConvertParamPassDirection(CK->getDirection()); |
||||
if (CK->isParamIndexValid() && !CK->isVarArgParam()) |
||||
PC->ParamIndex = CK->getParamIndex(); |
||||
break; |
||||
} |
||||
case Comment::TParamCommandCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::TParamCommandComment>(C); |
||||
_Comment = gcnew TParamCommandComment(); |
||||
auto TC = gcnew TParamCommandComment(); |
||||
_Comment = TC; |
||||
HandleBlockCommand(CK, TC); |
||||
if (CK->isPositionValid()) |
||||
for (unsigned I = 0, E = CK->getDepth(); I != E; ++I) |
||||
TC->Position->Add(CK->getIndex(I)); |
||||
break; |
||||
} |
||||
case Comment::VerbatimBlockCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::VerbatimBlockComment>(C); |
||||
auto VB = gcnew VerbatimBlockComment(); |
||||
_Comment = VB; |
||||
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I) |
||||
{ |
||||
auto Line = ConvertCommentBlock(*I); |
||||
VB->Lines->Add(dynamic_cast<VerbatimBlockLineComment^>(Line)); |
||||
} |
||||
break; |
||||
} |
||||
case Comment::VerbatimLineCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::VerbatimLineComment>(C); |
||||
auto VL = gcnew VerbatimLineComment(); |
||||
_Comment = VL; |
||||
VL->Text = marshalString<E_UTF8>(CK->getText()); |
||||
break; |
||||
} |
||||
case Comment::ParagraphCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::ParagraphComment>(C); |
||||
auto PC = gcnew ParagraphComment(); |
||||
_Comment = PC; |
||||
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I) |
||||
{ |
||||
auto Content = ConvertCommentBlock(*I); |
||||
PC->Content->Add(dynamic_cast<InlineContentComment^>(Content)); |
||||
} |
||||
PC->IsWhitespace = CK->isWhitespace(); |
||||
break; |
||||
} |
||||
case Comment::FullCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::FullComment>(C); |
||||
auto FC = gcnew FullComment(); |
||||
_Comment = FC; |
||||
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I) |
||||
{ |
||||
auto Content = ConvertCommentBlock(*I); |
||||
FC->Blocks->Add(dynamic_cast<BlockContentComment^>(Content)); |
||||
} |
||||
break; |
||||
} |
||||
case Comment::HTMLStartTagCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::HTMLStartTagComment>(C); |
||||
auto TC = gcnew HTMLStartTagComment(); |
||||
_Comment = TC; |
||||
TC->TagName = marshalString<E_UTF8>(CK->getTagName()); |
||||
for (unsigned I = 0, E = CK->getNumAttrs(); I != E; ++I) |
||||
{ |
||||
auto A = CK->getAttr(I); |
||||
auto Attr = CppSharp::AST::HTMLStartTagComment::Attribute(); |
||||
Attr.Name = marshalString<E_UTF8>(A.Name); |
||||
Attr.Value = marshalString<E_UTF8>(A.Value); |
||||
TC->Attributes->Add(Attr); |
||||
} |
||||
break; |
||||
} |
||||
case Comment::HTMLEndTagCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::HTMLEndTagComment>(C); |
||||
auto TC = gcnew HTMLEndTagComment(); |
||||
_Comment = TC; |
||||
TC->TagName = marshalString<E_UTF8>(CK->getTagName()); |
||||
break; |
||||
} |
||||
case Comment::TextCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::TextComment>(C); |
||||
auto TC = gcnew TextComment(); |
||||
_Comment = TC; |
||||
TC->Text = marshalString<E_UTF8>(CK->getText()); |
||||
break; |
||||
} |
||||
case Comment::InlineCommandCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::InlineCommandComment>(C); |
||||
auto IC = gcnew InlineCommandComment(); |
||||
_Comment = IC; |
||||
IC->Kind = ConvertRenderKind(CK->getRenderKind()); |
||||
for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I) |
||||
{ |
||||
auto Arg = CppSharp::AST::InlineCommandComment::Argument(); |
||||
Arg.Text = marshalString<E_UTF8>(CK->getArgText(I)); |
||||
IC->Arguments->Add(Arg); |
||||
} |
||||
break; |
||||
} |
||||
case Comment::VerbatimBlockLineCommentKind: |
||||
{ |
||||
auto CK = cast<clang::comments::VerbatimBlockLineComment>(C); |
||||
auto VL = gcnew VerbatimBlockLineComment(); |
||||
_Comment = VL; |
||||
VL->Text = marshalString<E_UTF8>(CK->getText()); |
||||
break; |
||||
} |
||||
case Comment::NoCommentKind: return nullptr; |
||||
default: |
||||
llvm_unreachable("Unknown comment kind"); |
||||
} |
||||
|
||||
assert(_Comment && "Invalid comment instance"); |
||||
return _Comment; |
||||
} |
||||
|
||||
void Parser::HandleComments(clang::Decl* D, CppSharp::AST::Declaration^ Decl) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clang::comments; |
||||
using namespace clix; |
||||
|
||||
const RawComment* RC = 0; |
||||
if (!(RC = AST->getRawCommentForAnyRedecl(D))) |
||||
return; |
||||
|
||||
auto RawComment = WalkRawComment(RC); |
||||
Decl->Comment = RawComment; |
||||
|
||||
if (FullComment* FC = RC->parse(*AST, &C->getPreprocessor(), D)) |
||||
{ |
||||
auto CB = safe_cast<CppSharp::AST::FullComment^>(ConvertCommentBlock(FC)); |
||||
RawComment->FullComment = CB; |
||||
} |
||||
} |
@ -1,203 +0,0 @@
@@ -1,203 +0,0 @@
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
// clix.hpp (from http://blog.nuclex-games.com/mono-dotnet/cxx-cli-string-marshaling)
|
||||
//
|
||||
// Marshals strings between .NET and C++ using C++/CLI (Visual C++ 2005 and later only).
|
||||
// Faster and cleaner than the System::Interop method because it uses garbage collected memory.
|
||||
// Use at your own leisure. No warranties whatsoever provided.
|
||||
//
|
||||
// Original code by Markus Ewald
|
||||
// Updated version including several improvements suggested by Neil Hunt
|
||||
//
|
||||
// Licensed under the IBM CPL (free of charge, closed source commercial use is okay)
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
#pragma once |
||||
|
||||
#include <string> |
||||
#include <vcclr.h> |
||||
|
||||
// CLI extensions namespace
|
||||
namespace clix { |
||||
|
||||
/// <summary>Encoding types for strings</summary>
|
||||
enum Encoding { |
||||
|
||||
/// <summary>ANSI encoding</summary>
|
||||
/// <remarks>
|
||||
/// This is the default encoding you've most likely been using all around in C++. ANSI
|
||||
/// means 8 Bit encoding with character codes depending on the system's selected code page.
|
||||
/// <remarks>
|
||||
E_ANSI, |
||||
|
||||
/// <summary>UTF-8 encoding</summary>
|
||||
/// <remarks>
|
||||
/// This is the encoding commonly used for multilingual C++ strings. All ASCII characters
|
||||
/// (0-127) will be represented as single bytes. Be aware that UTF-8 uses more than one
|
||||
/// byte for extended characters, so std::string::length() might not reflect the actual
|
||||
/// length of the string in characters if it contains any non-ASCII characters.
|
||||
/// <remarks>
|
||||
E_UTF8, |
||||
|
||||
/// <summary>UTF-16 encoding</summary>
|
||||
/// <remarks>
|
||||
/// This is the suggested to be used for marshaling and the native encoding of .NET
|
||||
/// strings. It is similar to UTF-8 but uses a minimum of two bytes per character, making
|
||||
/// the number of bytes required for a given string better predictable. Be aware, however,
|
||||
/// that UTF-16 can still use more than two bytes for a character, so std::wstring::length()
|
||||
/// might not reflect the actual length of the string.
|
||||
/// </remarks>
|
||||
E_UTF16, E_UNICODE = E_UTF16 |
||||
|
||||
}; |
||||
|
||||
// Ignore this if you're just scanning the headers for informations!
|
||||
/* All this template stuff might seem like overkill, but it is well thought out and enables
|
||||
you to use a readable and convenient call while still keeping the highest possible code |
||||
efficiency due to compile-time evaluation of the required conversion path. |
||||
*/ |
||||
namespace detail { |
||||
|
||||
// Get C++ string type for specified encoding
|
||||
template<Encoding encoding> struct StringTypeSelector; |
||||
template<> struct StringTypeSelector<E_ANSI> { typedef std::string Type; }; |
||||
template<> struct StringTypeSelector<E_UTF8> { typedef std::string Type; }; |
||||
template<> struct StringTypeSelector<E_UTF16> { typedef std::wstring Type; }; |
||||
|
||||
// Compile-time selection depending on whether a string is managed
|
||||
template<typename StringType> struct IfManaged { |
||||
struct Select { |
||||
template<typename TrueType, typename FalseType> |
||||
struct Either { typedef FalseType Type; }; |
||||
}; |
||||
enum { Result = false }; |
||||
}; |
||||
template<> struct IfManaged<System::String ^> { |
||||
struct Select { |
||||
template<typename TrueType, typename FalseType> |
||||
struct Either { typedef TrueType Type; }; |
||||
}; |
||||
enum { Result = true }; |
||||
}; |
||||
|
||||
// Direction of the marshaling process
|
||||
enum MarshalingDirection { |
||||
CxxFromNet, |
||||
NetFromCxx |
||||
}; |
||||
|
||||
// The actual marshaling code
|
||||
template<MarshalingDirection direction> struct StringMarshaler; |
||||
|
||||
// Marshals to .NET from C++ strings
|
||||
template<> struct StringMarshaler<NetFromCxx> { |
||||
|
||||
template<Encoding encoding, typename SourceType> |
||||
static System::String ^marshal(const SourceType &string) { |
||||
// Constructs a std::[w]string in case someone gave us a char * to choke on
|
||||
return marshalCxxString<encoding, SourceType>(string); |
||||
} |
||||
|
||||
template<Encoding encoding, typename SourceType> |
||||
static System::String ^marshalCxxString( |
||||
const typename StringTypeSelector<encoding>::Type &cxxString |
||||
) { |
||||
typedef typename StringTypeSelector<encoding>::Type SourceStringType; |
||||
size_t byteCount = cxxString.length() * sizeof(SourceStringType::value_type); |
||||
|
||||
if(byteCount == 0) return System::String::Empty; |
||||
|
||||
// Copy the C++ string contents into a managed array of bytes
|
||||
array<unsigned char> ^bytes = gcnew array<unsigned char>(byteCount); |
||||
{ pin_ptr<unsigned char> pinnedBytes = &bytes[0]; |
||||
memcpy(pinnedBytes, cxxString.c_str(), byteCount); |
||||
} |
||||
|
||||
// Now let one of .NET's encoding classes do the rest
|
||||
return decode<encoding>(bytes); |
||||
} |
||||
|
||||
private: |
||||
// Converts a byte array based on the selected encoding
|
||||
template<Encoding encoding> static System::String ^decode(array<unsigned char> ^bytes); |
||||
template<> static System::String ^decode<E_ANSI>(array<unsigned char> ^bytes) { |
||||
return System::Text::Encoding::Default->GetString(bytes); |
||||
} |
||||
template<> static System::String ^decode<E_UTF8>(array<unsigned char> ^bytes) { |
||||
return System::Text::Encoding::UTF8->GetString(bytes); |
||||
} |
||||
template<> static System::String ^decode<E_UTF16>(array<unsigned char> ^bytes) { |
||||
return System::Text::Encoding::Unicode->GetString(bytes); |
||||
} |
||||
}; |
||||
|
||||
// Marshals to C++ strings from .NET
|
||||
template<> struct StringMarshaler<CxxFromNet> { |
||||
|
||||
template<Encoding encoding, typename SourceType> |
||||
static typename detail::StringTypeSelector<encoding>::Type marshal( |
||||
System::String ^string |
||||
) { |
||||
typedef typename StringTypeSelector<encoding>::Type StringType; |
||||
|
||||
// First, we use .NET's encoding classes to convert the string into a byte array
|
||||
array<unsigned char> ^bytes = encode<encoding>(string); |
||||
|
||||
if(bytes->Length == 0) return StringType(); |
||||
|
||||
// Then we construct our native string from that byte array
|
||||
pin_ptr<unsigned char> pinnedBytes(&bytes[0]); |
||||
return StringType( |
||||
reinterpret_cast<StringType::value_type *>(static_cast<unsigned char *>(pinnedBytes)), |
||||
bytes->Length / sizeof(StringType::value_type) |
||||
); |
||||
} |
||||
|
||||
template<> static std::wstring marshal<E_UTF16, System::String ^>( |
||||
System::String ^string |
||||
) { |
||||
// We can directly accesss the characters in the managed string
|
||||
pin_ptr<const wchar_t> pinnedChars(::PtrToStringChars(string)); |
||||
return std::wstring(pinnedChars, string->Length); |
||||
} |
||||
|
||||
private: |
||||
// Converts a string based on the selected encoding
|
||||
template<Encoding encoding> static array<unsigned char> ^encode(System::String ^string); |
||||
template<> static array<unsigned char> ^encode<E_ANSI>(System::String ^string) { |
||||
return System::Text::Encoding::Default->GetBytes(string); |
||||
} |
||||
template<> static array<unsigned char> ^encode<E_UTF8>(System::String ^string) { |
||||
return System::Text::Encoding::UTF8->GetBytes(string); |
||||
} |
||||
template<> static array<unsigned char> ^encode<E_UTF16>(System::String ^string) { |
||||
return System::Text::Encoding::Unicode->GetBytes(string); |
||||
} |
||||
|
||||
}; |
||||
|
||||
} // namespace detail
|
||||
|
||||
// ----------------------------------------------------------------------------------------- //
|
||||
// clix::marshalString()
|
||||
// ----------------------------------------------------------------------------------------- //
|
||||
/// <summary>Marshals strings between .NET managed and C++ native</summary>
|
||||
/// <remarks>
|
||||
/// This all-in-one function marshals native C++ strings to .NET strings and vice versa.
|
||||
/// You have to specify an encoding to use for the conversion, which always applies to the
|
||||
/// native C++ string as .NET always uses UTF-16 for its own strings.
|
||||
/// </remarks>
|
||||
/// <param name="string">String to be marshalled to the other side</param>
|
||||
/// <returns>The marshaled representation of the string</returns>
|
||||
template<Encoding encoding, typename SourceType> |
||||
typename detail::IfManaged<SourceType>::Select::Either< |
||||
typename detail::StringTypeSelector<encoding>::Type, |
||||
System::String ^ |
||||
>::Type marshalString(SourceType string) { |
||||
|
||||
// Pass on the call to our nifty template routines
|
||||
return detail::StringMarshaler< |
||||
detail::IfManaged<SourceType>::Result ? detail::CxxFromNet : detail::NetFromCxx |
||||
>::marshal<encoding, SourceType>(string); |
||||
|
||||
} |
||||
|
||||
} // namespace clix
|
@ -1,46 +0,0 @@
@@ -1,46 +0,0 @@
|
||||
/************************************************************************
|
||||
* |
||||
* CppSharp |
||||
* Licensed under the simplified BSD license. All rights reserved. |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#include "Parser.h" |
||||
#include "Interop.h" |
||||
|
||||
namespace CppSharp { namespace Parser { |
||||
|
||||
public ref class ClangParser |
||||
{ |
||||
public: |
||||
|
||||
static ParserTargetInfo^ GetTargetInfo(ParserOptions^ Opts) |
||||
{ |
||||
::Parser parser(Opts); |
||||
return parser.GetTargetInfo(); |
||||
} |
||||
|
||||
static ParserResult^ ParseHeader(ParserOptions^ Opts) |
||||
{ |
||||
if (!Opts->FileName) return nullptr; |
||||
|
||||
using namespace clix; |
||||
std::string File = marshalString<E_UTF8>(Opts->FileName); |
||||
|
||||
::Parser parser(Opts); |
||||
return parser.ParseHeader(File); |
||||
} |
||||
|
||||
static ParserResult^ ParseLibrary(ParserOptions^ Opts) |
||||
{ |
||||
if (!Opts->FileName) return nullptr; |
||||
|
||||
using namespace clix; |
||||
std::string File = marshalString<E_UTF8>(Opts->FileName); |
||||
|
||||
::Parser parser(Opts); |
||||
return parser.ParseLibrary(File); |
||||
} |
||||
}; |
||||
|
||||
} } |
@ -1,102 +0,0 @@
@@ -1,102 +0,0 @@
|
||||
/************************************************************************
|
||||
* |
||||
* CppSharp |
||||
* Licensed under the simplified BSD license. All rights reserved. |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#using <CppSharp.AST.dll> |
||||
using namespace System::Collections::Generic; |
||||
|
||||
public enum struct CppAbi |
||||
{ |
||||
Itanium, |
||||
Microsoft, |
||||
ARM |
||||
}; |
||||
|
||||
public ref struct ParserOptions |
||||
{ |
||||
ParserOptions() |
||||
{ |
||||
Arguments = gcnew List<System::String^>(); |
||||
IncludeDirs = gcnew List<System::String^>(); |
||||
SystemIncludeDirs = gcnew List<System::String^>(); |
||||
Defines = gcnew List<System::String^>(); |
||||
LibraryDirs = gcnew List<System::String^>(); |
||||
MicrosoftMode = false; |
||||
NoStandardIncludes = false; |
||||
NoBuiltinIncludes = false; |
||||
} |
||||
|
||||
List<System::String^>^ Arguments; |
||||
|
||||
// Include directories
|
||||
List<System::String^>^ IncludeDirs; |
||||
List<System::String^>^ SystemIncludeDirs; |
||||
List<System::String^>^ Defines; |
||||
List<System::String^>^ LibraryDirs; |
||||
|
||||
// C/C++ header file name.
|
||||
System::String^ FileName; |
||||
|
||||
CppSharp::AST::ASTContext^ ASTContext; |
||||
|
||||
int ToolSetToUse; |
||||
System::String^ TargetTriple; |
||||
|
||||
bool NoStandardIncludes; |
||||
bool NoBuiltinIncludes; |
||||
bool MicrosoftMode; |
||||
CppAbi Abi; |
||||
|
||||
bool Verbose; |
||||
}; |
||||
|
||||
public enum struct ParserDiagnosticLevel |
||||
{ |
||||
Ignored, |
||||
Note, |
||||
Warning, |
||||
Error, |
||||
Fatal |
||||
}; |
||||
|
||||
public value struct ParserDiagnostic |
||||
{ |
||||
System::String^ FileName; |
||||
System::String^ Message; |
||||
ParserDiagnosticLevel Level; |
||||
int LineNumber; |
||||
int ColumnNumber; |
||||
}; |
||||
|
||||
public enum struct ParserResultKind |
||||
{ |
||||
Success, |
||||
Error, |
||||
FileNotFound |
||||
}; |
||||
|
||||
public ref struct ParserResult |
||||
{ |
||||
ParserResult() |
||||
{ |
||||
Diagnostics = gcnew List<ParserDiagnostic>(); |
||||
} |
||||
|
||||
ParserResultKind Kind; |
||||
List<ParserDiagnostic>^ Diagnostics; |
||||
|
||||
CppSharp::AST::ASTContext^ ASTContext; |
||||
CppSharp::AST::NativeLibrary^ Library; |
||||
}; |
||||
|
||||
enum class SourceLocationKind |
||||
{ |
||||
Invalid, |
||||
Builtin, |
||||
CommandLine, |
||||
System, |
||||
User |
||||
}; |
@ -1,130 +0,0 @@
@@ -1,130 +0,0 @@
|
||||
/************************************************************************
|
||||
* |
||||
* CppSharp |
||||
* Licensed under the simplified BSD license. All rights reserved. |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#using <CppSharp.AST.dll> |
||||
|
||||
#include <llvm/Support/Host.h> |
||||
#include <clang/Frontend/CompilerInstance.h> |
||||
#include <clang/Frontend/CompilerInvocation.h> |
||||
#include <clang/Frontend/ASTConsumers.h> |
||||
#include <clang/Basic/FileManager.h> |
||||
#include <clang/Basic/TargetOptions.h> |
||||
#include <clang/Basic/TargetInfo.h> |
||||
#include <clang/Basic/IdentifierTable.h> |
||||
#include <clang/AST/ASTConsumer.h> |
||||
#include <clang/AST/Mangle.h> |
||||
#include <clang/AST/RawCommentList.h> |
||||
#include <clang/AST/Comment.h> |
||||
#include <clang/AST/RecordLayout.h> |
||||
#include <clang/AST/VTableBuilder.h> |
||||
#include <clang/Lex/Preprocessor.h> |
||||
#include <clang/Lex/PreprocessingRecord.h> |
||||
#include <clang/Parse/ParseAST.h> |
||||
#include <clang/Sema/Sema.h> |
||||
#include "CXXABI.h" |
||||
#include "Options.h" |
||||
#include "Target.h" |
||||
|
||||
#include <vcclr.h> |
||||
#include <string> |
||||
typedef std::string String; |
||||
|
||||
namespace clang { |
||||
class TargetCodeGenInfo; |
||||
namespace CodeGen { |
||||
class CodeGenTypes; |
||||
} |
||||
} |
||||
|
||||
#define Debug printf |
||||
|
||||
struct Parser |
||||
{ |
||||
Parser(ParserOptions^ Opts); |
||||
|
||||
void SetupHeader(); |
||||
ParserResult^ ParseHeader(const std::string& File); |
||||
ParserResult^ ParseLibrary(const std::string& File); |
||||
ParserResultKind ParseArchive(llvm::StringRef File, |
||||
llvm::MemoryBuffer *Buffer, |
||||
CppSharp::AST::NativeLibrary^ NativeLib); |
||||
ParserResultKind ParseSharedLib(llvm::StringRef File, |
||||
llvm::MemoryBuffer *Buffer, |
||||
CppSharp::AST::NativeLibrary^ NativeLib); |
||||
ParserTargetInfo^ GetTargetInfo(); |
||||
|
||||
protected: |
||||
|
||||
// AST traversers
|
||||
void WalkAST(); |
||||
CppSharp::AST::Declaration^ WalkDeclaration(clang::Decl* D, |
||||
bool IgnoreSystemDecls = true, bool CanBeDefinition = false); |
||||
CppSharp::AST::Declaration^ WalkDeclarationDef(clang::Decl* D); |
||||
CppSharp::AST::Enumeration^ WalkEnum(clang::EnumDecl* ED); |
||||
CppSharp::AST::Function^ WalkFunction(clang::FunctionDecl* FD, bool IsDependent = false, |
||||
bool AddToNamespace = true); |
||||
CppSharp::AST::Class^ WalkRecordCXX(clang::CXXRecordDecl* Record); |
||||
void WalkRecordCXX(clang::CXXRecordDecl* Record, CppSharp::AST::Class^ RC); |
||||
CppSharp::AST::ClassTemplateSpecialization^ |
||||
WalkClassTemplateSpecialization(clang::ClassTemplateSpecializationDecl* CTS); |
||||
CppSharp::AST::ClassTemplatePartialSpecialization^ |
||||
WalkClassTemplatePartialSpecialization(clang::ClassTemplatePartialSpecializationDecl* CTS); |
||||
CppSharp::AST::Method^ WalkMethodCXX(clang::CXXMethodDecl* MD, bool AddToClass = true); |
||||
CppSharp::AST::Field^ WalkFieldCXX(clang::FieldDecl* FD, CppSharp::AST::Class^ Class); |
||||
CppSharp::AST::ClassTemplate^ Parser::WalkClassTemplate(clang::ClassTemplateDecl* TD); |
||||
CppSharp::AST::FunctionTemplate^ Parser::WalkFunctionTemplate( |
||||
clang::FunctionTemplateDecl* TD); |
||||
CppSharp::AST::FunctionTemplateSpecialization^ WalkFunctionTemplateSpec(clang::FunctionTemplateSpecializationInfo* FTS, CppSharp::AST::Function^ Function); |
||||
CppSharp::AST::Variable^ WalkVariable(clang::VarDecl* VD); |
||||
CppSharp::AST::RawComment^ WalkRawComment(const clang::RawComment* RC); |
||||
CppSharp::AST::Type^ WalkType(clang::QualType QualType, clang::TypeLoc* TL = 0, |
||||
bool DesugarType = false); |
||||
CppSharp::AST::TemplateArgument WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc); |
||||
List<CppSharp::AST::TemplateArgument>^ WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, clang::TemplateSpecializationTypeLoc* TSTL); |
||||
List<CppSharp::AST::TemplateArgument>^ WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, const clang::ASTTemplateArgumentListInfo* TSTL); |
||||
CppSharp::AST::QualifiedType^ WalkQualifiedType(clang::TypeSourceInfo* TSI); |
||||
void WalkVTable(clang::CXXRecordDecl* RD, CppSharp::AST::Class^ C); |
||||
CppSharp::AST::VTableLayout^ WalkVTableLayout(const clang::VTableLayout& VTLayout); |
||||
CppSharp::AST::VTableComponent WalkVTableComponent(const clang::VTableComponent& Component); |
||||
CppSharp::AST::PreprocessedEntity^ WalkPreprocessedEntity(CppSharp::AST::Declaration^ Decl, |
||||
clang::PreprocessedEntity* PPEntity); |
||||
|
||||
// Clang helpers
|
||||
SourceLocationKind GetLocationKind(const clang::SourceLocation& Loc); |
||||
bool IsValidDeclaration(const clang::SourceLocation& Loc); |
||||
std::string GetDeclMangledName(clang::Decl* D, clang::TargetCXXABI ABI, |
||||
bool IsDependent = false); |
||||
std::string GetTypeName(const clang::Type* Type); |
||||
void WalkFunction(clang::FunctionDecl* FD, CppSharp::AST::Function^ F, |
||||
bool IsDependent = false); |
||||
void HandlePreprocessedEntities(CppSharp::AST::Declaration^ Decl); |
||||
void HandlePreprocessedEntities(CppSharp::AST::Declaration^ Decl, clang::SourceRange sourceRange, |
||||
CppSharp::AST::MacroLocation macroLocation = CppSharp::AST::MacroLocation::Unknown); |
||||
bool GetDeclText(clang::SourceRange SR, std::string& Text); |
||||
|
||||
CppSharp::AST::TranslationUnit^ GetTranslationUnit(clang::SourceLocation Loc, |
||||
SourceLocationKind *Kind = 0); |
||||
CppSharp::AST::TranslationUnit^ GetTranslationUnit(const clang::Decl* D); |
||||
|
||||
CppSharp::AST::DeclarationContext^ GetNamespace(clang::Decl* D, clang::DeclContext* Ctx); |
||||
CppSharp::AST::DeclarationContext^ GetNamespace(clang::Decl* D); |
||||
|
||||
void HandleDeclaration(clang::Decl* D, CppSharp::AST::Declaration^ Decl); |
||||
void HandleOriginalText(clang::Decl* D, CppSharp::AST::Declaration^ Decl); |
||||
void HandleComments(clang::Decl* D, CppSharp::AST::Declaration^ Decl); |
||||
void HandleDiagnostics(ParserResult^ res); |
||||
|
||||
int Index; |
||||
gcroot<CppSharp::AST::ASTContext^> Lib; |
||||
gcroot<CppSharp::AST::SymbolContext^> Symbols; |
||||
gcroot<ParserOptions^> Opts; |
||||
llvm::OwningPtr<clang::CompilerInstance> C; |
||||
clang::ASTContext* AST; |
||||
clang::TargetCXXABI::Kind TargetABI; |
||||
clang::TargetCodeGenInfo* CodeGenInfo; |
||||
clang::CodeGen::CodeGenTypes* CodeGenTypes; |
||||
}; |
@ -1,51 +0,0 @@
@@ -1,51 +0,0 @@
|
||||
clang_msvc_flags = |
||||
{ |
||||
"/wd4146", "/wd4244", "/wd4800", "/wd4345", |
||||
"/wd4355", "/wd4996", "/wd4624", "/wd4291" |
||||
} |
||||
|
||||
project "CppSharp.Parser" |
||||
|
||||
kind "SharedLib" |
||||
language "C++" |
||||
SetupNativeProject() |
||||
|
||||
dependson { "CppSharp.AST" } |
||||
flags { common_flags, "Managed" } |
||||
|
||||
usingdirs { libdir } |
||||
|
||||
-- usingdirs is only supported in per-file configs in our |
||||
-- premake build. remove this once this support is added |
||||
-- at the project level. |
||||
|
||||
configuration { "Main.cpp" } |
||||
flags { "Managed" } |
||||
usingdirs { libdir } |
||||
|
||||
configuration { "Parser.cpp" } |
||||
flags { "Managed" } |
||||
usingdirs { libdir } |
||||
|
||||
configuration { "Comments.cpp" } |
||||
flags { "Managed" } |
||||
usingdirs { libdir } |
||||
|
||||
configuration "vs*" |
||||
buildoptions { clang_msvc_flags } |
||||
files { "VSLookup.cpp" } |
||||
|
||||
configuration "*" |
||||
|
||||
files |
||||
{ |
||||
"*.h", |
||||
"*.cpp", |
||||
"*.lua" |
||||
} |
||||
|
||||
SetupLLVMIncludes() |
||||
SetupLLVMLibs() |
||||
|
||||
configuration "*" |
||||
|
@ -1,69 +0,0 @@
@@ -1,69 +0,0 @@
|
||||
/************************************************************************
|
||||
* |
||||
* CppSharp |
||||
* Licensed under the simplified BSD license. All rights reserved. |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#using <CppSharp.AST.dll> |
||||
using namespace System::Collections::Generic; |
||||
|
||||
public enum ParserIntType |
||||
{ |
||||
NoInt = 0, |
||||
SignedChar, |
||||
UnsignedChar, |
||||
SignedShort, |
||||
UnsignedShort, |
||||
SignedInt, |
||||
UnsignedInt, |
||||
SignedLong, |
||||
UnsignedLong, |
||||
SignedLongLong, |
||||
UnsignedLongLong |
||||
}; |
||||
|
||||
public ref struct ParserTargetInfo |
||||
{ |
||||
System::String^ ABI; |
||||
|
||||
ParserIntType Char16Type; |
||||
ParserIntType Char32Type; |
||||
ParserIntType Int64Type; |
||||
ParserIntType IntMaxType; |
||||
ParserIntType IntPtrType; |
||||
ParserIntType SizeType; |
||||
ParserIntType UIntMaxType; |
||||
ParserIntType WCharType; |
||||
ParserIntType WIntType; |
||||
|
||||
unsigned int BoolAlign; |
||||
unsigned int BoolWidth; |
||||
unsigned int CharAlign; |
||||
unsigned int CharWidth; |
||||
unsigned int Char16Align; |
||||
unsigned int Char16Width; |
||||
unsigned int Char32Align; |
||||
unsigned int Char32Width; |
||||
unsigned int HalfAlign; |
||||
unsigned int HalfWidth; |
||||
unsigned int FloatAlign; |
||||
unsigned int FloatWidth; |
||||
unsigned int DoubleAlign; |
||||
unsigned int DoubleWidth; |
||||
unsigned int ShortAlign; |
||||
unsigned int ShortWidth; |
||||
unsigned int IntAlign; |
||||
unsigned int IntWidth; |
||||
unsigned int IntMaxTWidth; |
||||
unsigned int LongAlign; |
||||
unsigned int LongWidth; |
||||
unsigned int LongDoubleAlign; |
||||
unsigned int LongDoubleWidth; |
||||
unsigned int LongLongAlign; |
||||
unsigned int LongLongWidth; |
||||
unsigned int PointerAlign; |
||||
unsigned int PointerWidth; |
||||
unsigned int WCharAlign; |
||||
unsigned int WCharWidth; |
||||
}; |
@ -1,269 +0,0 @@
@@ -1,269 +0,0 @@
|
||||
/************************************************************************
|
||||
* |
||||
* CppSharp |
||||
* Licensed under the simplified BSD license. All rights reserved. |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#ifdef _MSC_VER |
||||
|
||||
#include <string> |
||||
#include <vector> |
||||
#include <cctype> |
||||
|
||||
// Include the necessary headers to interface with the Windows registry and
|
||||
// environment.
|
||||
#define WIN32_LEAN_AND_MEAN |
||||
#define NOGDI |
||||
#define NOMINMAX |
||||
#include <Windows.h> |
||||
|
||||
/// \brief Read registry string.
|
||||
/// This also supports a means to look for high-versioned keys by use
|
||||
/// of a $VERSION placeholder in the key path.
|
||||
/// $VERSION in the key path is a placeholder for the version number,
|
||||
/// causing the highest value path to be searched for and used.
|
||||
/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
|
||||
/// There can be additional characters in the component. Only the numeric
|
||||
/// characters are compared.
|
||||
static bool getSystemRegistryString(const char *keyPath, const char *valueName, |
||||
char *value, size_t maxLength) { |
||||
HKEY hRootKey = NULL; |
||||
HKEY hKey = NULL; |
||||
const char* subKey = NULL; |
||||
DWORD valueType; |
||||
DWORD valueSize = maxLength - 1; |
||||
long lResult; |
||||
bool returnValue = false; |
||||
|
||||
if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { |
||||
hRootKey = HKEY_CLASSES_ROOT; |
||||
subKey = keyPath + 18; |
||||
} else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { |
||||
hRootKey = HKEY_USERS; |
||||
subKey = keyPath + 11; |
||||
} else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { |
||||
hRootKey = HKEY_LOCAL_MACHINE; |
||||
subKey = keyPath + 19; |
||||
} else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { |
||||
hRootKey = HKEY_CURRENT_USER; |
||||
subKey = keyPath + 18; |
||||
} else { |
||||
return false; |
||||
} |
||||
|
||||
const char *placeHolder = strstr(subKey, "$VERSION"); |
||||
char bestName[256]; |
||||
bestName[0] = '\0'; |
||||
// If we have a $VERSION placeholder, do the highest-version search.
|
||||
if (placeHolder) { |
||||
const char *keyEnd = placeHolder - 1; |
||||
const char *nextKey = placeHolder; |
||||
// Find end of previous key.
|
||||
while ((keyEnd > subKey) && (*keyEnd != '\\')) |
||||
keyEnd--; |
||||
// Find end of key containing $VERSION.
|
||||
while (*nextKey && (*nextKey != '\\')) |
||||
nextKey++; |
||||
size_t partialKeyLength = keyEnd - subKey; |
||||
char partialKey[256]; |
||||
if (partialKeyLength > sizeof(partialKey)) |
||||
partialKeyLength = sizeof(partialKey); |
||||
strncpy(partialKey, subKey, partialKeyLength); |
||||
partialKey[partialKeyLength] = '\0'; |
||||
HKEY hTopKey = NULL; |
||||
lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ, &hTopKey); |
||||
if (lResult == ERROR_SUCCESS) { |
||||
char keyName[256]; |
||||
int bestIndex = -1; |
||||
double bestValue = 0.0; |
||||
DWORD index, size = sizeof(keyName) - 1; |
||||
for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, |
||||
NULL, NULL, NULL) == ERROR_SUCCESS; index++) { |
||||
const char *sp = keyName; |
||||
while (*sp && !isdigit(*sp)) |
||||
sp++; |
||||
if (!*sp) |
||||
continue; |
||||
const char *ep = sp + 1; |
||||
while (*ep && (isdigit(*ep) || (*ep == '.'))) |
||||
ep++; |
||||
char numBuf[32]; |
||||
strncpy(numBuf, sp, sizeof(numBuf) - 1); |
||||
numBuf[sizeof(numBuf) - 1] = '\0'; |
||||
double value = strtod(numBuf, NULL); |
||||
|
||||
// Check if InstallDir key value exists.
|
||||
bool isViableVersion = false; |
||||
|
||||
lResult = RegOpenKeyExA(hTopKey, keyName, 0, KEY_READ, &hKey); |
||||
if (lResult == ERROR_SUCCESS) { |
||||
lResult = RegQueryValueExA(hKey, valueName, NULL, NULL, NULL, NULL); |
||||
if (lResult == ERROR_SUCCESS) |
||||
isViableVersion = true; |
||||
RegCloseKey(hKey); |
||||
} |
||||
|
||||
if (isViableVersion && (value > bestValue)) { |
||||
bestIndex = (int)index; |
||||
bestValue = value; |
||||
strcpy(bestName, keyName); |
||||
} |
||||
size = sizeof(keyName) - 1; |
||||
} |
||||
// If we found the highest versioned key, open the key and get the value.
|
||||
if (bestIndex != -1) { |
||||
// Append rest of key.
|
||||
strncat(bestName, nextKey, sizeof(bestName) - 1); |
||||
bestName[sizeof(bestName) - 1] = '\0'; |
||||
// Open the chosen key path remainder.
|
||||
lResult = RegOpenKeyExA(hTopKey, bestName, 0, KEY_READ, &hKey); |
||||
if (lResult == ERROR_SUCCESS) { |
||||
lResult = RegQueryValueExA(hKey, valueName, NULL, &valueType, |
||||
(LPBYTE)value, &valueSize); |
||||
if (lResult == ERROR_SUCCESS) |
||||
returnValue = true; |
||||
RegCloseKey(hKey); |
||||
} |
||||
} |
||||
RegCloseKey(hTopKey); |
||||
} |
||||
} else { |
||||
lResult = RegOpenKeyExA(hRootKey, subKey, 0, KEY_READ, &hKey); |
||||
if (lResult == ERROR_SUCCESS) { |
||||
lResult = RegQueryValueExA(hKey, valueName, NULL, &valueType, |
||||
(LPBYTE)value, &valueSize); |
||||
if (lResult == ERROR_SUCCESS) |
||||
returnValue = true; |
||||
RegCloseKey(hKey); |
||||
} |
||||
} |
||||
return returnValue; |
||||
} |
||||
|
||||
/// \brief Get Windows SDK installation directory.
|
||||
static bool getWindowsSDKDir(std::string &path) { |
||||
char windowsSDKInstallDir[256]; |
||||
// Try the Windows registry.
|
||||
bool hasSDKDir = getSystemRegistryString( |
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", |
||||
"InstallationFolder", |
||||
windowsSDKInstallDir, |
||||
sizeof(windowsSDKInstallDir) - 1); |
||||
// If we have both vc80 and vc90, pick version we were compiled with.
|
||||
if (hasSDKDir && windowsSDKInstallDir[0]) { |
||||
path = windowsSDKInstallDir; |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
// Get Visual Studio installation directory.
|
||||
static bool getVisualStudioDir(std::string &path) { |
||||
// First check the environment variables that vsvars32.bat sets.
|
||||
const char* vcinstalldir = getenv("VCINSTALLDIR"); |
||||
if (vcinstalldir) { |
||||
char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); |
||||
if (p) |
||||
*p = '\0'; |
||||
path = vcinstalldir; |
||||
return true; |
||||
} |
||||
|
||||
char vsIDEInstallDir[256]; |
||||
char vsExpressIDEInstallDir[256]; |
||||
// Then try the windows registry.
|
||||
bool hasVCDir = getSystemRegistryString( |
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", |
||||
"InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); |
||||
bool hasVCExpressDir = getSystemRegistryString( |
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", |
||||
"InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); |
||||
// If we have both vc80 and vc90, pick version we were compiled with.
|
||||
if (hasVCDir && vsIDEInstallDir[0]) { |
||||
char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); |
||||
if (p) |
||||
*p = '\0'; |
||||
path = vsIDEInstallDir; |
||||
return true; |
||||
} |
||||
|
||||
if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { |
||||
char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); |
||||
if (p) |
||||
*p = '\0'; |
||||
path = vsExpressIDEInstallDir; |
||||
return true; |
||||
} |
||||
|
||||
// Try the environment.
|
||||
const char *vs120comntools = getenv("VS120COMNTOOLS"); |
||||
const char *vs110comntools = getenv("VS110COMNTOOLS"); |
||||
const char *vs100comntools = getenv("VS100COMNTOOLS"); |
||||
const char *vs90comntools = getenv("VS90COMNTOOLS"); |
||||
const char *vs80comntools = getenv("VS80COMNTOOLS"); |
||||
const char *vscomntools = NULL; |
||||
|
||||
// Try to find the version that we were compiled with
|
||||
if(false) {} |
||||
#if (_MSC_VER >= 1800) // VC120
|
||||
else if (vs120comntools) { |
||||
vscomntools = vs120comntools; |
||||
} |
||||
#elif (_MSC_VER == 1700) // VC110
|
||||
else if (vs110comntools) { |
||||
vscomntools = vs110comntools; |
||||
} |
||||
#elif (_MSC_VER == 1600) // VC100
|
||||
else if(vs100comntools) { |
||||
vscomntools = vs100comntools; |
||||
} |
||||
#elif (_MSC_VER == 1500) // VC80
|
||||
else if(vs90comntools) { |
||||
vscomntools = vs90comntools; |
||||
} |
||||
#elif (_MSC_VER == 1400) // VC80
|
||||
else if(vs80comntools) { |
||||
vscomntools = vs80comntools; |
||||
} |
||||
#endif |
||||
// Otherwise find any version we can
|
||||
else if (vs120comntools) |
||||
vscomntools = vs120comntools; |
||||
else if (vs110comntools) |
||||
vscomntools = vs110comntools; |
||||
else if (vs100comntools) |
||||
vscomntools = vs100comntools; |
||||
else if (vs90comntools) |
||||
vscomntools = vs90comntools; |
||||
else if (vs80comntools) |
||||
vscomntools = vs80comntools; |
||||
|
||||
if (vscomntools && *vscomntools) { |
||||
const char *p = strstr(vscomntools, "\\Common7\\Tools"); |
||||
path = p ? std::string(vscomntools, p) : vscomntools; |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
std::vector<std::string> GetWindowsSystemIncludeDirs() { |
||||
std::vector<std::string> Paths; |
||||
|
||||
std::string VSDir; |
||||
std::string WindowsSDKDir; |
||||
|
||||
// When built with access to the proper Windows APIs, try to actually find
|
||||
// the correct include paths first.
|
||||
if (getVisualStudioDir(VSDir)) { |
||||
Paths.push_back(VSDir + "\\VC\\include"); |
||||
if (getWindowsSDKDir(WindowsSDKDir)) |
||||
Paths.push_back(WindowsSDKDir + "\\include"); |
||||
else |
||||
Paths.push_back(VSDir + "\\VC\\PlatformSDK\\Include"); |
||||
} |
||||
|
||||
return Paths; |
||||
} |
||||
|
||||
#endif |
Loading…
Reference in new issue