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