1 /*
2  * Copyright 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 <dirent.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 
23 #include <iostream>
24 
25 #include <android-base/logging.h>
26 #include "VtsCompilerUtils.h"
27 #include "code_gen/CodeGenBase.h"
28 
29 using namespace std;
30 
31 // To generate both header and source files,
32 //   Usage: vtsc -mDRIVER | -mPROFILER <.vts input file path> \
33 //          <header output dir> <C/C++ source output file path>
34 // To generate only a header file,
35 //   Usage: vtsc -mDRIVER | -mPROFILER -tHEADER -b<base path> \
36 //          <.vts input file or dir path> <header output file or dir path>
37 // To generate only a source file,
38 //   Usage: vtsc -mDRIVER | -mPROFILER -tSOURCE -b<base path> \
39 //          <.vts input file or dir path> \
40 //          <C/C++ source output file or dir path>
41 // where <base path> is a base path of where .vts input file or dir is
42 // stored but should be excluded when computing the package path of generated
43 // source or header output file(s).
44 
main(int argc,char * argv[])45 int main(int argc, char* argv[]) {
46 #ifdef VTS_DEBUG
47   cout << "Android VTS Compiler (AVTSC)" << endl;
48 #endif
49   int opt_count = 0;
50   android::vts::VtsCompileMode mode = android::vts::kDriver;
51   android::vts::VtsCompileFileType type = android::vts::VtsCompileFileType::kBoth;
52   string vts_base_dir;
53   for (int i = 0; i < argc; i++) {
54 #ifdef VTS_DEBUG
55     cout << "- args[" << i << "] " << argv[i] << endl;
56 #endif
57     if (argv[i] && strlen(argv[i]) > 1 && argv[i][0] == '-') {
58       opt_count++;
59       if (argv[i][1] == 'm') {
60         if (!strcmp(&argv[i][2], "PROFILER")) {
61           mode = android::vts::kProfiler;
62 #ifdef VTS_DEBUG
63           cout << "- mode: PROFILER" << endl;
64 #endif
65         } else if (!strcmp(&argv[i][2], "FUZZER")) {
66           mode = android::vts::kFuzzer;
67 #ifdef VTS_DEBUG
68           cout << "- mode: FUZZER" << endl;
69 #endif
70         }
71       }
72       if (argv[i][1] == 't') {
73         if (!strcmp(&argv[i][2], "HEADER")) {
74           type = android::vts::kHeader;
75 #ifdef VTS_DEBUG
76           cout << "- type: HEADER" << endl;
77 #endif
78         } else if (!strcmp(&argv[i][2], "SOURCE")) {
79           type = android::vts::kSource;
80 #ifdef VTS_DEBUG
81           cout << "- type: SOURCE" << endl;
82 #endif
83         }
84       }
85       if (argv[i][1] == 'b') {
86         vts_base_dir = &argv[i][2];
87 #ifdef VTS_DEBUG
88         cout << "- VTS base dir: " << vts_base_dir << endl;
89 #endif
90       }
91     }
92   }
93   if (argc < 5) {
94     cerr << "argc " << argc << " < 5" << endl;
95     return -1;
96   }
97   switch (type) {
98     case android::vts::kBoth:
99       android::vts::Translate(
100           mode, argv[opt_count + 1], argv[opt_count + 2], argv[opt_count + 3]);
101       break;
102     case android::vts::kHeader:
103     case android::vts::kSource: {
104       struct stat s;
105       bool is_dir = false;
106       if (vts_base_dir.length() > 0) {
107         if (chdir(vts_base_dir.c_str())) {
108           cerr << __func__ << " can't chdir to " << vts_base_dir << endl;
109           exit(-1);
110         }
111       }
112       if (stat(argv[opt_count + 1], &s) == 0) {
113         if (s.st_mode & S_IFDIR) {
114           is_dir = true;
115         }
116       }
117       if (!is_dir) {
118         android::vts::TranslateToFile(
119             mode, argv[opt_count + 1], argv[opt_count + 2], type);
120       } else {
121         DIR* input_dir;
122         struct dirent* ent;
123         if ((input_dir = opendir(argv[opt_count + 1])) != NULL) {
124           // argv[opt_count + 2] should be a directory. if that dir does not exist,
125           // that dir is created as part of the translation operation.
126           while ((ent = readdir(input_dir)) != NULL) {
127             if (!strncmp(&ent->d_name[strlen(ent->d_name)-4], ".vts", 4)) {
128               string src_file = android::vts::RemoveBaseDir(
129                   android::vts::PathJoin(
130                       argv[opt_count + 1], ent->d_name), vts_base_dir);
131               string dst_file = android::vts::RemoveBaseDir(
132                   android::vts::PathJoin(
133                       argv[opt_count + 2], ent->d_name), vts_base_dir);
134               if (type == android::vts::kHeader) {
135                 dst_file = android::vts::PathJoin(dst_file.c_str(), ".h");
136               } else {
137                 dst_file = android::vts::PathJoin(dst_file.c_str(), ".cpp");
138               }
139 #ifdef VTS_DEBUG
140               cout << ent->d_name << endl;
141               cout << "<- " << src_file.c_str() << endl;
142               cout << "-> " << dst_file.c_str() << endl;
143 #endif
144               android::vts::TranslateToFile(
145                   mode, src_file.c_str(), dst_file.c_str(), type);
146             }
147           }
148           closedir(input_dir);
149         } else {
150           cerr << __func__ << " can't open the given input dir, "
151                << argv[opt_count + 1] << "." << endl;
152           exit(-1);
153         }
154       }
155       break;
156     }
157   }
158   return 0;
159 }
160