1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <iostream>
8 #include "pio_assembler.h"
9 
10 #define DEFAULT_OUTPUT_FORMAT "c-sdk"
11 
usage()12 void usage() {
13     std::cerr << "usage: pioasm <options> <input> (<output>)\n\n";
14     std::cerr << "Assemble file of PIO program(s) for use in applications.\n";
15     std::cerr << "   <input>             the input filename\n";
16     std::cerr << "   <output>            the output filename (or filename prefix if the output format produces multiple outputs).\n";
17     std::cerr << "                       if not specified, a single output will be written to stdout\n";
18     std::cerr << "\n";
19     std::cerr << "options:\n";
20     std::cerr << "  -o <output_format>   select output_format (default '" << DEFAULT_OUTPUT_FORMAT << "'); available options are:\n";
21     for(const auto& f : output_format::all()) {
22         std::cerr << "                           " << f->name << std::endl;
23         std::cerr << "                               " << f->get_description() << std::endl;
24     }
25     std::cerr << "  -p <output_param>    add a parameter to be passed to the output format generator" << std::endl;
26     std::cerr << "  -v <version>         specify the default PIO version (0 or 1)" << std::endl;
27     std::cerr << "  -?, --help           print this help and exit\n";
28 }
29 
main(int argc,char * argv[])30 int main(int argc, char *argv[]) {
31     int res = 0;
32     pio_assembler pioasm;
33     std::string format(DEFAULT_OUTPUT_FORMAT);
34     const char *input = nullptr;
35     const char *output = nullptr;
36     std::vector<std::string> options;
37     int i = 1;
38     for (; !res && i < argc; i++) {
39         if (argv[i][0] != '-') break;
40         if (argv[i] == std::string("-o")) {
41             if (++i < argc) {
42                 format = argv[i];
43             } else {
44                 std::cerr << "error: -o requires format value" << std::endl;
45                 res = 1;
46             }
47         } else if (argv[i] == std::string("-p")) {
48             if (++i < argc) {
49                 options.emplace_back(argv[i]);
50             } else {
51                 std::cerr << "error: -p requires parameter value" << std::endl;
52                 res = 1;
53             }
54         } else if (argv[i] == std::string("-v")) {
55             if (++i < argc) {
56                 if (argv[i] == std::string("0")) pioasm.default_pio_version = 0;
57                 else if (argv[i] == std::string("1")) pioasm.default_pio_version = 1;
58                 else {
59                     std::cerr << "error: unsupported PIO version '" <<  argv[i] << "'" << std::endl;
60                     res = 1;
61                 }
62             } else {
63                 std::cerr << "error: -v requires version number" << std::endl;
64                 res = 1;
65             }
66         } else if (argv[i] == std::string("-?") || argv[i] == std::string("--help")) {
67             usage();
68             return 1;
69         } else {
70             std::cerr << "error: unknown option " << argv[i] << std::endl;
71             res = 1;
72         }
73     }
74     if (!res) {
75         if (i != argc) {
76             input = argv[i++];
77         } else {
78             std::cerr << "error: expected input filename\n";
79             res = 1;
80         }
81     }
82     if (!res) {
83         if (i != argc) {
84             output = argv[i++];
85         } else {
86             output = "-";
87         }
88     }
89     if (!res && i != argc) {
90         std::cerr << "unexpected command line argument " << argv[i] << std::endl;
91         res = 1;
92     }
93     std::shared_ptr<output_format> oformat;
94     if (!res) {
95         const auto& e = std::find_if(output_format::all().begin(), output_format::all().end(),
96                                      [&](const std::shared_ptr<output_format> &f) {
97                                          return f->name == format;
98                                      });
99         if (e == output_format::all().end()) {
100             std::cerr << "error: unknown output format '" << format << "'" << std::endl;
101             res = 1;
102         } else {
103             oformat = *e;
104         }
105     }
106     if (res) {
107         std::cerr << std::endl;
108         usage();
109     } else {
110         res = pioasm.generate(oformat, input, output, options);
111     }
112     return res;
113 }