1f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland/*
2f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * Copyright (C) 2016 The Android Open Source Project
3f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland *
4f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * Licensed under the Apache License, Version 2.0 (the "License");
5f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * you may not use this file except in compliance with the License.
6f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * You may obtain a copy of the License at
7f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland *
8f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland *      http://www.apache.org/licenses/LICENSE-2.0
9f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland *
10f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * Unless required by applicable law or agreed to in writing, software
11f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * distributed under the License is distributed on an "AS IS" BASIS,
12f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * See the License for the specific language governing permissions and
14f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland * limitations under the License.
15f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland */
16f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
17f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include "AST.h"
18f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
19f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include <android-base/logging.h>
20f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include <android-base/macros.h>
21f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include <set>
22f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include <map>
23f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include <stdio.h>
24f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include <string>
25f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include <unistd.h>
26f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland#include <vector>
27f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
28f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Morelandusing namespace android;
29f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
30f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Morelandextern status_t parseFile(android::AST *ast);
31f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
32f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Morelandstatic void usage(const char *me) {
33f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    fprintf(stderr,
342b02118f0cf27fabdb76e01bf60ca75dd1ad905bSteven Moreland            "usage: %s [-g] [-o dir] -p package (-r interface-root)+ (header-filepath)+\n",
35f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            me);
36f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
37cd16ae4797a0ee318ac08026330732e03016956dSteven Moreland    fprintf(stderr, "         -h print this message\n");
38f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    fprintf(stderr, "         -o output path\n");
39f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    fprintf(stderr, "            (example: ~/android/master)\n");
40f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    fprintf(stderr, "         -p package\n");
41f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    fprintf(stderr, "            (example: android.hardware.baz@1.0)\n");
42f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    fprintf(stderr, "         -g (enable open-gl mode) \n");
43f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    fprintf(stderr, "         -r package:path root "
44f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                    "(e.g., android.hardware:hardware/interfaces)\n");
45f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland}
46f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
47f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Morelandstatic void addPackageRootToMap(const std::string &val,
48f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                                std::map<std::string, std::string> &packageRootPaths) {
49f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    auto index = val.find_first_of(':');
50f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    CHECK(index != std::string::npos);
51f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
52f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    auto package = val.substr(0, index);
53f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    auto path = val.substr(index + 1);
54f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
55f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    packageRootPaths[package] = path;
56f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland}
57f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
58f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Morelandstatic bool isPathPrefix(const std::string &prefix, const std::string &base) {
59f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    if (prefix.size() >= base.size()) {
6092a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson        LOG(DEBUG) << "Not long enough";
61f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        return false;
62f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    }
63f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
64f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    if (base[prefix.size()] != '.') {
6592a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson        LOG(DEBUG) << "not full";
66f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        return false;
67f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    }
68f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
69f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    return prefix == base.substr(0, prefix.size());
70f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland}
71f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
72f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Morelandstatic void applyPackageRootPath(
73f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        const std::map<std::string, std::string> &packageRootPaths,
74f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        const std::string &package,
75f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        std::string &outputPath) {
76f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
77f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    auto index = package.find_first_of('@');
78f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    CHECK(index != std::string::npos);
79f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
80f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    auto packagePath = package.substr(0, index);
81f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    auto packageVersion = package.substr(index + 1);
82f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
83f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    for (auto const& pair : packageRootPaths) {
84f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        const std::string& rootPackage = pair.first;
85f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        const std::string& rootPath = pair.second;
86f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
87f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        if (isPathPrefix(rootPackage, packagePath)) {
88f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
89f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            packagePath = packagePath.substr(rootPackage.size() + 1);
90f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            std::replace(packagePath.begin(), packagePath.end(), '.', '/');
91f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            packagePath += '/' + packageVersion;
92f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
93f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            if (outputPath.empty()) {
94f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                outputPath = rootPath;
95f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            }
96f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
97f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            outputPath += '/' + packagePath + '/';
98f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            return;
99f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        }
100f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    }
101f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
102d3a82b5d9a5c1d755bc2e7a02d08d8b8fb1aa8efSteven Moreland    CHECK(!outputPath.empty()) << "No package root path provided for: " << package;
103d3a82b5d9a5c1d755bc2e7a02d08d8b8fb1aa8efSteven Moreland
104d3a82b5d9a5c1d755bc2e7a02d08d8b8fb1aa8efSteven Moreland    outputPath += '/';
105f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland}
106f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
107f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Morelandint main(int argc, char **argv) {
108f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    const char *me = argv[0];
109f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
110f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    std::string outputDir;
111f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    std::string package;
112f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    std::map<std::string, std::string> packageRootPaths;
113f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    bool isOpenGl = false;
11492a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson    bool verbose = false;
115f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
116f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    int res;
11792a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson    while ((res = getopt(argc, argv, "ghvo:p:r:")) >= 0) {
118f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        switch (res) {
119f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            case 'o': {
120f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                outputDir = optarg;
121f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                break;
122f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            }
123f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            case 'p': {
124f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                package = optarg;
125f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                break;
126f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            }
127f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            case 'g': {
128f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                isOpenGl = true;
129f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                break;
130f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            }
13192a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson            case 'v': {
13292a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson                verbose = true;
13392a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson                break;
13492a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson            }
135f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            case 'r':
136f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            {
137f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                addPackageRootToMap(optarg, packageRootPaths);
138f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                break;
139f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            }
140f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            case 'h':
141f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            default:
142f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            {
143f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                usage(me);
144f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                exit(1);
145f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland                break;
146f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            }
147f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        }
148f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    }
149f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
150f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    // if no arguments are provided, show usage instead of specific errors
151f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    if (optind == 1) {
152f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        usage(me);
153f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        exit(0);
154f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    }
155f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
15692a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson    if (verbose) {
15792a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson        SetMinimumLogSeverity(android::base::VERBOSE);
15892a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson    }
15992a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson
160f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    applyPackageRootPath(packageRootPaths, package, outputDir);
161f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
162f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    if (package.empty()) {
163f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        LOG(WARNING) << "You must provide a package.";
164f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        usage(me);
165f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        exit(0);
166f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    }
167f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
168f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    if (optind == argc) {
169f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        LOG(WARNING) << "You must provide a header-filepath.";
170f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        usage(me);
171f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        exit(0);
172f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    }
173f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
174f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    for(int i = optind; i < argc; i++) {
175f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        std::string path = argv[i];
176f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
17792a1fbbb744a279bb43874200cc12dac6ab2326aDiego Wilson        LOG(DEBUG) << "Processing " << path;
178f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
179f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        AST ast(path, outputDir, package, isOpenGl);
180f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
181f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        int res = parseFile(&ast);
182f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
183f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        if (res != 0) {
184f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            LOG(ERROR) << "Could not parse: " << res;
185f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland            exit(1);
186f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        }
187f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
188f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        ast.processContents();
189f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
190f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland        ast.generateCode();
191f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    }
192f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland
193f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland    return 0;
194f1a35f7d73f38e0d30d7a4343e33c3f4777cf87eSteven Moreland}
195