| /** |
| * @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)); |
| } |