/**
* @file op_xml_out.c
* C utility routines for writing XML
*
* @remark Copyright 2008 OProfile authors
* @remark Read the file COPYING
*
* @author Dave Nomura
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "op_xml_out.h"
char const * xml_tag_map[] = {
"NONE",
"id",
"profile",
"processor",
"cputype",
"title",
"schemaversion",
"mhz",
"setup",
"timersetup",
"rtcinterrupts",
"eventsetup",
"eventname",
"unitmask",
"setupcount",
"separatedcpus",
"options",
"session", "debuginfo", "details", "excludedependent",
"excludesymbols", "imagepath", "includesymbols", "merge",
"classes",
"class",
"cpu",
"event",
"mask",
"process",
"pid",
"thread",
"tid",
"binary",
"module",
"name",
"callers",
"callees",
"symbol",
"idref",
"self",
"detaillo",
"detailhi",
"symboltable",
"symboldata",
"startingaddr",
"file",
"line",
"codelength",
"summarydata",
"sampledata",
"count",
"detailtable",
"symboldetails",
"detaildata",
"vmaoffset",
"bytestable",
"bytes",
"help_events",
"header",
"title",
"doc",
"event",
"event_name",
"group",
"desc",
"counter_mask",
"min_count",
"unit_masks",
"default",
"unit_mask",
"mask",
"desc"
};
#define MAX_BUF_LEN 2048
char const * xml_tag_name(tag_t tag)
{
return xml_tag_map[tag];
}
void open_xml_element(tag_t tag, int with_attrs, char * buffer)
{
char const * tag_name = xml_tag_name(tag);
unsigned int const max_len = strlen(tag_name) + 3;
char tmp_buf[MAX_BUF_LEN];
if (max_len >= sizeof(tmp_buf))
fprintf(stderr,"Warning: open_xml_element: buffer overflow %d\n", max_len);
if (snprintf(tmp_buf, sizeof(tmp_buf), "<%s%s", tag_name,
(with_attrs ? " " : ">\n")) < 0) {
fprintf(stderr,"open_xml_element: snprintf failed\n");
exit(EXIT_FAILURE);
}
strncat(buffer, tmp_buf, sizeof(tmp_buf));
}
void close_xml_element(tag_t tag, int has_nested, char * buffer)
{
char const * tag_name = xml_tag_name(tag);
unsigned int const max_len = strlen(tag_name) + 3;
char tmp_buf[MAX_BUF_LEN];
if (max_len >= sizeof(tmp_buf))
fprintf(stderr,"Warning: close_xml_element: buffer overflow %d\n", max_len);
if (tag == NONE) {
if (snprintf(tmp_buf, sizeof(tmp_buf), "%s\n", (has_nested ? ">" : "/>")) < 0) {
fprintf(stderr, "close_xml_element: snprintf failed\n");
exit(EXIT_FAILURE);
}
} else {
if (snprintf(tmp_buf, sizeof(tmp_buf), "</%s>\n", tag_name) < 0) {
fprintf(stderr, "close_xml_element: snprintf failed\n");
exit(EXIT_FAILURE);
}
}
strncat(buffer, tmp_buf, sizeof(tmp_buf));
}
void init_xml_int_attr(tag_t attr, int value, char * buffer)
{
char const * attr_name = xml_tag_name(attr);
char tmp_buf[MAX_BUF_LEN];
unsigned int const max_len = strlen(attr_name) + 50;
if (max_len >= sizeof(tmp_buf)) {
fprintf(stderr,
"Warning: init_xml_int_attr: buffer overflow %d\n", max_len);
}
if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=\"%d\"", attr_name, value) < 0) {
fprintf(stderr,"init_xml_int_attr: snprintf failed\n");
exit(EXIT_FAILURE);
}
strncat(buffer, tmp_buf, sizeof(tmp_buf));
}
void init_xml_dbl_attr(tag_t attr, double value, char * buffer)
{
char const * attr_name = xml_tag_name(attr);
unsigned int const max_len = strlen(attr_name) + 50;
char tmp_buf[MAX_BUF_LEN];
if (max_len >= sizeof(tmp_buf))
fprintf(stderr, "Warning: init_xml_dbl_attr: buffer overflow %d\n", max_len);
if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=\"%.2f\"", attr_name, value) < 0) {
fprintf(stderr, "init_xml_dbl_attr: snprintf failed\n");
exit(EXIT_FAILURE);
}
strncat(buffer, tmp_buf, sizeof(tmp_buf));
}
static char * xml_quote(char const * str, char * quote_buf)
{
int i;
int pos = 0;
int len = strlen(str);
quote_buf[pos++] = '"';
for (i = 0; i < len; i++) {
if (pos >= MAX_BUF_LEN - 10) {
fprintf(stderr,"quote_str: buffer overflow %d\n", pos);
exit(EXIT_FAILURE);
}
switch(str[i]) {
case '&':
strncpy(quote_buf + pos, "&", 5);
pos += 5;
break;
case '<':
strncpy(quote_buf + pos, "<", 4);
pos += 4;
break;
case '>':
strncpy(quote_buf + pos, ">", 4);
pos += 4;
break;
case '"':
strncpy(quote_buf + pos, """, 6);
pos += 6;
break;
default:
quote_buf[pos++] = str[i];
break;
}
}
quote_buf[pos++] = '"';
quote_buf[pos++] = '\0';
return quote_buf;
}
void init_xml_str_attr(tag_t attr, char const * str, char * buffer)
{
char tmp_buf[MAX_BUF_LEN];
char quote_buf[MAX_BUF_LEN];
char const * attr_name = xml_tag_name(attr);
char const * quote_str = xml_quote(str, quote_buf);
const unsigned int max_len = strlen(attr_name) + strlen(quote_str) + 10;
if (max_len >= sizeof(tmp_buf))
fprintf(stderr, "Warning: init_xml_str_attr: buffer overflow %d\n", max_len);
if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=""%s""", attr_name, quote_str) < 0) {
fprintf(stderr,"init_xml_str_attr: snprintf failed\n");
exit(EXIT_FAILURE);
}
strncat(buffer, tmp_buf, sizeof(tmp_buf));
}