1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdio.h>
6
7 #include <map>
8 #include <numeric>
9 #include <string>
10
11 #include "abigen_generator.h"
12 #include "syscall_parser.h"
13 #include "types.h"
14
15 using std::string;
16
17 constexpr Dispatch<AbigenGenerator> abigen_table[] = {
18 // comments start with '#' and terminate at the end of line. this also handles #! reqs.
19 {"#", nullptr, process_comment},
20 // sycalls start with 'syscall' and terminate with ';'.
21 {"syscall", ";", process_syscall},
22 // table terminator.
23 {nullptr, nullptr, nullptr}};
24
25 // =================================== driver ====================================================
26
main(int argc,char * argv[])27 int main(int argc, char* argv[]) {
28 string output_prefix = "generated";
29 bool verbose = false;
30 bool generate_all = false;
31 std::map<string, string> type_to_filename;
32
33 argc--;
34 argv++;
35 while (argc > 0) {
36 const string command(argv[0]);
37 if (command[0] != '-')
38 break;
39 else if (get_type_to_generator().find(command.substr(1)) != get_type_to_generator().end()) {
40 string type = command.substr(1);
41 type_to_filename[type] = string(argv[1]);
42 argc--;
43 argv++;
44 } else if (command == "-a") {
45 generate_all = true;
46 } else if (command == "-v") {
47 verbose = true;
48 } else if (command == "-o") {
49 if (argc < 2) {
50 fprintf(stderr, "no output prefix given\n");
51 return -1;
52 }
53 output_prefix.assign(argv[1]);
54 argc--;
55 argv++;
56 } else if (command == "-h") {
57 fprintf(stderr, "usage: abigen [-a] [-v] [-o output_prefix] "
58 "[-<type> filename] file1 ... fileN\n");
59 const string delimiter = ", ";
60 const string valid_types =
61 std::accumulate(
62 get_type_to_default_suffix().begin(),
63 get_type_to_default_suffix().end(), std::string(),
64 [delimiter](const std::string& s,
65 const std::pair<const std::string, std::string>& p) {
66 return s + (s.empty() ? std::string() : delimiter) + p.first;
67 });
68 fprintf(stderr, "\n Valid <type>s: %s\n", valid_types.c_str());
69 return 0;
70 } else {
71 fprintf(stderr, "unknown option: %s\n", command.c_str());
72 return -1;
73 }
74 argc--;
75 argv++;
76 }
77 if (argc < 1) {
78 fprintf(stderr, "no syscall-spec input given\n");
79 return -1;
80 }
81
82 // Use defaults for anything not specified.
83 if (generate_all) {
84 for (auto& entry : get_type_to_default_suffix()) {
85 if (type_to_filename.find(entry.first) == type_to_filename.end()) {
86 type_to_filename[entry.first] = output_prefix + entry.second;
87 }
88 }
89 }
90
91 AbigenGenerator generator(verbose);
92
93 for (int ix = 0; ix < argc; ix++) {
94 if (!run_parser(&generator, abigen_table, argv[ix], verbose))
95 return 1;
96 }
97 return generator.Generate(type_to_filename) ? 0 : 1;
98 }
99