1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _OUTPUT_FORMAT_H
8 #define _OUTPUT_FORMAT_H
9 
10 #include <vector>
11 #include <map>
12 #include <string>
13 #include <memory>
14 
15 typedef unsigned int uint;
16 
17 // can't use optional because we want to support older compilers
18 template<typename T>
19 struct simple_optional {
20     T value;
21     T default_value;
22     bool specified;
23 
simple_optionalsimple_optional24     simple_optional() : default_value(), specified(false) {}
25 
simple_optionalsimple_optional26     simple_optional(const T &value) : value(value), specified(true) {}
27 
28     simple_optional<T> &operator=(const T &v) {
29         value = v;
30         specified = true;
31         return *this;
32     }
33 
34     operator bool() = delete; // confusing
getsimple_optional35     const T &get() const { return specified ? value : default_value; }
36 
is_specifiedsimple_optional37     bool is_specified() const { return specified; }
38 
with_defaultsimple_optional39     static simple_optional<T> with_default(const T &default_value) {
40         simple_optional<T> rc;
41         rc.default_value = default_value;
42         return rc;
43     }
44 };
45 
46 typedef simple_optional<int> optional_int;
47 typedef simple_optional<bool> optional_bool;
48 
49 struct compiled_source {
50     struct symbol {
51         std::string name;
52         int value;
53         bool is_label;
54 
symbolcompiled_source::symbol55         symbol(std::string name, int value, bool is_label) : name(std::move(name)), value(value), is_label(is_label) {}
56     };
57 
58     struct program {
59         std::string name;
60         optional_int origin = optional_int::with_default(-1);
61         optional_int sideset_bits_including_opt;
62         bool sideset_opt = false;
63         bool sideset_pindirs = false;
64         int wrap;
65         int wrap_target;
66         std::vector<uint> instructions;
67         std::vector<symbol> symbols; // public only
68         std::map<std::string, std::vector<std::string>> code_blocks;
69         std::map<std::string, std::vector<std::pair<std::string,std::string>>> lang_opts;
70 
71         // todo can't have wrap at -1
programcompiled_source::program72         program(std::string name) : name(std::move(name)) {}
73     };
74 
75     std::vector<symbol> global_symbols; // public only
76     std::vector<program> programs;
77 };
78 
79 struct output_format {
80     static std::string default_name;
81 
82     std::string name;
83 
addoutput_format84     static void add(output_format *lang) {
85         all().push_back(std::shared_ptr<output_format>(lang));
86     }
87 
88     virtual int output(std::string destination, std::vector<std::string> output_options,
89                        const compiled_source &source) = 0;
90 
91     virtual std::string get_description() = 0;
92 
93     FILE *open_single_output(std::string destination);
94     virtual ~output_format() = default;
95 
alloutput_format96     static std::vector<std::shared_ptr<output_format>>& all() {
97         static std::vector<std::shared_ptr<output_format>> output_formats;
98         return output_formats;
99     }
100 protected:
output_formatoutput_format101     output_format(std::string name) : name(std::move(name)) {}
102 };
103 
104 #endif