Coordinator.cpp revision e61e3f7b138a992047a60c4b8c27f1c752ed57ba
15345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "Coordinator.h"
25345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
35345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "AST.h"
45345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "RefType.h"
55345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
65345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include <android-base/logging.h>
75345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huberextern android::status_t parseFile(android::AST *ast, const char *path);
95345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
105345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Hubernamespace android {
115345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
12dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas HuberCoordinator::Coordinator(const std::string &interfacesPath)
13dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber    : mInterfacesPath(interfacesPath) {
14dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber}
15dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber
165345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas HuberCoordinator::~Coordinator() {}
175345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas HuberAST *Coordinator::parse(const FQName &fqName) {
1968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
2068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
216e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber    // LOG(INFO) << "parsing " << fqName.string();
226e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
2368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    ssize_t index = mCache.indexOfKey(fqName);
245345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
255345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
265345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
275345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        return ast;
285345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
295345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
3068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Add this to the cache immediately, so we can discover circular imports.
3168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    mCache.add(fqName, NULL);
3268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
33dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber    const std::string packagePath = getPackagePath(fqName);
3468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
3568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (fqName.name() != "types") {
3668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // Any interface file implicitly imports its package's types.hal.
3768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        FQName typesName(fqName.package(), fqName.version(), "types");
3868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        (void)parse(typesName);
3968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
4068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // fall through.
4168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
4268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
4368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    std::string path = packagePath;
4468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(fqName.name());
4568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(".hal");
465345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
475345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    AST *ast = new AST(this);
4868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    status_t err = parseFile(ast, path.c_str());
4968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
5068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (err != OK) {
516e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        // LOG(ERROR) << "parsing '" << path << "' FAILED.";
526e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
5368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        delete ast;
5468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        ast = NULL;
555345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
5668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        return NULL;
5768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
5868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
59a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (ast->package().package() != fqName.package()
60a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            || ast->package().version() != fqName.version()) {
61a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        LOG(ERROR)
62a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            << "File at '" << path << "' does not match expected package "
63a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            << "and/or version.";
64a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
65a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        err = UNKNOWN_ERROR;
66a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    } else {
67a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        std::string ifaceName;
68a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        if (ast->isInterface(&ifaceName)) {
69a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            if (fqName.name() == "types") {
70a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                LOG(ERROR)
71a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << "File at '" << path << "' declares an interface '"
72a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << ifaceName
73a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << "' instead of the expected types common to the package.";
74a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
75a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
76a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            } else if (ifaceName != fqName.name()) {
77a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                LOG(ERROR)
78a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << "File at '" << path << "' does not declare interface type '"
79a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << fqName.name()
80a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << "'.";
81a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
82a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
83a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            }
84a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        } else if (fqName.name() != "types") {
85a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            LOG(ERROR)
86a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                << "File at '" << path << "' declares types rather than the "
87a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                << "expected interface type '" << fqName.name() << "'.";
88a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
89a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            err = UNKNOWN_ERROR;
90a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        }
91a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
92a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
93a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (err != OK) {
94a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        delete ast;
95a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        ast = NULL;
96a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
97a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        return NULL;
98a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
99a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
10068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    mCache.add(fqName, ast);
1015345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1025345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return ast;
1035345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1045345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
105881227d860c59471eee31d39946e96ce2daa35d6Andreas Huberstd::string Coordinator::getPackagePath(
106881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber        const FQName &fqName, bool relative) const {
1075345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.package().empty());
1085345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.version().empty());
1095345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    const char *const kPrefix = "android.hardware.";
1105345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_EQ(fqName.package().find(kPrefix), 0u);
1115345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1125345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    const std::string packageSuffix = fqName.package().substr(strlen(kPrefix));
1135345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
114881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    std::string packagePath;
115881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    if (!relative) {
116881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber        packagePath = mInterfacesPath;
117881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    }
1185345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1195345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t startPos = 0;
1205345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos;
1215345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) {
1225345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append(packageSuffix.substr(startPos, dotPos - startPos));
1235345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append("/");
1245345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1255345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        startPos = dotPos + 1;
1265345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
1275345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_LT(startPos + 1, packageSuffix.length());
1285345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(packageSuffix.substr(startPos));
1295345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
1305345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1315345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_EQ(fqName.version().find('@'), 0u);
1325345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(fqName.version().substr(1));
1335345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
1345345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1355345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return packagePath;
1365345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1375345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1380e00de41d11a83ce3becb0dbd20b799acceb19a7Andreas HuberRefType *Coordinator::lookupType(const FQName &fqName) const {
1395345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    // Fully qualified.
14068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
1415345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1425345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    std::string topType;
1435345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos = fqName.name().find('.');
1445345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (dotPos == std::string::npos) {
1455345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        topType = fqName.name();
1465345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    } else {
1475345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        topType = fqName.name().substr(0, dotPos);
1485345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
1495345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
15068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Assuming {topType} is the name of an interface type, let's see if the
15168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // associated {topType}.hal file was imported.
15268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    FQName ifaceName(fqName.package(), fqName.version(), topType);
15368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    ssize_t index = mCache.indexOfKey(ifaceName);
1545345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
1555345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
1566e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        CHECK(ast != NULL);
1576e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
1585345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        Type *type = ast->lookupTypeInternal(fqName.name());
1595345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1605345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        if (type != NULL) {
161867fcb63af8c3ac96ed1b3f3950525aa70393bdfAndreas Huber            return new RefType(type);
1625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        }
1635345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
1645345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
16568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    FQName typesName(fqName.package(), fqName.version(), "types");
16668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    index = mCache.indexOfKey(typesName);
1675345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
1685345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
1696e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        if (ast != NULL) {
1706e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            // ast could be NULL if types.hal didn't exist, which is valid.
1716e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            Type *type = ast->lookupTypeInternal(fqName.name());
1725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1736e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            if (type != NULL) {
174867fcb63af8c3ac96ed1b3f3950525aa70393bdfAndreas Huber                return new RefType(type);
1756e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            }
1765345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        }
1775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
1785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return NULL;
1805345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1815345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
182e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huberstatus_t Coordinator::forEachAST(for_each_cb cb) const {
183e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    for (size_t i = 0; i < mCache.size(); ++i) {
184e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        status_t err = cb(mCache.valueAt(i));
185e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
186e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        if (err != OK) {
187e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber            return err;
188e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        }
189e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    }
190e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
191e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    return OK;
192e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber}
193e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
1945345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}  // namespace android
1955345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
196