1/**
2 * @file op_xml_out.c
3 * C utility routines for writing XML
4 *
5 * @remark Copyright 2008 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author Dave Nomura
9 */
10
11#include <stdio.h>
12#include <string.h>
13#include <stdlib.h>
14#include "op_xml_out.h"
15
16char const * xml_tag_map[] = {
17	"NONE",
18	"id",
19	"profile",
20		"processor",
21		"cputype",
22		"title",
23		"schemaversion",
24		"mhz",
25	"setup",
26	"timersetup",
27		"rtcinterrupts",
28	"eventsetup",
29		"eventname",
30		"unitmask",
31		"setupcount",
32		"separatedcpus",
33	"options",
34		"session", "debuginfo", "details", "excludedependent",
35		"excludesymbols", "imagepath", "includesymbols", "merge",
36	"classes",
37	"class",
38		"cpu",
39		"event",
40		"mask",
41	"process",
42		"pid",
43	"thread",
44		"tid",
45	"binary",
46	"module",
47		"name",
48	"callers",
49	"callees",
50	"symbol",
51		"idref",
52		"self",
53		"detaillo",
54		"detailhi",
55	"symboltable",
56	"symboldata",
57		"startingaddr",
58		"file",
59		"line",
60		"codelength",
61	"summarydata",
62	"sampledata",
63	"count",
64	"detailtable",
65	"symboldetails",
66	"detaildata",
67		"vmaoffset",
68	"bytestable",
69	"bytes",
70	"help_events",
71	"header",
72		"title",
73		"doc",
74	"event",
75		"event_name",
76		"group",
77		"desc",
78		"counter_mask",
79		"min_count",
80		"ext",
81	"unit_masks",
82		"default",
83		"category",
84	"unit_mask",
85		"mask",
86		"desc"
87};
88
89#define MAX_BUF_LEN 2048
90char const * xml_tag_name(tag_t tag)
91{
92	return xml_tag_map[tag];
93}
94
95
96void open_xml_element(tag_t tag, int with_attrs, char *buffer, size_t max)
97{
98	char *buf;
99	int size, ret;
100
101	buffer[max - 1] = '\0';
102	size = strlen(buffer);
103	buf = &buffer[size];
104	size = max - 1 - size;
105
106	ret = snprintf(buf, size, "<%s%s", xml_tag_name(tag),
107		       (with_attrs ? " " : ">\n"));
108
109	if (ret < 0 || ret >= size) {
110		fprintf(stderr,"open_xml_element: snprintf failed\n");
111		exit(EXIT_FAILURE);
112	}
113}
114
115
116void close_xml_element(tag_t tag, int has_nested, char *buffer, size_t max)
117{
118	char *buf;
119	int size, ret;
120
121	buffer[max - 1] = '\0';
122	size = strlen(buffer);
123	buf = &buffer[size];
124	size = max - 1 - size;
125
126	if (tag == NONE)
127		ret = snprintf(buf, size, "%s\n", (has_nested ? ">" : "/>"));
128	else
129		ret = snprintf(buf, size, "</%s>\n", xml_tag_name(tag));
130
131	if (ret < 0 || ret >= size) {
132		fprintf(stderr, "close_xml_element: snprintf failed\n");
133		exit(EXIT_FAILURE);
134	}
135}
136
137
138void init_xml_int_attr(tag_t attr, int value, char *buffer, size_t max)
139{
140	char *buf;
141	int size, ret;
142
143	buffer[max - 1] = '\0';
144	size = strlen(buffer);
145	buf = &buffer[size];
146	size = max - 1 - size;
147
148	ret = snprintf(buf, size, " %s=\"%d\"", xml_tag_name(attr), value);
149
150	if (ret < 0 || ret >= size) {
151		fprintf(stderr,"init_xml_int_attr: snprintf failed\n");
152		exit(EXIT_FAILURE);
153	}
154}
155
156
157void init_xml_dbl_attr(tag_t attr, double value, char *buffer, size_t max)
158{
159	char *buf;
160	int size, ret;
161
162	buffer[max - 1] = '\0';
163	size = strlen(buffer);
164	buf = &buffer[size];
165	size = max - 1 - size;
166
167	ret = snprintf(buf, size, " %s=\"%.2f\"", xml_tag_name(attr), value);
168
169	if (ret < 0 || ret >= size) {
170		fprintf(stderr, "init_xml_dbl_attr: snprintf failed\n");
171		exit(EXIT_FAILURE);
172	}
173}
174
175
176static void xml_quote(char const *str, char *buffer, size_t max)
177{
178	char *buf;
179	char *quote;
180	char *pos = (char*)str;
181	size_t size;
182	int ret;
183
184	buffer[max - 1] = '\0';
185	size = strlen(buffer);
186	buf = &buffer[size];
187	size = max - 1 - size;
188
189	if (size < strlen(pos) + 2)
190		goto Error;
191
192	*buf = '"';
193	buf++;
194	size--;
195
196	while (*pos) {
197		switch(*pos) {
198		case '&':
199			quote = "&amp;";
200			break;
201		case '<':
202			quote = "&lt;";
203			break;
204		case '>':
205                        quote = "&gt;";
206			break;
207		case '"':
208			quote = "&quot;";
209			break;
210		default:
211			*buf = *pos;
212			pos++;
213			buf++;
214			size--;
215			continue;
216		}
217
218		pos++;
219		ret = snprintf(buf, size, "%s", quote);
220		if (ret < 0 || ret >= (int)size)
221			goto Error;
222		buf += ret;
223		size -= ret;
224		if (size < strlen(pos))
225			goto Error;
226	}
227
228	if (!size)
229		goto Error;
230
231	*buf = '"';
232	buf++;
233	*buf = '\0';
234
235	return;
236
237Error:
238	fprintf(stderr,"quote_str: buffer overflow\n");
239	exit(EXIT_FAILURE);
240}
241
242
243void init_xml_str_attr(tag_t attr, char const *str, char *buffer, size_t max)
244{
245	char *buf;
246	int size, ret;
247
248	buffer[max - 1] = '\0';
249	size = strlen(buffer);
250	buf = &buffer[size];
251	size = max - 1 - size;
252
253	ret = snprintf(buf, size, " %s=", xml_tag_name(attr));
254	if (ret < 0 || ret >= size)
255		goto Error;
256
257	buf += ret;
258	size -= ret;
259
260	if (!size)
261		goto Error;
262
263	xml_quote(str, buf, size);
264	return;
265Error:
266	fprintf(stderr,"init_xml_str_attr: snprintf failed\n");
267	exit(EXIT_FAILURE);
268}
269