1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <algorithm>
#include <iostream>
#include "output_format.h"
#include "pio_disassembler.h"
struct json_output : public output_format {
struct factory {
factory() {
output_format::add(new json_output());
}
};
json_output() : output_format("json") {}
std::string get_description() override {
return "Machine-formatted output for integrating with external tools";
}
void output_symbols(FILE *out, bool output_labels, std::string prefix, const std::vector<compiled_source::symbol> &symbols) {
fprintf(out, "%s\"publicSymbols\": {\n", prefix.c_str());
bool first = true;
for (const auto &s : symbols) {
if (!s.is_label) {
// output trailing comma if necessary
if (!first) {
fprintf(out, ",\n");
} else {
first = false;
}
fprintf(out, "%s\t\"%s\": %d", prefix.c_str(), s.name.c_str(), s.value);
}
}
if (!first)
fprintf(out, "\n");
fprintf(out, "%s},\n", prefix.c_str());
if (!output_labels)
return;
fprintf(out, "%s\"publicLabels\": {\n", prefix.c_str());
first = true;
for (const auto &s : symbols) {
if (s.is_label) {
// output trailing comma if necessary
if (!first) {
fprintf(out, ",\n");
} else {
first = false;
}
fprintf(out, "%s\t\"%s\": %d", prefix.c_str(), s.name.c_str(), s.value);
}
}
if (!first)
fprintf(out, "\n");
fprintf(out, "%s},\n", prefix.c_str());
}
int output(std::string destination, std::vector<std::string> output_options,
const compiled_source &source) override {
for (const auto &program : source.programs) {
for(const auto &p : program.lang_opts) {
if (p.first.size() >= name.size() && p.first.compare(0, name.size(), name) == 0) {
std::cerr << "warning: " << name << " does not support output options; " << p.first << " lang_opt ignored.\n";
}
}
}
FILE *out = open_single_output(destination);
if (!out) return 1;
fprintf(out, "{\n");
bool first = true;
output_symbols(out, false, "\t", source.global_symbols);
const char* tabs = "\t\t\t";
fprintf(out, "\t\"programs\": [\n");
for (const auto &program : source.programs) {
// output trailing comma if necessary
if (!first) {
fprintf(out, ",\n");
} else {
first = false;
}
fprintf(out, "\t\t{\n");
fprintf(out, "%s\"name\": \"%s\",\n", tabs, program.name.c_str());
fprintf(out, "%s\"wrapTarget\": %d,\n", tabs, program.wrap_target);
fprintf(out, "%s\"wrap\": %d,\n", tabs, program.wrap);
fprintf(out, "%s\"origin\": %d,\n", tabs, program.origin.get());
if (program.sideset_bits_including_opt.is_specified()) {
fprintf(out, "%s\"sideset\": {\"size\": %d, \"optional\": %s, \"pindirs\": %s},\n", tabs, program.sideset_bits_including_opt.get(),
program.sideset_opt ? "true" : "false",
program.sideset_pindirs ? "true" : "false");
} else {
fprintf(out, "%s\"sideset\": {\"size\": 0, \"optional\": false, \"pindirs\": false},\n", tabs);
}
output_symbols(out, true, tabs, program.symbols);
fprintf(out, "%s\"instructions\": [\n", tabs);
bool first_inst = true;
for (int i = 0; i < (int)program.instructions.size(); i++) {
const auto &inst = program.instructions[i];
// output trailing comma if necessary
if (!first_inst) {
fprintf(out, ",\n");
} else {
first_inst = false;
}
// TODO: find a nice, supportable, output format for instruction disassembly.
// Note that may require tearing apart pio_disassembler to return to us something
// that we could output as {"instr":"mov", args: ["x", "~y"], side: 3, delay: 1}
// but that will likely wait for now
fprintf(out, "%s\t{\"hex\": \"%04X\"}",// \"disassembly\": \"%s\"}",
tabs, inst
//, disassemble(inst, program.sideset_bits_including_opt.get(), program.sideset_opt).c_str()
);
}
fprintf(out, "\n");
fprintf(out, "%s]\n", tabs);
fprintf(out, "\t\t}");
}
fprintf(out, "\n\t]\n}\n");
if (out != stdout) { fclose(out); }
return 0;
}
};
static json_output::factory creator;
|