blob: c89c2daf7c827c67e55a6c73a60a8af7e3cb499d [file] [log] [blame]
Andreas Huber5345ec22016-07-29 13:33:27 -07001#include "Coordinator.h"
2
3#include "AST.h"
4#include "RefType.h"
5
6#include <android-base/logging.h>
7
Andreas Huber68f24592016-07-29 14:53:48 -07008extern android::status_t parseFile(android::AST *ast, const char *path);
Andreas Huber5345ec22016-07-29 13:33:27 -07009
10namespace android {
11
12Coordinator::Coordinator() {}
13Coordinator::~Coordinator() {}
14
Andreas Huber68f24592016-07-29 14:53:48 -070015AST *Coordinator::parse(const FQName &fqName) {
16 CHECK(fqName.isFullyQualified());
17
18 ssize_t index = mCache.indexOfKey(fqName);
Andreas Huber5345ec22016-07-29 13:33:27 -070019 if (index >= 0) {
20 AST *ast = mCache.valueAt(index);
21
22 return ast;
23 }
24
Andreas Huber68f24592016-07-29 14:53:48 -070025 // Add this to the cache immediately, so we can discover circular imports.
26 mCache.add(fqName, NULL);
27
28 const std::string packagePath = GetPackagePath(fqName);
29
30 if (fqName.name() != "types") {
31 // Any interface file implicitly imports its package's types.hal.
32 FQName typesName(fqName.package(), fqName.version(), "types");
33 (void)parse(typesName);
34
35 // fall through.
36 }
37
38 std::string path = packagePath;
39 path.append(fqName.name());
40 path.append(".hal");
Andreas Huber5345ec22016-07-29 13:33:27 -070041
42 AST *ast = new AST(this);
Andreas Huber68f24592016-07-29 14:53:48 -070043 status_t err = parseFile(ast, path.c_str());
Andreas Huber5345ec22016-07-29 13:33:27 -070044
Andreas Huber68f24592016-07-29 14:53:48 -070045 if (err != OK) {
46 delete ast;
47 ast = NULL;
48
49 return NULL;
50 }
51
52 mCache.add(fqName, ast);
Andreas Huber5345ec22016-07-29 13:33:27 -070053
54 return ast;
55}
56
57// static
58std::string Coordinator::GetPackagePath(const FQName &fqName) {
59 CHECK(!fqName.package().empty());
60 CHECK(!fqName.version().empty());
61 const char *const kPrefix = "android.hardware.";
62 CHECK_EQ(fqName.package().find(kPrefix), 0u);
63
64 const std::string packageSuffix = fqName.package().substr(strlen(kPrefix));
65
66 std::string packagePath =
67 "/Volumes/Source/nyc-mr1-dev-lego/hardware/interfaces/";
68
69 size_t startPos = 0;
70 size_t dotPos;
71 while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) {
72 packagePath.append(packageSuffix.substr(startPos, dotPos - startPos));
73 packagePath.append("/");
74
75 startPos = dotPos + 1;
76 }
77 CHECK_LT(startPos + 1, packageSuffix.length());
78 packagePath.append(packageSuffix.substr(startPos));
79 packagePath.append("/");
80
81 CHECK_EQ(fqName.version().find('@'), 0u);
82 packagePath.append(fqName.version().substr(1));
83 packagePath.append("/");
84
85 return packagePath;
86}
87
88Type *Coordinator::lookupType(const FQName &fqName) const {
89 // Fully qualified.
Andreas Huber68f24592016-07-29 14:53:48 -070090 CHECK(fqName.isFullyQualified());
Andreas Huber5345ec22016-07-29 13:33:27 -070091
92 std::string topType;
93 size_t dotPos = fqName.name().find('.');
94 if (dotPos == std::string::npos) {
95 topType = fqName.name();
96 } else {
97 topType = fqName.name().substr(0, dotPos);
98 }
99
Andreas Huber68f24592016-07-29 14:53:48 -0700100 // Assuming {topType} is the name of an interface type, let's see if the
101 // associated {topType}.hal file was imported.
102 FQName ifaceName(fqName.package(), fqName.version(), topType);
103 ssize_t index = mCache.indexOfKey(ifaceName);
Andreas Huber5345ec22016-07-29 13:33:27 -0700104 if (index >= 0) {
105 AST *ast = mCache.valueAt(index);
106 Type *type = ast->lookupTypeInternal(fqName.name());
107
108 if (type != NULL) {
Andreas Huber68f24592016-07-29 14:53:48 -0700109 return new RefType(fqName.string().c_str(), type);
Andreas Huber5345ec22016-07-29 13:33:27 -0700110 }
111 }
112
Andreas Huber68f24592016-07-29 14:53:48 -0700113 FQName typesName(fqName.package(), fqName.version(), "types");
114 index = mCache.indexOfKey(typesName);
Andreas Huber5345ec22016-07-29 13:33:27 -0700115 if (index >= 0) {
116 AST *ast = mCache.valueAt(index);
117 Type *type = ast->lookupTypeInternal(fqName.name());
118
119 if (type != NULL) {
Andreas Huber68f24592016-07-29 14:53:48 -0700120 return new RefType(fqName.string().c_str(), type);
Andreas Huber5345ec22016-07-29 13:33:27 -0700121 }
122 }
123
124 return NULL;
125}
126
127} // namespace android
128