1239313Sdim//===- ObjCRuntime.cpp - Objective-C Runtime Handling -----------*- C++ -*-===//
2239313Sdim//
3239313Sdim//                     The LLVM Compiler Infrastructure
4239313Sdim//
5239313Sdim// This file is distributed under the University of Illinois Open Source
6239313Sdim// License. See LICENSE.TXT for details.
7239313Sdim//
8239313Sdim//===----------------------------------------------------------------------===//
9239313Sdim//
10239313Sdim// This file implements the ObjCRuntime class, which represents the
11239313Sdim// target Objective-C runtime.
12239313Sdim//
13239313Sdim//===----------------------------------------------------------------------===//
14239313Sdim#include "clang/Basic/ObjCRuntime.h"
15239313Sdim#include "llvm/Support/raw_ostream.h"
16239313Sdim
17239313Sdimusing namespace clang;
18239313Sdim
19239313Sdimstd::string ObjCRuntime::getAsString() const {
20239313Sdim  std::string Result;
21239313Sdim  {
22239313Sdim    llvm::raw_string_ostream Out(Result);
23239313Sdim    Out << *this;
24239313Sdim  }
25239313Sdim  return Result;
26239313Sdim}
27239313Sdim
28239313Sdimraw_ostream &clang::operator<<(raw_ostream &out, const ObjCRuntime &value) {
29239313Sdim  switch (value.getKind()) {
30239313Sdim  case ObjCRuntime::MacOSX: out << "macosx"; break;
31239313Sdim  case ObjCRuntime::FragileMacOSX: out << "macosx-fragile"; break;
32239313Sdim  case ObjCRuntime::iOS: out << "ios"; break;
33239313Sdim  case ObjCRuntime::GNUstep: out << "gnustep"; break;
34239313Sdim  case ObjCRuntime::GCC: out << "gcc"; break;
35239313Sdim  case ObjCRuntime::ObjFW: out << "objfw"; break;
36239313Sdim  }
37239313Sdim  if (value.getVersion() > VersionTuple(0)) {
38239313Sdim    out << '-' << value.getVersion();
39239313Sdim  }
40239313Sdim  return out;
41239313Sdim}
42239313Sdim
43239313Sdimbool ObjCRuntime::tryParse(StringRef input) {
44239313Sdim  // Look for the last dash.
45239313Sdim  std::size_t dash = input.rfind('-');
46239313Sdim
47239313Sdim  // We permit dashes in the runtime name, and we also permit the
48239313Sdim  // version to be omitted, so if we see a dash not followed by a
49239313Sdim  // digit then we need to ignore it.
50239313Sdim  if (dash != StringRef::npos && dash + 1 != input.size() &&
51239313Sdim      (input[dash+1] < '0' || input[dash+1] > '9')) {
52239313Sdim    dash = StringRef::npos;
53239313Sdim  }
54239313Sdim
55239313Sdim  // Everything prior to that must be a valid string name.
56239313Sdim  Kind kind;
57239313Sdim  StringRef runtimeName = input.substr(0, dash);
58239313Sdim  Version = VersionTuple(0);
59239313Sdim  if (runtimeName == "macosx") {
60239313Sdim    kind = ObjCRuntime::MacOSX;
61239313Sdim  } else if (runtimeName == "macosx-fragile") {
62239313Sdim    kind = ObjCRuntime::FragileMacOSX;
63239313Sdim  } else if (runtimeName == "ios") {
64239313Sdim    kind = ObjCRuntime::iOS;
65239313Sdim  } else if (runtimeName == "gnustep") {
66239313Sdim    // If no version is specified then default to the most recent one that we
67239313Sdim    // know about.
68239313Sdim    Version = VersionTuple(1, 6);
69239313Sdim    kind = ObjCRuntime::GNUstep;
70239313Sdim  } else if (runtimeName == "gcc") {
71239313Sdim    kind = ObjCRuntime::GCC;
72239313Sdim  } else if (runtimeName == "objfw") {
73239313Sdim    kind = ObjCRuntime::ObjFW;
74263509Sdim    Version = VersionTuple(0, 8);
75239313Sdim  } else {
76239313Sdim    return true;
77239313Sdim  }
78239313Sdim  TheKind = kind;
79263509Sdim
80239313Sdim  if (dash != StringRef::npos) {
81239313Sdim    StringRef verString = input.substr(dash + 1);
82263509Sdim    if (Version.tryParse(verString))
83239313Sdim      return true;
84239313Sdim  }
85239313Sdim
86263509Sdim  if (kind == ObjCRuntime::ObjFW && Version > VersionTuple(0, 8))
87263509Sdim    Version = VersionTuple(0, 8);
88263509Sdim
89239313Sdim  return false;
90239313Sdim}
91