1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
|
/*
* Copyright (C) 2015, 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 "options.h"
#include <cstring>
#include <iostream>
#include <stdio.h>
#include "logging.h"
#include "os.h"
using std::cerr;
using std::endl;
using std::string;
using std::unique_ptr;
using std::vector;
namespace android {
namespace aidl {
namespace {
unique_ptr<JavaOptions> java_usage() {
fprintf(stderr,
"usage: aidl OPTIONS INPUT [OUTPUT]\n"
" aidl --preprocess OUTPUT INPUT...\n"
"\n"
"OPTIONS:\n"
" -I<DIR> search path for import statements.\n"
" -d<FILE> generate dependency file.\n"
" -a generate dependency file next to the output file with "
"the name based on the input file.\n"
" -ninja generate dependency file in a format ninja "
"understands.\n"
" -p<FILE> file created by --preprocess to import.\n"
" -o<FOLDER> base output folder for generated files.\n"
" -b fail when trying to compile a parcelable.\n"
"\n"
"INPUT:\n"
" An aidl interface file.\n"
"\n"
"OUTPUT:\n"
" The generated interface files.\n"
" If omitted and the -o option is not used, the input filename is "
"used, with the .aidl extension changed to a .java extension.\n"
" If the -o option is used, the generated files will be placed in "
"the base output folder, under their package folder\n");
return unique_ptr<JavaOptions>(nullptr);
}
} // namespace
unique_ptr<JavaOptions> JavaOptions::Parse(int argc, const char* const* argv) {
unique_ptr<JavaOptions> options(new JavaOptions());
int i = 1;
if (argc >= 2 && 0 == strcmp(argv[1], "--preprocess")) {
if (argc < 4) {
return java_usage();
}
options->output_file_name_ = argv[2];
for (int i = 3; i < argc; i++) {
options->files_to_preprocess_.push_back(argv[i]);
}
options->task = PREPROCESS_AIDL;
return options;
}
options->task = COMPILE_AIDL_TO_JAVA;
// OPTIONS
while (i < argc) {
const char* s = argv[i];
const size_t len = strlen(s);
if (s[0] != '-') {
break;
}
if (len <= 1) {
fprintf(stderr, "unknown option (%d): %s\n", i, s);
return java_usage();
}
// -I<system-import-path>
if (s[1] == 'I') {
if (len > 2) {
options->import_paths_.push_back(s + 2);
} else {
fprintf(stderr, "-I option (%d) requires a path.\n", i);
return java_usage();
}
} else if (s[1] == 'd') {
if (len > 2) {
options->dep_file_name_ = s + 2;
} else {
fprintf(stderr, "-d option (%d) requires a file.\n", i);
return java_usage();
}
} else if (strcmp(s, "-a") == 0) {
options->auto_dep_file_ = true;
} else if (s[1] == 'p') {
if (len > 2) {
options->preprocessed_files_.push_back(s + 2);
} else {
fprintf(stderr, "-p option (%d) requires a file.\n", i);
return java_usage();
}
} else if (s[1] == 'o') {
if (len > 2) {
options->output_base_folder_= s + 2;
} else {
fprintf(stderr, "-o option (%d) requires a path.\n", i);
return java_usage();
}
} else if (strcmp(s, "-b") == 0) {
options->fail_on_parcelable_ = true;
} else if (strcmp(s, "-ninja") == 0) {
options->dep_file_ninja_ = true;
} else {
// s[1] is not known
fprintf(stderr, "unknown option (%d): %s\n", i, s);
return java_usage();
}
i++;
}
// INPUT
if (i < argc) {
options->input_file_name_ = argv[i];
i++;
} else {
fprintf(stderr, "INPUT required\n");
return java_usage();
}
if (!EndsWith(options->input_file_name_, ".aidl")) {
cerr << "Expected .aidl file for input but got "
<< options->input_file_name_ << endl;
return java_usage();
}
// OUTPUT
if (i < argc) {
options->output_file_name_ = argv[i];
i++;
} else if (options->output_base_folder_.empty()) {
// copy input into output and change the extension from .aidl to .java
options->output_file_name_= options->input_file_name_;
if (!ReplaceSuffix(".aidl", ".java", &options->output_file_name_)) {
// we should never get here since we validated the suffix.
LOG(FATAL) << "Internal aidl error.";
return java_usage();
}
}
// anything remaining?
if (i != argc) {
fprintf(stderr, "unknown option%s:",
(i == argc - 1 ? (const char*)"" : (const char*)"s"));
for (; i < argc - 1; i++) {
fprintf(stderr, " %s", argv[i]);
}
fprintf(stderr, "\n");
return java_usage();
}
return options;
}
string JavaOptions::DependencyFilePath() const {
if (auto_dep_file_) {
return output_file_name_ + ".d";
}
return dep_file_name_;
}
namespace {
unique_ptr<CppOptions> cpp_usage() {
cerr << "usage: aidl-cpp INPUT_FILE HEADER_DIR OUTPUT_FILE" << endl
<< endl
<< "OPTIONS:" << endl
<< " -I<DIR> search path for import statements" << endl
<< " -d<FILE> generate dependency file" << endl
<< " -ninja generate dependency file in a format ninja "
"understands" << endl
<< endl
<< "INPUT_FILE:" << endl
<< " an aidl interface file" << endl
<< "HEADER_DIR:" << endl
<< " empty directory to put generated headers" << endl
<< "OUTPUT_FILE:" << endl
<< " path to write generated .cpp code" << endl;
return unique_ptr<CppOptions>(nullptr);
}
} // namespace
unique_ptr<CppOptions> CppOptions::Parse(int argc, const char* const* argv) {
unique_ptr<CppOptions> options(new CppOptions());
int i = 1;
// Parse flags, all of which start with '-'
for ( ; i < argc; ++i) {
const size_t len = strlen(argv[i]);
const char *s = argv[i];
if (s[0] != '-') {
break; // On to the positional arguments.
}
if (len < 2) {
cerr << "Invalid argument '" << s << "'." << endl;
return cpp_usage();
}
const string the_rest = s + 2;
if (s[1] == 'I') {
options->import_paths_.push_back(the_rest);
} else if (s[1] == 'd') {
options->dep_file_name_ = the_rest;
} else if (strcmp(s, "-ninja") == 0) {
options->dep_file_ninja_ = true;
} else {
cerr << "Invalid argument '" << s << "'." << endl;
return cpp_usage();
}
}
// There are exactly three positional arguments.
const int remaining_args = argc - i;
if (remaining_args != 3) {
cerr << "Expected 3 positional arguments but got " << remaining_args << "." << endl;
return cpp_usage();
}
options->input_file_name_ = argv[i];
options->output_header_dir_ = argv[i + 1];
options->output_file_name_ = argv[i + 2];
if (!EndsWith(options->input_file_name_, ".aidl")) {
cerr << "Expected .aidl file for input but got " << options->input_file_name_ << endl;
return cpp_usage();
}
return options;
}
bool EndsWith(const string& str, const string& suffix) {
if (str.length() < suffix.length()) {
return false;
}
return std::equal(str.crbegin(), str.crbegin() + suffix.length(),
suffix.crbegin());
}
bool ReplaceSuffix(const string& old_suffix,
const string& new_suffix,
string* str) {
if (!EndsWith(*str, old_suffix)) return false;
str->replace(str->length() - old_suffix.length(),
old_suffix.length(),
new_suffix);
return true;
}
} // namespace android
} // namespace aidl
|