1de3ef502SDouglas Gregor //===--- Module.h - Describe a module ---------------------------*- C++ -*-===//
2de3ef502SDouglas Gregor //
3de3ef502SDouglas Gregor //                     The LLVM Compiler Infrastructure
4de3ef502SDouglas Gregor //
5de3ef502SDouglas Gregor // This file is distributed under the University of Illinois Open Source
6de3ef502SDouglas Gregor // License. See LICENSE.TXT for details.
7de3ef502SDouglas Gregor //
8de3ef502SDouglas Gregor //===----------------------------------------------------------------------===//
9de3ef502SDouglas Gregor //
10de3ef502SDouglas Gregor // This file defines the Module class, which describes a module in the source
11de3ef502SDouglas Gregor // code.
12de3ef502SDouglas Gregor //
13de3ef502SDouglas Gregor //===----------------------------------------------------------------------===//
14de3ef502SDouglas Gregor #include "clang/Basic/Module.h"
15de3ef502SDouglas Gregor #include "clang/Basic/FileManager.h"
16de3ef502SDouglas Gregor #include "llvm/Support/raw_ostream.h"
17de3ef502SDouglas Gregor using namespace clang;
18de3ef502SDouglas Gregor 
19de3ef502SDouglas Gregor Module::~Module() {
20de3ef502SDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
21de3ef502SDouglas Gregor                                         IEnd = SubModules.end();
22de3ef502SDouglas Gregor        I != IEnd; ++I) {
23de3ef502SDouglas Gregor     delete I->getValue();
24de3ef502SDouglas Gregor   }
25de3ef502SDouglas Gregor 
26de3ef502SDouglas Gregor }
27de3ef502SDouglas Gregor 
28de3ef502SDouglas Gregor std::string Module::getFullModuleName() const {
29de3ef502SDouglas Gregor   llvm::SmallVector<StringRef, 2> Names;
30de3ef502SDouglas Gregor 
31de3ef502SDouglas Gregor   // Build up the set of module names (from innermost to outermost).
32de3ef502SDouglas Gregor   for (const Module *M = this; M; M = M->Parent)
33de3ef502SDouglas Gregor     Names.push_back(M->Name);
34de3ef502SDouglas Gregor 
35de3ef502SDouglas Gregor   std::string Result;
36de3ef502SDouglas Gregor   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
37de3ef502SDouglas Gregor                                                       IEnd = Names.rend();
38de3ef502SDouglas Gregor        I != IEnd; ++I) {
39de3ef502SDouglas Gregor     if (!Result.empty())
40de3ef502SDouglas Gregor       Result += '.';
41de3ef502SDouglas Gregor 
42de3ef502SDouglas Gregor     Result += *I;
43de3ef502SDouglas Gregor   }
44de3ef502SDouglas Gregor 
45de3ef502SDouglas Gregor   return Result;
46de3ef502SDouglas Gregor }
47de3ef502SDouglas Gregor 
48de3ef502SDouglas Gregor StringRef Module::getTopLevelModuleName() const {
49de3ef502SDouglas Gregor   const Module *Top = this;
50de3ef502SDouglas Gregor   while (Top->Parent)
51de3ef502SDouglas Gregor     Top = Top->Parent;
52de3ef502SDouglas Gregor 
53de3ef502SDouglas Gregor   return Top->Name;
54de3ef502SDouglas Gregor }
55de3ef502SDouglas Gregor 
56*24bb923aSDouglas Gregor static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) {
57*24bb923aSDouglas Gregor   for (unsigned I = 0, N = Id.size(); I != N; ++I) {
58*24bb923aSDouglas Gregor     if (I)
59*24bb923aSDouglas Gregor       OS << ".";
60*24bb923aSDouglas Gregor     OS << Id[I].first;
61*24bb923aSDouglas Gregor   }
62*24bb923aSDouglas Gregor }
63*24bb923aSDouglas Gregor 
64de3ef502SDouglas Gregor void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
65de3ef502SDouglas Gregor   OS.indent(Indent);
66de3ef502SDouglas Gregor   if (IsFramework)
67de3ef502SDouglas Gregor     OS << "framework ";
68de3ef502SDouglas Gregor   if (IsExplicit)
69de3ef502SDouglas Gregor     OS << "explicit ";
70de3ef502SDouglas Gregor   OS << "module " << Name << " {\n";
71de3ef502SDouglas Gregor 
72de3ef502SDouglas Gregor   if (UmbrellaHeader) {
73de3ef502SDouglas Gregor     OS.indent(Indent + 2);
74de3ef502SDouglas Gregor     OS << "umbrella \"";
75de3ef502SDouglas Gregor     OS.write_escaped(UmbrellaHeader->getName());
76de3ef502SDouglas Gregor     OS << "\"\n";
77de3ef502SDouglas Gregor   }
78de3ef502SDouglas Gregor 
79de3ef502SDouglas Gregor   for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
80de3ef502SDouglas Gregor     OS.indent(Indent + 2);
81de3ef502SDouglas Gregor     OS << "header \"";
82de3ef502SDouglas Gregor     OS.write_escaped(Headers[I]->getName());
83de3ef502SDouglas Gregor     OS << "\"\n";
84de3ef502SDouglas Gregor   }
85de3ef502SDouglas Gregor 
86de3ef502SDouglas Gregor   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
87de3ef502SDouglas Gregor        MIEnd = SubModules.end();
88de3ef502SDouglas Gregor        MI != MIEnd; ++MI)
89de3ef502SDouglas Gregor     MI->getValue()->print(OS, Indent + 2);
90de3ef502SDouglas Gregor 
91*24bb923aSDouglas Gregor   for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
92*24bb923aSDouglas Gregor     OS.indent(Indent + 2);
93*24bb923aSDouglas Gregor     OS << "export " << Exports[I].getPointer()->getFullModuleName();
94*24bb923aSDouglas Gregor     if (Exports[I].getInt())
95*24bb923aSDouglas Gregor       OS << ".*";
96*24bb923aSDouglas Gregor     OS << "\n";
97*24bb923aSDouglas Gregor   }
98*24bb923aSDouglas Gregor 
99*24bb923aSDouglas Gregor   for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
100*24bb923aSDouglas Gregor     OS.indent(Indent + 2);
101*24bb923aSDouglas Gregor     OS << "export ";
102*24bb923aSDouglas Gregor     printModuleId(OS, UnresolvedExports[I].Id);
103*24bb923aSDouglas Gregor     if (UnresolvedExports[I].Wildcard)
104*24bb923aSDouglas Gregor       OS << ".*";
105*24bb923aSDouglas Gregor     OS << "\n";
106*24bb923aSDouglas Gregor   }
107*24bb923aSDouglas Gregor 
108de3ef502SDouglas Gregor   OS.indent(Indent);
109de3ef502SDouglas Gregor   OS << "}\n";
110de3ef502SDouglas Gregor }
111de3ef502SDouglas Gregor 
112de3ef502SDouglas Gregor void Module::dump() const {
113de3ef502SDouglas Gregor   print(llvm::errs());
114de3ef502SDouglas Gregor }
115de3ef502SDouglas Gregor 
116de3ef502SDouglas Gregor 
117