Ben Cheng | 5a4eb4e | 2009-09-14 16:00:41 -0700 | [diff] [blame] | 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 | |
| 16 | char 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 | "unit_masks", |
| 81 | "default", |
| 82 | "unit_mask", |
| 83 | "mask", |
| 84 | "desc" |
| 85 | }; |
| 86 | |
| 87 | #define MAX_BUF_LEN 2048 |
| 88 | char const * xml_tag_name(tag_t tag) |
| 89 | { |
| 90 | return xml_tag_map[tag]; |
| 91 | } |
| 92 | |
| 93 | |
| 94 | void open_xml_element(tag_t tag, int with_attrs, char * buffer) |
| 95 | { |
| 96 | char const * tag_name = xml_tag_name(tag); |
| 97 | unsigned int const max_len = strlen(tag_name) + 3; |
| 98 | char tmp_buf[MAX_BUF_LEN]; |
| 99 | |
| 100 | if (max_len >= sizeof(tmp_buf)) |
| 101 | fprintf(stderr,"Warning: open_xml_element: buffer overflow %d\n", max_len); |
| 102 | |
| 103 | if (snprintf(tmp_buf, sizeof(tmp_buf), "<%s%s", tag_name, |
| 104 | (with_attrs ? " " : ">\n")) < 0) { |
| 105 | fprintf(stderr,"open_xml_element: snprintf failed\n"); |
| 106 | exit(EXIT_FAILURE); |
| 107 | } |
| 108 | strncat(buffer, tmp_buf, sizeof(tmp_buf)); |
| 109 | } |
| 110 | |
| 111 | |
| 112 | void close_xml_element(tag_t tag, int has_nested, char * buffer) |
| 113 | { |
| 114 | char const * tag_name = xml_tag_name(tag); |
| 115 | unsigned int const max_len = strlen(tag_name) + 3; |
| 116 | char tmp_buf[MAX_BUF_LEN]; |
| 117 | |
| 118 | if (max_len >= sizeof(tmp_buf)) |
| 119 | fprintf(stderr,"Warning: close_xml_element: buffer overflow %d\n", max_len); |
| 120 | |
| 121 | if (tag == NONE) { |
| 122 | if (snprintf(tmp_buf, sizeof(tmp_buf), "%s\n", (has_nested ? ">" : "/>")) < 0) { |
| 123 | fprintf(stderr, "close_xml_element: snprintf failed\n"); |
| 124 | exit(EXIT_FAILURE); |
| 125 | } |
| 126 | } else { |
| 127 | if (snprintf(tmp_buf, sizeof(tmp_buf), "</%s>\n", tag_name) < 0) { |
| 128 | fprintf(stderr, "close_xml_element: snprintf failed\n"); |
| 129 | exit(EXIT_FAILURE); |
| 130 | } |
| 131 | } |
| 132 | strncat(buffer, tmp_buf, sizeof(tmp_buf)); |
| 133 | } |
| 134 | |
| 135 | |
| 136 | void init_xml_int_attr(tag_t attr, int value, char * buffer) |
| 137 | { |
| 138 | char const * attr_name = xml_tag_name(attr); |
| 139 | char tmp_buf[MAX_BUF_LEN]; |
| 140 | unsigned int const max_len = strlen(attr_name) + 50; |
| 141 | |
| 142 | if (max_len >= sizeof(tmp_buf)) { |
| 143 | fprintf(stderr, |
| 144 | "Warning: init_xml_int_attr: buffer overflow %d\n", max_len); |
| 145 | } |
| 146 | |
| 147 | |
| 148 | if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=\"%d\"", attr_name, value) < 0) { |
| 149 | fprintf(stderr,"init_xml_int_attr: snprintf failed\n"); |
| 150 | exit(EXIT_FAILURE); |
| 151 | } |
| 152 | strncat(buffer, tmp_buf, sizeof(tmp_buf)); |
| 153 | } |
| 154 | |
| 155 | |
| 156 | void init_xml_dbl_attr(tag_t attr, double value, char * buffer) |
| 157 | { |
| 158 | char const * attr_name = xml_tag_name(attr); |
| 159 | unsigned int const max_len = strlen(attr_name) + 50; |
| 160 | char tmp_buf[MAX_BUF_LEN]; |
| 161 | |
| 162 | if (max_len >= sizeof(tmp_buf)) |
| 163 | fprintf(stderr, "Warning: init_xml_dbl_attr: buffer overflow %d\n", max_len); |
| 164 | |
| 165 | if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=\"%.2f\"", attr_name, value) < 0) { |
| 166 | fprintf(stderr, "init_xml_dbl_attr: snprintf failed\n"); |
| 167 | exit(EXIT_FAILURE); |
| 168 | } |
| 169 | strncat(buffer, tmp_buf, sizeof(tmp_buf)); |
| 170 | } |
| 171 | |
| 172 | |
| 173 | static char * xml_quote(char const * str, char * quote_buf) |
| 174 | { |
| 175 | int i; |
| 176 | int pos = 0; |
| 177 | int len = strlen(str); |
| 178 | |
| 179 | |
| 180 | quote_buf[pos++] = '"'; |
| 181 | |
| 182 | for (i = 0; i < len; i++) { |
| 183 | if (pos >= MAX_BUF_LEN - 10) { |
| 184 | fprintf(stderr,"quote_str: buffer overflow %d\n", pos); |
| 185 | exit(EXIT_FAILURE); |
| 186 | } |
| 187 | |
| 188 | switch(str[i]) { |
| 189 | case '&': |
| 190 | strncpy(quote_buf + pos, "&", 5); |
| 191 | pos += 5; |
| 192 | break; |
| 193 | case '<': |
| 194 | strncpy(quote_buf + pos, "<", 4); |
| 195 | pos += 4; |
| 196 | break; |
| 197 | case '>': |
| 198 | strncpy(quote_buf + pos, ">", 4); |
| 199 | pos += 4; |
| 200 | break; |
| 201 | case '"': |
| 202 | strncpy(quote_buf + pos, """, 6); |
| 203 | pos += 6; |
| 204 | break; |
| 205 | default: |
| 206 | quote_buf[pos++] = str[i]; |
| 207 | break; |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | quote_buf[pos++] = '"'; |
| 212 | quote_buf[pos++] = '\0'; |
| 213 | return quote_buf; |
| 214 | } |
| 215 | |
| 216 | |
| 217 | void init_xml_str_attr(tag_t attr, char const * str, char * buffer) |
| 218 | { |
| 219 | char tmp_buf[MAX_BUF_LEN]; |
| 220 | char quote_buf[MAX_BUF_LEN]; |
| 221 | char const * attr_name = xml_tag_name(attr); |
| 222 | char const * quote_str = xml_quote(str, quote_buf); |
| 223 | const unsigned int max_len = strlen(attr_name) + strlen(quote_str) + 10; |
| 224 | |
| 225 | if (max_len >= sizeof(tmp_buf)) |
| 226 | fprintf(stderr, "Warning: init_xml_str_attr: buffer overflow %d\n", max_len); |
| 227 | |
| 228 | if (snprintf(tmp_buf, sizeof(tmp_buf), " %s=""%s""", attr_name, quote_str) < 0) { |
| 229 | fprintf(stderr,"init_xml_str_attr: snprintf failed\n"); |
| 230 | exit(EXIT_FAILURE); |
| 231 | } |
| 232 | strncat(buffer, tmp_buf, sizeof(tmp_buf)); |
| 233 | } |