~pbatch/patchwerk

patchwerk/dump.w -rw-r--r-- 5.2 KiB
9c265356 — paul plan9 additions from Sigrid 3 months ago
                                                                                
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
@** Data Dumping. When debugging Patchwerk, it can helpful to probe the inner
contents. This issue of needing to see information has come up enough times
in production to warrant a formal interface for printing contents.

The following functions can be used to print contents to file or
standard output. The data format is JSON, which can be scanned or prettified
using external utilities like jq or Python.

@<Top@>+=
@<Data Dumpers@>

@ The function |pw_dump_cable| dumps the contents of a cable.
@<Header@>+=
void pw_dump_cable(FILE *fp, pw_cable *c);

@ @<Data Dumpers@>+=
void pw_dump_cable(FILE *fp, pw_cable *c)
{
    fprintf(fp, "{");
    fprintf(fp, "\"type\":");
    if(c->type == CABLE_BLOCK) {
        fprintf(fp, "\"block\",");
    } else if(c->type == CABLE_IVAL){
        fprintf(fp, "\"constant\",");
    }
    fprintf(fp, "\"node_id\":");
    if(c->node == NULL) {
        fprintf(fp, "-1,");
    } else {
        fprintf(fp, "%d,", pw_node_get_id(c->node));
    }
    fprintf(fp, "\"ival\":%g,", c->ival);
    fprintf(fp, "\"buffer\":");
    if(c->buf != NULL) {
        fprintf(fp, "%d,", pw_buffer_id(c->buf));
    } else {
        fprintf(fp, "-1,");
    }
    fprintf(fp, "\"pcable\":");
    if(c->pcable != c) {
        pw_dump_cable(fp, c->pcable);
    } else {
        fprintf(fp, "{}");
    }
    fprintf(fp, "}");
}

@ The function |pw_dump_node| dumps the contents of a node.
@<Header@>+=
void pw_dump_node(FILE *fp, pw_node *n, int print_cables);
@ @<Data Dumpers@>+=
void pw_dump_node(FILE *fp, pw_node *n, int print_cables)
{
    int c;
    fprintf(fp, "{");
    fprintf(fp, "\"id\":%d,", n->id);
    fprintf(fp, "\"ncables\":%d,", n->ncables);
    fprintf(fp, "\"type\":%d", n->type);
    if(print_cables) {
        fprintf(fp, ",");
        fprintf(fp, "\"cables\":[");
            for(c = 0; c < n->ncables; c++) {
                pw_dump_cable(fp, &n->cables[c]);
                if(c != n->ncables - 1) {
                    fprintf(fp,",");
                }
            }
        fprintf(fp, "]");
    }
    fprintf(fp, "}");
}

@ The function |pw_dump_nodes| is a function that dumps a linked list of
nodes. It is used inside |pw_dump_nodelist| and |pw_dump_subpatch|. It
normally shouldn't be called directly.
@<Header@>+=
void pw_dump_nodes(FILE *fp, pw_node *nodes, int nnodes, int print_cables);
@ @<Data Dumpers@>+=
void pw_dump_nodes(FILE *fp, pw_node *nodes, int nnodes, int print_cables)
{
    int n;
    pw_node *nd;
    pw_node *nxt;
    nd = nodes;
    fprintf(fp, "{");
    fprintf(fp, "\"nnodes\":%d,", nnodes);
    fprintf(fp, "\"nodes\":[");
    for(n = 0; n < nnodes; n++) {
        nxt = nd->next;
        pw_dump_node(fp, nd, print_cables);
        if(n != nnodes - 1) {
            fprintf(fp, ",");
        }
        nd = nxt;
    }
    fprintf(fp, "]");
    fprintf(fp, "}");
}

@ The function |pw_dump_nodelist| dumps the list of nodes in the current
patch.
@<Header@>+=
void pw_dump_nodelist(FILE *fp, pw_patch *p, int print_cables);
@ @<Data Dumpers@>+=
void pw_dump_nodelist(FILE *fp, pw_patch *p, int print_cables)
{
    pw_dump_nodes(fp, p->nodes, p->nnodes, print_cables);
}


@ The function |pw_dump_subpatch| dumps the contents of a subpatch.
@<Header@>+=
void pw_dump_subpatch(FILE *fp, pw_subpatch *s, int print_cables);

@ @<Data Dumpers@>+=
void pw_dump_subpatch(FILE *fp, pw_subpatch *s, int print_cables)
{
    pw_dump_nodes(fp, s->nodes, s->nnodes, print_cables);
}

@ The function |pw_dump_bufferpool| dumps the contents of the bufferpool.
@<Header@>+=
void pw_dump_bufferpool(FILE *fp, pw_bufferpool *bp, int print_buffers);
@ @<Data Dumpers@>+=
void pw_dump_bufferpool(FILE *fp, pw_bufferpool *bp, int print_buffers)
{
    int b;
    int pos;
    fprintf(fp, "{");
    fprintf(fp, "\"size\": %d,", bp->size);
    fprintf(fp, "\"nactive\": %d,", bp->nactive);
    fprintf(fp, "\"user_buffers\": %d,", pw_bufferpool_uactive(bp));
    fprintf(fp, "\"last_free\": %d", bp->last_free);
    if(print_buffers) {
        fprintf(fp, ",\"buffers\":[");
        pos = 0;
        for(b = 0; b < bp->size; b++) {
            if(bp->buffers[b].read != 0) {
                pw_dump_buffer(fp, &bp->buffers[b]);
                pos++;
                if(pos != bp->nactive) fprintf(fp, ",");
            }
        }
        fprintf(fp, "]");
    }
    fprintf(fp, "}");
}

@ The function |pw_dump_stack| dumps the contents of the buffer stack.
@<Header@>+=
void pw_dump_stack(FILE *fp, pw_stack *s, int print_buffers);
@ @<Data Dumpers@>+=
void pw_dump_stack(FILE *fp, pw_stack *s, int print_buffers)
{
    int b;
    fprintf(fp, "{");
    fprintf(fp, "\"size\": %d,", s->size);
    fprintf(fp, "\"pos\": %d", s->pos);
    if(print_buffers) {
        fprintf(fp, ",\"buffers\":[");
        for(b = 0; b < s->pos; b++) {
            pw_dump_buffer(fp, s->buffers[b]);
            if(b != s->pos - 1) {
                fprintf(fp, ",");
            }
        }
        fprintf(fp, "]");
    }
    fprintf(fp, "}");
}

@ The function |pw_dump_buffer| dumps the contents of a buffer.
@<Header@>+=
void pw_dump_buffer(FILE *fp, pw_buffer *b);
@ @<Data Dumpers@>+=
void pw_dump_buffer(FILE *fp, pw_buffer *b)
{
    fprintf(fp, "{");
    fprintf(fp, "\"id\": %d,", b->id);
    fprintf(fp, "\"read\": %d", b->read);
    fprintf(fp, "}");
}