Coordinator.cpp revision 0d0f9a2e0195a8609f1939c35bd8907253b68249
15345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "Coordinator.h"
25345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
35345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "AST.h"
45345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
55345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include <android-base/logging.h>
6dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber#include <iterator>
7d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber#include <sys/dir.h>
8d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber#include <sys/stat.h>
95345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
100d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huberextern android::status_t parseFile(android::AST *ast);
115345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
125345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Hubernamespace android {
135345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
14dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::Coordinator(
15dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        const std::vector<std::string> &packageRootPaths,
16dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        const std::vector<std::string> &packageRoots)
17dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    : mPackageRootPaths(packageRootPaths),
18dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber      mPackageRoots(packageRoots) {
19dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // empty
20dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber}
21dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber
22dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::~Coordinator() {
23dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // empty
24dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
255345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas HuberAST *Coordinator::parse(const FQName &fqName) {
2768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
2868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
296e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber    // LOG(INFO) << "parsing " << fqName.string();
306e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
3168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    ssize_t index = mCache.indexOfKey(fqName);
325345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
335345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
345345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
355345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        return ast;
365345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
375345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
3868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Add this to the cache immediately, so we can discover circular imports.
3968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    mCache.add(fqName, NULL);
4068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
4168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (fqName.name() != "types") {
4268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // Any interface file implicitly imports its package's types.hal.
4368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        FQName typesName(fqName.package(), fqName.version(), "types");
4468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        (void)parse(typesName);
4568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
4668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // fall through.
4768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
4868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
49dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    std::string path = getPackagePath(fqName);
50dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
5168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(fqName.name());
5268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(".hal");
535345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
540d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber    AST *ast = new AST(this, path);
550d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber    status_t err = parseFile(ast);
5668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
5768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (err != OK) {
586e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        // LOG(ERROR) << "parsing '" << path << "' FAILED.";
596e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
6068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        delete ast;
6168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        ast = NULL;
625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
6368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        return NULL;
6468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
6568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
66a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (ast->package().package() != fqName.package()
67a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            || ast->package().version() != fqName.version()) {
6870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber        fprintf(stderr,
6970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                "ERROR: File at '%s' does not match expected package and/or "
700d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                "version.\n",
7170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                path.c_str());
72a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
73a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        err = UNKNOWN_ERROR;
74a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    } else {
75a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        std::string ifaceName;
76a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        if (ast->isInterface(&ifaceName)) {
77a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            if (fqName.name() == "types") {
7870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                fprintf(stderr,
7970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        "ERROR: File at '%s' declares an interface '%s' "
800d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                        "instead of the expected types common to the package.\n",
8170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        path.c_str(),
8270a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        ifaceName.c_str());
83a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
84a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
85a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            } else if (ifaceName != fqName.name()) {
8670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                fprintf(stderr,
8770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        "ERROR: File at '%s' does not declare interface type "
880d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                        "'%s'.\n",
8970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        path.c_str(),
9070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        fqName.name().c_str());
91a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
92a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
93a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            }
94a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        } else if (fqName.name() != "types") {
9570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber            fprintf(stderr,
9670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    "ERROR: File at '%s' declares types rather than the "
970d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                    "expected interface type '%s'.\n",
9870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    path.c_str(),
9970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    fqName.name().c_str());
100a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
101a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            err = UNKNOWN_ERROR;
102a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        }
103a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
104a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
105a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (err != OK) {
106a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        delete ast;
107a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        ast = NULL;
108a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
109a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        return NULL;
110a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
111a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
11268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    mCache.add(fqName, ast);
1135345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1145345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return ast;
1155345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1165345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
117dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator
118dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const {
1195345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.package().empty());
1205345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.version().empty());
1215345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
122dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Find the right package prefix and path for this FQName.  For
123dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // example, if FQName is "android.hardware.nfc@1.0::INfc", and the
124dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix:root is set to [ "android.hardware:hardware/interfaces",
125dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "vendor.qcom.hardware:vendor/qcom"], then we will identify the
126dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix "android.hardware" and the package root
127dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "hardware/interfaces".
128dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
129dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // TODO: This now returns on the first match.  Throw an error if
130dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // there are multiple hits.
131dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = mPackageRoots.begin();
132dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    for (; it != mPackageRoots.end(); it++) {
133dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        if (fqName.package().find(*it) != std::string::npos) {
134dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber            break;
135dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        }
136dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
137dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    CHECK(it != mPackageRoots.end());
138dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
139dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    return it;
140dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
141dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
142dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const {
143dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
144dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
145dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    return prefix;
146dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
147dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
1485bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const {
1495bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto it = findPackageRoot(fqName);
1505bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
1515bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    return root;
1525bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev}
1535bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev
154dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath(
155dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        const FQName &fqName, bool relative) const {
156dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
157dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
158dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
159dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
160dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
161dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Make sure the prefix ends on a '.' and the root path on a '/'
162dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--prefix.end()) != '.') {
163dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        prefix += '.';
164dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
165dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
166dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--root.end()) != '/') {
167dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        root += '/';
168dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
169dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
170dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix
171dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "android.hardware.", the suffix is "nfc@1.0::IFoo".
172dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    const std::string packageSuffix = fqName.package().substr(prefix.length());
1735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
174881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    std::string packagePath;
175881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    if (!relative) {
176dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        packagePath = root;
177881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    }
1785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t startPos = 0;
1805345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos;
1815345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) {
1825345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append(packageSuffix.substr(startPos, dotPos - startPos));
1835345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append("/");
1845345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        startPos = dotPos + 1;
1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
1875345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_LT(startPos + 1, packageSuffix.length());
1885345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(packageSuffix.substr(startPos));
1895345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
1905345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1915345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_EQ(fqName.version().find('@'), 0u);
1925345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(fqName.version().substr(1));
1935345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
1945345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1955345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return packagePath;
1965345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1975345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
198fd4afabde8fb9bbdd0021addeb9fbb62428f2c17Andreas HuberType *Coordinator::lookupType(const FQName &fqName) const {
1995345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    // Fully qualified.
20068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
2015345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2025345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    std::string topType;
2035345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos = fqName.name().find('.');
2045345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (dotPos == std::string::npos) {
2055345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        topType = fqName.name();
2065345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    } else {
2075345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        topType = fqName.name().substr(0, dotPos);
2085345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2095345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
21068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Assuming {topType} is the name of an interface type, let's see if the
21168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // associated {topType}.hal file was imported.
21268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    FQName ifaceName(fqName.package(), fqName.version(), topType);
21368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    ssize_t index = mCache.indexOfKey(ifaceName);
2145345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
2155345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
2166e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        CHECK(ast != NULL);
2176e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
2185345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        Type *type = ast->lookupTypeInternal(fqName.name());
2195345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2205345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        if (type != NULL) {
221fd4afabde8fb9bbdd0021addeb9fbb62428f2c17Andreas Huber            return type->ref();
2225345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        }
2235345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2245345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
22568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    FQName typesName(fqName.package(), fqName.version(), "types");
22668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    index = mCache.indexOfKey(typesName);
2275345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
2285345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
2296e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        if (ast != NULL) {
2306e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            // ast could be NULL if types.hal didn't exist, which is valid.
2316e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            Type *type = ast->lookupTypeInternal(fqName.name());
2325345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2336e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            if (type != NULL) {
234fd4afabde8fb9bbdd0021addeb9fbb62428f2c17Andreas Huber                return type->ref();
2356e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            }
2365345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        }
2375345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2385345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2395345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return NULL;
2405345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
2415345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
242d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles(
243d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
244d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<std::string> *fileNames) const {
245d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    fileNames->clear();
2466cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
247d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    const std::string packagePath = getPackagePath(package);
248d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
249d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    DIR *dir = opendir(packagePath.c_str());
250d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
251d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (dir == NULL) {
252d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return -errno;
253d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
254d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
255d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    struct dirent *ent;
256d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((ent = readdir(dir)) != NULL) {
257d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (ent->d_type != DT_REG) {
2586cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber            continue;
2596cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber        }
2606cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
261d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix = ".hal";
262d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix_len = std::strlen(suffix);
263d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto d_namelen = strlen(ent->d_name);
264e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
265d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (d_namelen < suffix_len
266d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) {
267d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
268e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        }
269d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
270d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len));
271e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    }
272e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
273d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    closedir(dir);
274d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    dir = NULL;
275d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
276e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    return OK;
277e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber}
278e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
2795bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstatus_t Coordinator::appendPackageInterfacesToSet(
280d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
281d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<FQName> *packageInterfaces) const {
282d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    packageInterfaces->clear();
283d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
284d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::vector<std::string> fileNames;
285d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    status_t err = getPackageInterfaceFiles(package, &fileNames);
286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (err != OK) {
288d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return err;
289d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
290d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
291d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    for (const auto &fileName : fileNames) {
292d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        FQName subFQName(
293d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                package.package() + package.version() + "::" + fileName);
294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (!subFQName.isValid()) {
296d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            LOG(WARNING)
297d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "Whole-package import encountered invalid filename '"
298d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << fileName
299d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "' in package "
300d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << package.package()
301d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << package.version();
302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
304d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
305d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageInterfaces->push_back(subFQName);
307d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
308d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
309d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return OK;
310d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
311d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
312d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const {
313d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::string packageRoot = getPackageRoot(fqName);
314d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
315d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (*(packageRoot.end()--) != '.') {
316d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageRoot += '.';
317d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
318d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
319d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::replace(packageRoot.begin(), packageRoot.end(), '.', '/');
320d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
321d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return packageRoot; // now converted to a path
322d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
323d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
324d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber// static
325d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) {
326d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    static const mode_t kMode = 0755;
327d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
328d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t start = 1;  // Ignore leading '/'
329d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t slashPos;
330d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((slashPos = path.find("/", start)) != std::string::npos) {
331d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::string partial = path.substr(0, slashPos);
332d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
333d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        struct stat st;
334d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (stat(partial.c_str(), &st) < 0) {
335d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (errno != ENOENT) {
336d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
337d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
338d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
339d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            int res = mkdir(partial.c_str(), kMode);
340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (res < 0) {
341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        } else if (!S_ISDIR(st.st_mode)) {
344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            return false;
345d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        start = slashPos + 1;
348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return true;
351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
352d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
3535345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}  // namespace android
3545345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
355