Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 1 | #include "Coordinator.h" |
| 2 | |
| 3 | #include "AST.h" |
| 4 | #include "RefType.h" |
| 5 | |
| 6 | #include <android-base/logging.h> |
| 7 | |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 8 | extern android::status_t parseFile(android::AST *ast, const char *path); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 9 | |
| 10 | namespace android { |
| 11 | |
| 12 | Coordinator::Coordinator() {} |
| 13 | Coordinator::~Coordinator() {} |
| 14 | |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 15 | AST *Coordinator::parse(const FQName &fqName) { |
| 16 | CHECK(fqName.isFullyQualified()); |
| 17 | |
| 18 | ssize_t index = mCache.indexOfKey(fqName); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 19 | if (index >= 0) { |
| 20 | AST *ast = mCache.valueAt(index); |
| 21 | |
| 22 | return ast; |
| 23 | } |
| 24 | |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 25 | // 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 Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 41 | |
| 42 | AST *ast = new AST(this); |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 43 | status_t err = parseFile(ast, path.c_str()); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 44 | |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 45 | if (err != OK) { |
| 46 | delete ast; |
| 47 | ast = NULL; |
| 48 | |
| 49 | return NULL; |
| 50 | } |
| 51 | |
| 52 | mCache.add(fqName, ast); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 53 | |
| 54 | return ast; |
| 55 | } |
| 56 | |
| 57 | // static |
| 58 | std::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 | |
| 88 | Type *Coordinator::lookupType(const FQName &fqName) const { |
| 89 | // Fully qualified. |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 90 | CHECK(fqName.isFullyQualified()); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 91 | |
| 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 Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 100 | // 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 Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 104 | if (index >= 0) { |
| 105 | AST *ast = mCache.valueAt(index); |
| 106 | Type *type = ast->lookupTypeInternal(fqName.name()); |
| 107 | |
| 108 | if (type != NULL) { |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 109 | return new RefType(fqName.string().c_str(), type); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 110 | } |
| 111 | } |
| 112 | |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 113 | FQName typesName(fqName.package(), fqName.version(), "types"); |
| 114 | index = mCache.indexOfKey(typesName); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 115 | if (index >= 0) { |
| 116 | AST *ast = mCache.valueAt(index); |
| 117 | Type *type = ast->lookupTypeInternal(fqName.name()); |
| 118 | |
| 119 | if (type != NULL) { |
Andreas Huber | 68f2459 | 2016-07-29 14:53:48 -0700 | [diff] [blame^] | 120 | return new RefType(fqName.string().c_str(), type); |
Andreas Huber | 5345ec2 | 2016-07-29 13:33:27 -0700 | [diff] [blame] | 121 | } |
| 122 | } |
| 123 | |
| 124 | return NULL; |
| 125 | } |
| 126 | |
| 127 | } // namespace android |
| 128 | |