blob: 405920210fcb5bda7255a835c9a96cc03a60419c [file] [log] [blame]
Andreas Huberc9410c72016-07-28 12:18:40 -07001#include "AST.h"
Andreas Huber5345ec22016-07-29 13:33:27 -07002#include "Coordinator.h"
Andreas Huber84f89de2016-07-28 15:39:51 -07003#include "FQName.h"
Andreas Huberc9410c72016-07-28 12:18:40 -07004
Andreas Huber68f24592016-07-29 14:53:48 -07005#include <android-base/logging.h>
Andreas Huberc9410c72016-07-28 12:18:40 -07006#include <stdio.h>
Andreas Huberdca261f2016-08-04 13:47:51 -07007#include <string>
Andreas Huberb82318c2016-08-02 14:45:54 -07008#include <unistd.h>
Andreas Huberdca261f2016-08-04 13:47:51 -07009#include <vector>
Andreas Huberc9410c72016-07-28 12:18:40 -070010
11using namespace android;
12
Andreas Huberb82318c2016-08-02 14:45:54 -070013static void usage(const char *me) {
Andreas Huberdca261f2016-08-04 13:47:51 -070014 fprintf(stderr,
15 "usage: %s -o output-path (-r interface-root)+ fqname+\n",
16 me);
17
18 fprintf(stderr, " -o output path\n");
19
20 fprintf(stderr,
21 " -r package:path root "
22 "(e.g., android.hardware:hardware/interfaces)\n");
Andreas Huberb82318c2016-08-02 14:45:54 -070023}
24
25int main(int argc, char **argv) {
26 std::string outputDir;
Andreas Huberdca261f2016-08-04 13:47:51 -070027 std::vector<std::string> packageRootPaths;
28 std::vector<std::string> packageRoots;
Andreas Huberb82318c2016-08-02 14:45:54 -070029
Andreas Huber737080b2016-08-02 15:38:04 -070030 const char *me = argv[0];
31
Andreas Huberb82318c2016-08-02 14:45:54 -070032 int res;
Andreas Huberdca261f2016-08-04 13:47:51 -070033 while ((res = getopt(argc, argv, "ho:r:")) >= 0) {
Andreas Huberb82318c2016-08-02 14:45:54 -070034 switch (res) {
35 case 'o':
36 {
37 outputDir = optarg;
38 break;
39 }
40
Andreas Huberdca261f2016-08-04 13:47:51 -070041 case 'r':
42 {
43 std::string val(optarg);
44 auto index = val.find_first_of(':');
45 CHECK(index != std::string::npos);
46
47 auto package = val.substr(0, index);
48 auto path = val.substr(index + 1);
49 packageRootPaths.push_back(path);
50 packageRoots.push_back(package);
51 break;
52 }
53
Andreas Huberb82318c2016-08-02 14:45:54 -070054 case '?':
55 case 'h':
56 default:
57 {
Andreas Huber737080b2016-08-02 15:38:04 -070058 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -070059 exit(1);
60 break;
61 }
62 }
63 }
64
65 argc -= optind;
66 argv += optind;
67
Andreas Huberdca261f2016-08-04 13:47:51 -070068 if (packageRootPaths.empty()) {
69 // Pick reasonable defaults.
70
71 packageRoots.push_back("android.hardware");
72
73 const char *TOP = getenv("TOP");
74 CHECK(TOP != NULL);
75
76 std::string path = TOP;
77 path.append("/hardware/interfaces");
78
79 packageRootPaths.push_back(path);
80 }
81
Andreas Huber737080b2016-08-02 15:38:04 -070082 // Valid options are now in argv[0] .. argv[argc - 1].
83
Andreas Huberb82318c2016-08-02 14:45:54 -070084 if (outputDir.empty()) {
Andreas Huber737080b2016-08-02 15:38:04 -070085 usage(me);
Andreas Huberb82318c2016-08-02 14:45:54 -070086 exit(1);
87 } else {
88 const size_t len = outputDir.size();
89 if (outputDir[len - 1] != '/') {
90 outputDir += "/";
91 }
92 }
93
Andreas Huberdca261f2016-08-04 13:47:51 -070094 Coordinator coordinator(packageRootPaths, packageRoots);
Andreas Huber5345ec22016-07-29 13:33:27 -070095
Andreas Huber737080b2016-08-02 15:38:04 -070096 for (int i = 0; i < argc; ++i) {
Andreas Huber68f24592016-07-29 14:53:48 -070097 FQName fqName(argv[i]);
98 CHECK(fqName.isValid() && fqName.isFullyQualified());
99
100 AST *ast = coordinator.parse(fqName);
Andreas Huberc9410c72016-07-28 12:18:40 -0700101
Andreas Hubere61e3f72016-08-03 10:22:03 -0700102 if (ast == NULL) {
103 fprintf(stderr,
104 "Could not parse %s. Aborting.\n",
105 fqName.string().c_str());
Andreas Huber881227d2016-08-02 14:20:21 -0700106
Andreas Hubere61e3f72016-08-03 10:22:03 -0700107 exit(1);
108 }
Andreas Hubereb1081f2016-07-28 13:13:24 -0700109 }
Andreas Huberc9410c72016-07-28 12:18:40 -0700110
Andreas Hubere61e3f72016-08-03 10:22:03 -0700111 // Now that we've found the transitive hull of all necessary interfaces
112 // and types to process, go ahead and do the work.
113 status_t err = coordinator.forEachAST(
114 [&](const AST *ast) {
115 return ast->generateCpp(outputDir);
116 });
117
118 return (err == OK) ? 0 : 1;
Andreas Huberc9410c72016-07-28 12:18:40 -0700119}