blob: 21b743fbd4a489d06ad79ebcce16c7643c7037a0 [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 Wileya590de82015-09-15 15:46:28 -0700174namespace {
175
176unique_ptr<CppOptions> cpp_usage() {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700177 cerr << "usage: aidl-cpp INPUT_FILE HEADER_DIR OUTPUT_FILE" << endl
Christopher Wileya590de82015-09-15 15:46:28 -0700178 << endl
179 << "OPTIONS:" << endl
180 << " -I<DIR> search path for import statements" << endl
181 << " -d<FILE> generate dependency file" << endl
182 << endl
183 << "INPUT_FILE:" << endl
184 << " an aidl interface file" << endl
Christopher Wiley054afbd2015-10-16 17:08:43 -0700185 << "HEADER_DIR:" << endl
186 << " empty directory to put generated headers" << endl
187 << "OUTPUT_FILE:" << endl
188 << " path to write generated .cpp code" << endl;
Christopher Wileya590de82015-09-15 15:46:28 -0700189 return unique_ptr<CppOptions>(nullptr);
190}
191
192} // namespace
193
Christopher Wileya590de82015-09-15 15:46:28 -0700194unique_ptr<CppOptions> CppOptions::Parse(int argc, const char* const* argv) {
195 unique_ptr<CppOptions> options(new CppOptions());
196 int i = 1;
197
198 // Parse flags, all of which start with '-'
199 for ( ; i < argc; ++i) {
200 const size_t len = strlen(argv[i]);
201 const char *s = argv[i];
202 if (s[0] != '-') {
203 break; // On to the positional arguments.
204 }
205 if (len < 2) {
206 cerr << "Invalid argument '" << s << "'." << endl;
207 return cpp_usage();
208 }
209 const string the_rest = s + 2;
210 if (s[1] == 'I') {
211 options->import_paths_.push_back(the_rest);
212 } else if (s[1] == 'd') {
213 options->dep_file_name_ = the_rest;
214 } else {
215 cerr << "Invalid argument '" << s << "'." << endl;
216 return cpp_usage();
217 }
218 }
219
Christopher Wiley054afbd2015-10-16 17:08:43 -0700220 // There are exactly three positional arguments.
Christopher Wileya590de82015-09-15 15:46:28 -0700221 const int remaining_args = argc - i;
Christopher Wiley054afbd2015-10-16 17:08:43 -0700222 if (remaining_args != 3) {
223 cerr << "Expected 3 positional arguments but got " << remaining_args << "." << endl;
Christopher Wileya590de82015-09-15 15:46:28 -0700224 return cpp_usage();
225 }
Christopher Wiley054afbd2015-10-16 17:08:43 -0700226
Christopher Wileya590de82015-09-15 15:46:28 -0700227 options->input_file_name_ = argv[i];
Christopher Wiley054afbd2015-10-16 17:08:43 -0700228 options->output_header_dir_ = argv[i + 1];
229 options->output_file_name_ = argv[i + 2];
230
Christopher Wiley4432ccf2015-09-18 18:32:08 -0700231 if (!EndsWith(options->input_file_name_, ".aidl")) {
Christopher Wiley054afbd2015-10-16 17:08:43 -0700232 cerr << "Expected .aidl file for input but got " << options->input_file_name_ << endl;
Christopher Wiley4432ccf2015-09-18 18:32:08 -0700233 return cpp_usage();
234 }
235
Christopher Wileya590de82015-09-15 15:46:28 -0700236 return options;
237}
238
Christopher Wiley4432ccf2015-09-18 18:32:08 -0700239bool EndsWith(const string& str, const string& suffix) {
240 if (str.length() < suffix.length()) {
241 return false;
242 }
243 return std::equal(str.crbegin(), str.crbegin() + suffix.length(),
244 suffix.crbegin());
245}
246
247bool ReplaceSuffix(const string& old_suffix,
248 const string& new_suffix,
249 string* str) {
250 if (!EndsWith(*str, old_suffix)) return false;
251 str->replace(str->length() - old_suffix.length(),
252 old_suffix.length(),
253 new_suffix);
254 return true;
255}
256
257
258
Christopher Wiley4427d862015-09-14 11:07:39 -0700259} // namespace android
260} // namespace aidl