You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
5.1 KiB
194 lines
5.1 KiB
/* |
|
* Copyright (C) 2016 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#include "AST.h" |
|
|
|
#include <android-base/logging.h> |
|
#include <android-base/macros.h> |
|
#include <set> |
|
#include <map> |
|
#include <stdio.h> |
|
#include <string> |
|
#include <unistd.h> |
|
#include <vector> |
|
|
|
using namespace android; |
|
|
|
extern status_t parseFile(android::AST *ast); |
|
|
|
static void usage(const char *me) { |
|
fprintf(stderr, |
|
"usage: %s [-g] [-o dir] -p package (-r interface-root)+ (header-filepath)+\n", |
|
me); |
|
|
|
fprintf(stderr, " -h print this message\n"); |
|
fprintf(stderr, " -o output path\n"); |
|
fprintf(stderr, " (example: ~/android/master)\n"); |
|
fprintf(stderr, " -p package\n"); |
|
fprintf(stderr, " (example: android.hardware.baz@1.0)\n"); |
|
fprintf(stderr, " -g (enable open-gl mode) \n"); |
|
fprintf(stderr, " -r package:path root " |
|
"(e.g., android.hardware:hardware/interfaces)\n"); |
|
} |
|
|
|
static void addPackageRootToMap(const std::string &val, |
|
std::map<std::string, std::string> &packageRootPaths) { |
|
auto index = val.find_first_of(':'); |
|
CHECK(index != std::string::npos); |
|
|
|
auto package = val.substr(0, index); |
|
auto path = val.substr(index + 1); |
|
|
|
packageRootPaths[package] = path; |
|
} |
|
|
|
static bool isPathPrefix(const std::string &prefix, const std::string &base) { |
|
if (prefix.size() >= base.size()) { |
|
LOG(DEBUG) << "Not long enough"; |
|
return false; |
|
} |
|
|
|
if (base[prefix.size()] != '.') { |
|
LOG(DEBUG) << "not full"; |
|
return false; |
|
} |
|
|
|
return prefix == base.substr(0, prefix.size()); |
|
} |
|
|
|
static void applyPackageRootPath( |
|
const std::map<std::string, std::string> &packageRootPaths, |
|
const std::string &package, |
|
std::string &outputPath) { |
|
|
|
auto index = package.find_first_of('@'); |
|
CHECK(index != std::string::npos); |
|
|
|
auto packagePath = package.substr(0, index); |
|
auto packageVersion = package.substr(index + 1); |
|
|
|
for (auto const& pair : packageRootPaths) { |
|
const std::string& rootPackage = pair.first; |
|
const std::string& rootPath = pair.second; |
|
|
|
if (isPathPrefix(rootPackage, packagePath)) { |
|
|
|
packagePath = packagePath.substr(rootPackage.size() + 1); |
|
std::replace(packagePath.begin(), packagePath.end(), '.', '/'); |
|
packagePath += '/' + packageVersion; |
|
|
|
if (outputPath.empty()) { |
|
outputPath = rootPath; |
|
} |
|
|
|
outputPath += '/' + packagePath + '/'; |
|
return; |
|
} |
|
} |
|
|
|
CHECK(!outputPath.empty()) << "No package root path provided for: " << package; |
|
|
|
outputPath += '/'; |
|
} |
|
|
|
int main(int argc, char **argv) { |
|
const char *me = argv[0]; |
|
|
|
std::string outputDir; |
|
std::string package; |
|
std::map<std::string, std::string> packageRootPaths; |
|
bool isOpenGl = false; |
|
bool verbose = false; |
|
|
|
int res; |
|
while ((res = getopt(argc, argv, "ghvo:p:r:")) >= 0) { |
|
switch (res) { |
|
case 'o': { |
|
outputDir = optarg; |
|
break; |
|
} |
|
case 'p': { |
|
package = optarg; |
|
break; |
|
} |
|
case 'g': { |
|
isOpenGl = true; |
|
break; |
|
} |
|
case 'v': { |
|
verbose = true; |
|
break; |
|
} |
|
case 'r': |
|
{ |
|
addPackageRootToMap(optarg, packageRootPaths); |
|
break; |
|
} |
|
case 'h': |
|
default: |
|
{ |
|
usage(me); |
|
exit(1); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
// if no arguments are provided, show usage instead of specific errors |
|
if (optind == 1) { |
|
usage(me); |
|
exit(0); |
|
} |
|
|
|
if (verbose) { |
|
SetMinimumLogSeverity(android::base::VERBOSE); |
|
} |
|
|
|
applyPackageRootPath(packageRootPaths, package, outputDir); |
|
|
|
if (package.empty()) { |
|
LOG(WARNING) << "You must provide a package."; |
|
usage(me); |
|
exit(0); |
|
} |
|
|
|
if (optind == argc) { |
|
LOG(WARNING) << "You must provide a header-filepath."; |
|
usage(me); |
|
exit(0); |
|
} |
|
|
|
for(int i = optind; i < argc; i++) { |
|
std::string path = argv[i]; |
|
|
|
LOG(DEBUG) << "Processing " << path; |
|
|
|
AST ast(path, outputDir, package, isOpenGl); |
|
|
|
int res = parseFile(&ast); |
|
|
|
if (res != 0) { |
|
LOG(ERROR) << "Could not parse: " << res; |
|
exit(1); |
|
} |
|
|
|
ast.processContents(); |
|
|
|
ast.generateCode(); |
|
} |
|
|
|
return 0; |
|
}
|
|
|