| 129 | } |
| 130 | |
| 131 | static void graph_show_jgf(Graph g, FILE *fp) |
| 132 | { |
| 133 | fputs("{\n" |
| 134 | " \"graph\": {\n" |
| 135 | " \"version\": \"1.0\",\n" |
| 136 | " \"directed\": true,\n" |
| 137 | " \"type\": \"tree\",\n" |
| 138 | " \"root\": 0,\n" |
| 139 | " \"order\": \"dfs-preorder\",\n", |
| 140 | fp); |
| 141 | |
| 142 | if (filename) |
| 143 | /* assume no need to escape filename */ |
| 144 | fprintf(fp, " \"label\": \"%s\",\n", filename); |
| 145 | |
| 146 | fputs(" \"nodes\": [\n", fp); |
| 147 | |
| 148 | det_coords_adjust_labels(g); |
| 149 | |
| 150 | Node n; |
| 151 | for (n = g->nodes; n; n = n->next) { |
| 152 | fprintf(fp, " { \"id\":%2u,\"label\":", n->visited); |
| 153 | show(fp, n->label, 1); |
| 154 | if (n->line) /* leaf node */ |
| 155 | fprintf(fp, ",\"line\":%u,\"column\":%u", n->line, n->column); |
| 156 | fputs(" }", fp); |
| 157 | if (n->next) fputc(',', fp); |
| 158 | fputc('\n', fp); |
| 159 | } |
| 160 | fputs(" ],\n" |
| 161 | " \"edges\": [\n", fp); |
| 162 | int need_comma = 0; |
| 163 | for (n = g->nodes; n; n = n->next) { |
| 164 | Edge e; |
| 165 | for (e = n->outgoing; e; e = e->next_adj_out) { |
| 166 | if (need_comma) fputs(",\n", fp); |
| 167 | fprintf(fp, " { \"between\": [%2u,%2u] }", |
| 168 | e->from->visited, |
| 169 | e->to->visited); |
| 170 | need_comma = 1; |
| 171 | } |
| 172 | } |
| 173 | if (need_comma) fputc('\n', fp); |
| 174 | fputs(" ]\n }\n}\n", fp); |
| 175 | } |
| 176 | |
| 177 | /* Undo JSON escaping: \\ => \. */ |
| 178 | static void JSON_unescape(jsmntok_t *tok) |
no test coverage detected