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