blob: c7cef5ce0a0f3e69f48d2bfca94560ac704cb026 [file] [log] [blame]
Christopher Wiley4427d862015-09-14 11:07:39 -07001/*
2 * Copyright (C) 2015, 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 */
Adam Lesinskiffa16862014-01-23 18:17:42 -080016
17#include "options.h"
18
Christopher Wiley054afbd2015-10-16 17:08:43 -070019#include <cstring>
Christopher Wileya590de82015-09-15 15:46:28 -070020#include <iostream>
Adam Lesinskiffa16862014-01-23 18:17:42 -080021#include <stdio.h>
Adam Lesinskiffa16862014-01-23 18:17:42 -080022
Christopher Wiley4432ccf2015-09-18 18:32:08 -070023#include "logging.h"
24#include "os.h"
25
Christopher Wileya590de82015-09-15 15:46:28 -070026using std::cerr;
27using std::endl;
Christopher Wiley4427d862015-09-14 11:07:39 -070028using std::string;
29using std::unique_ptr;
Christopher Wileyeb1acc12015-09-16 11:25:13 -070030using std::vector;
Christopher Wiley4427d862015-09-14 11:07:39 -070031
32namespace android {
33namespace aidl {
34namespace {
35
Christopher Wiley89eaab52015-09-15 14:46:46 -070036unique_ptr<JavaOptions> java_usage() {
Christopher Wiley4427d862015-09-14 11:07:39 -070037 fprintf(stderr,
38 "usage: aidl OPTIONS INPUT [OUTPUT]\n"
39 " aidl --preprocess OUTPUT INPUT...\n"
40 "\n"
41 "OPTIONS:\n"
42 " -I<DIR> search path for import statements.\n"
43 " -d<FILE> generate dependency file.\n"
44 " -a generate dependency file next to the output file with "
45 "the name based on the input file.\n"
46 " -p<FILE> file created by --preprocess to import.\n"
47 " -o<FOLDER> base output folder for generated files.\n"
48 " -b fail when trying to compile a parcelable.\n"
49 "\n"
50 "INPUT:\n"
51 " An aidl interface file.\n"
52 "\n"
53 "OUTPUT:\n"
54 " The generated interface files.\n"
55 " If omitted and the -o option is not used, the input filename is "
56 "used, with the .aidl extension changed to a .java extension.\n"
57 " If the -o option is used, the generated files will be placed in "
58 "the base output folder, under their package folder\n");
Christopher Wiley89eaab52015-09-15 14:46:46 -070059 return unique_ptr<JavaOptions>(nullptr);
Adam Lesinskiffa16862014-01-23 18:17:42 -080060}
61
Christopher Wiley4427d862015-09-14 11:07:39 -070062} // namespace
Adam Lesinskiffa16862014-01-23 18:17:42 -080063
Christopher Wiley89eaab52015-09-15 14:46:46 -070064unique_ptr<JavaOptions> JavaOptions::Parse(int argc, const char* const* argv) {
65 unique_ptr<JavaOptions> options(new JavaOptions());
Christopher Wiley4427d862015-09-14 11:07:39 -070066 int i = 1;
67
68 if (argc >= 2 && 0 == strcmp(argv[1], "--preprocess")) {
69 if (argc < 4) {
Christopher Wiley89eaab52015-09-15 14:46:46 -070070 return java_usage();
Christopher Wiley4427d862015-09-14 11:07:39 -070071 }
Christopher Wiley8f8cc9b2015-09-14 13:47:40 -070072 options->output_file_name_ = argv[2];
Christopher Wiley4427d862015-09-14 11:07:39 -070073 for (int i = 3; i < argc; i++) {
Christopher Wiley8f8cc9b2015-09-14 13:47:40 -070074 options->files_to_preprocess_.push_back(argv[i]);
Christopher Wiley4427d862015-09-14 11:07:39 -070075 }
76 options->task = PREPROCESS_AIDL;
77 return options;
78 }
79
Christopher Wileyd93c5b72015-09-14 13:21:37 -070080 options->task = COMPILE_AIDL_TO_JAVA;
Christopher Wiley4427d862015-09-14 11:07:39 -070081 // OPTIONS
82 while (i < argc) {
83 const char* s = argv[i];
Christopher Wileyd93c5b72015-09-14 13:21:37 -070084 const size_t len = strlen(s);
85 if (s[0] != '-') {
86 break;
87 }
88 if (len <= 1) {
89 fprintf(stderr, "unknown option (%d): %s\n", i, s);
Christopher Wiley89eaab52015-09-15 14:46:46 -070090 return java_usage();
Christopher Wileyd93c5b72015-09-14 13:21:37 -070091 }
92 // -I<system-import-path>
93 if (s[1] == 'I') {
94 if (len > 2) {
95 options->import_paths_.push_back(s + 2);
Christopher Wiley4427d862015-09-14 11:07:39 -070096 } else {
Christopher Wileyd93c5b72015-09-14 13:21:37 -070097 fprintf(stderr, "-I option (%d) requires a path.\n", i);
Christopher Wiley89eaab52015-09-15 14:46:46 -070098 return java_usage();
Christopher Wiley4427d862015-09-14 11:07:39 -070099 }
Christopher Wileyd93c5b72015-09-14 13:21:37 -0700100 } else if (s[1] == 'd') {
101 if (len > 2) {
102 options->dep_file_name_ = s + 2;
103 } else {
104 fprintf(stderr, "-d option (%d) requires a file.\n", i);
Christopher Wiley89eaab52015-09-15 14:46:46 -0700105 return java_usage();
Christopher Wileyd93c5b72015-09-14 13:21:37 -0700106 }
107 } else if (strcmp(s, "-a") == 0) {
108 options->auto_dep_file_ = true;
109 } else if (s[1] == 'p') {
110 if (len > 2) {
111 options->preprocessed_files_.push_back(s + 2);
112 } else {
113 fprintf(stderr, "-p option (%d) requires a file.\n", i);
Christopher Wiley89eaab52015-09-15 14:46:46 -0700114 return java_usage();
Christopher Wileyd93c5b72015-09-14 13:21:37 -0700115 }
116 } else if (s[1] == 'o') {
117 if (len > 2) {
118 options->output_base_folder_= s + 2;
119 } else {
120 fprintf(stderr, "-o option (%d) requires a path.\n", i);
Christopher Wiley89eaab52015-09-15 14:46:46 -0700121 return java_usage();
Christopher Wileyd93c5b72015-09-14 13:21:37 -0700122 }
123 } else if (strcmp(s, "-b") == 0) {
124 options->fail_on_parcelable_ = true;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800125 } else {
Christopher Wileyd93c5b72015-09-14 13:21:37 -0700126 // s[1] is not known
127 fprintf(stderr, "unknown option (%d): %s\n", i, s);
Christopher Wiley89eaab52015-09-15 14:46:46 -0700128 return java_usage();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800129 }
Christopher Wiley4427d862015-09-14 11:07:39 -0700130 i++;
131 }
Christopher Wiley4427d862015-09-14 11:07:39 -0700132 // INPUT
133 if (i < argc) {
Christopher Wiley8f8cc9b2015-09-14 13:47:40 -0700134 options->input_file_name_ = argv[i];
Christopher Wiley4427d862015-09-14 11:07:39 -0700135 i++;
136 } else {
137 fprintf(stderr, "INPUT required\n");
Christopher Wiley89eaab52015-09-15 14:46:46 -0700138 return java_usage();
Christopher Wiley4427d862015-09-14 11:07:39 -0700139 }
Christopher Wiley4432ccf2015-09-18 18:32:08 -0700140 if (!EndsWith(options->input_file_name_, ".aidl")) {
141 cerr << "Expected .aidl file for input but got "
142 << options->input_file_name_ << endl;
143 return java_usage();
144 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800145
Christopher Wiley4427d862015-09-14 11:07:39 -0700146 // OUTPUT
147 if (i < argc) {
Christopher Wiley8f8cc9b2015-09-14 13:47:40 -0700148 options->output_file_name_ = argv[i];
Christopher Wiley4427d862015-09-14 11:07:39 -0700149 i++;
Christopher Wileyd93c5b72015-09-14 13:21:37 -0700150 } else if (options->output_base_folder_.empty()) {
Christopher Wiley4427d862015-09-14 11:07:39 -0700151 // copy input into output and change the extension from .aidl to .java
Christopher Wiley8f8cc9b2015-09-14 13:47:40 -0700152 options->output_file_name_= options->input_file_name_;
Christopher Wiley4432ccf2015-09-18 18:32:08 -0700153 if (!ReplaceSuffix(".aidl", ".java", &options->output_file_name_)) {
154 // we should never get here since we validated the suffix.
155 LOG(FATAL) << "Internal aidl error.";
Christopher Wiley89eaab52015-09-15 14:46:46 -0700156 return java_usage();
Adam Lesinskiffa16862014-01-23 18:17:42 -0800157 }
Christopher Wiley4427d862015-09-14 11:07:39 -0700158 }
Adam Lesinskiffa16862014-01-23 18:17:42 -0800159
Christopher Wiley4427d862015-09-14 11:07:39 -0700160 // anything remaining?
161 if (i != argc) {
162 fprintf(stderr, "unknown option%s:",
163 (i == argc - 1 ? (const char*)"" : (const char*)"s"));
164 for (; i < argc - 1; i++) {
165 fprintf(stderr, " %s", argv[i]);
166 }
167 fprintf(stderr, "\n");
Christopher Wiley89eaab52015-09-15 14:46:46 -0700168 return java_usage();
Christopher Wiley4427d862015-09-14 11:07:39 -0700169 }
170
171 return options;
Adam Lesinskiffa16862014-01-23 18:17:42 -0800172}
173
Christopher Wileyef4132c2015-11-05 15:47:40 -0800174string JavaOptions::DependencyFilePath() const {
175 if (auto_dep_file_) {
176 return output_file_name_ + ".d";
177 }
178 return dep_file_name_;
179}
180
Christopher Wileya590de82015-09-15 15:46:28 -0700181namespace {
182
183unique_ptr<CppOptions> cpp_usage() {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700184 cerr << "usage: aidl-cpp INPUT_FILE HEADER_DIR OUTPUT_FILE" << endl
Christopher Wileya590de82015-09-15 15:46:28 -0700185 << endl
186 << "OPTIONS:" << endl
187 << " -I<DIR> search path for import statements" << endl
188 << " -d<FILE> generate dependency file" << endl
189 << endl
190 << "INPUT_FILE:" << endl
191 << " an aidl interface file" << endl
Christopher Wiley054afbd2015-10-16 17:08:43 -0700192 << "HEADER_DIR:" << endl
193 << " empty directory to put generated headers" << endl
194 << "OUTPUT_FILE:" << endl
195 << " path to write generated .cpp code" << endl;
Christopher Wileya590de82015-09-15 15:46:28 -0700196 return unique_ptr<CppOptions>(nullptr);
197}
198
199} // namespace
200
Christopher Wileya590de82015-09-15 15:46:28 -0700201unique_ptr<CppOptions> CppOptions::Parse(int argc, const char* const* argv) {
202 unique_ptr<CppOptions> options(new CppOptions());
203 int i = 1;
204
205 // Parse flags, all of which start with '-'
206 for ( ; i < argc; ++i) {
207 const size_t len = strlen(argv[i]);
208 const char *s = argv[i];
209 if (s[0] != '-') {
210 break; // On to the positional arguments.
211 }
212 if (len < 2) {
213 cerr << "Invalid argument '" << s << "'." << endl;
214 return cpp_usage();
215 }
216 const string the_rest = s + 2;
217 if (s[1] == 'I') {
218 options->import_paths_.push_back(the_rest);
219 } else if (s[1] == 'd') {
220 options->dep_file_name_ = the_rest;
221 } else {
222 cerr << "Invalid argument '" << s << "'." << endl;
223 return cpp_usage();
224 }
225 }
226
Christopher Wiley054afbd2015-10-16 17:08:43 -0700227 // There are exactly three positional arguments.
Christopher Wileya590de82015-09-15 15:46:28 -0700228 const int remaining_args = argc - i;
Christopher Wiley054afbd2015-10-16 17:08:43 -0700229 if (remaining_args != 3) {
230 cerr << "Expected 3 positional arguments but got " << remaining_args << "." << endl;
Christopher Wileya590de82015-09-15 15:46:28 -0700231 return cpp_usage();
232 }
Christopher Wiley054afbd2015-10-16 17:08:43 -0700233
Christopher Wileya590de82015-09-15 15:46:28 -0700234 options->input_file_name_ = argv[i];
Christopher Wiley054afbd2015-10-16 17:08:43 -0700235 options->output_header_dir_ = argv[i + 1];
236 options->output_file_name_ = argv[i + 2];
237
Christopher Wiley4432ccf2015-09-18 18:32:08 -0700238 if (!EndsWith(options->input_file_name_, ".aidl")) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700239 cerr << "Expected .aidl file for input but got " << options->input_file_name_ << endl;
Christopher Wiley4432ccf2015-09-18 18:32:08 -0700240 return cpp_usage();
241 }
242
Christopher Wileya590de82015-09-15 15:46:28 -0700243 return options;
244}
245
Christopher Wiley4432ccf2015-09-18 18:32:08 -0700246bool EndsWith(const string& str, const string& suffix) {
247 if (str.length() < suffix.length()) {
248 return false;
249 }
250 return std::equal(str.crbegin(), str.crbegin() + suffix.length(),
251 suffix.crbegin());
252}
253
254bool ReplaceSuffix(const string& old_suffix,
255 const string& new_suffix,
256 string* str) {
257 if (!EndsWith(*str, old_suffix)) return false;
258 str->replace(str->length() - old_suffix.length(),
259 old_suffix.length(),
260 new_suffix);
261 return true;
262}
263
264
265
Christopher Wiley4427d862015-09-14 11:07:39 -0700266} // namespace android
267} // namespace aidl