| /** |
| * @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", |
| "ext", |
| "unit_masks", |
| "default", |
| "category", |
| "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, size_t max) |
| { |
| char *buf; |
| int size, ret; |
| |
| buffer[max - 1] = '\0'; |
| size = strlen(buffer); |
| buf = &buffer[size]; |
| size = max - 1 - size; |
| |
| ret = snprintf(buf, size, "<%s%s", xml_tag_name(tag), |
| (with_attrs ? " " : ">\n")); |
| |
| if (ret < 0 || ret >= size) { |
| fprintf(stderr,"open_xml_element: snprintf failed\n"); |
| exit(EXIT_FAILURE); |
| } |
| } |
| |
| |
| void close_xml_element(tag_t tag, int has_nested, char *buffer, size_t max) |
| { |
| char *buf; |
| int size, ret; |
| |
| buffer[max - 1] = '\0'; |
| size = strlen(buffer); |
| buf = &buffer[size]; |
| size = max - 1 - size; |
| |
| if (tag == NONE) |
| ret = snprintf(buf, size, "%s\n", (has_nested ? ">" : "/>")); |
| else |
| ret = snprintf(buf, size, "</%s>\n", xml_tag_name(tag)); |
| |
| if (ret < 0 || ret >= size) { |
| fprintf(stderr, "close_xml_element: snprintf failed\n"); |
| exit(EXIT_FAILURE); |
| } |
| } |
| |
| |
| void init_xml_int_attr(tag_t attr, int value, char *buffer, size_t max) |
| { |
| char *buf; |
| int size, ret; |
| |
| buffer[max - 1] = '\0'; |
| size = strlen(buffer); |
| buf = &buffer[size]; |
| size = max - 1 - size; |
| |
| ret = snprintf(buf, size, " %s=\"%d\"", xml_tag_name(attr), value); |
| |
| if (ret < 0 || ret >= size) { |
| fprintf(stderr,"init_xml_int_attr: snprintf failed\n"); |
| exit(EXIT_FAILURE); |
| } |
| } |
| |
| |
| void init_xml_dbl_attr(tag_t attr, double value, char *buffer, size_t max) |
| { |
| char *buf; |
| int size, ret; |
| |
| buffer[max - 1] = '\0'; |
| size = strlen(buffer); |
| buf = &buffer[size]; |
| size = max - 1 - size; |
| |
| ret = snprintf(buf, size, " %s=\"%.2f\"", xml_tag_name(attr), value); |
| |
| if (ret < 0 || ret >= size) { |
| fprintf(stderr, "init_xml_dbl_attr: snprintf failed\n"); |
| exit(EXIT_FAILURE); |
| } |
| } |
| |
| |
| static void xml_quote(char const *str, char *buffer, size_t max) |
| { |
| char *buf; |
| char *quote; |
| char *pos = (char*)str; |
| size_t size; |
| int ret; |
| |
| buffer[max - 1] = '\0'; |
| size = strlen(buffer); |
| buf = &buffer[size]; |
| size = max - 1 - size; |
| |
| if (size < strlen(pos) + 2) |
| goto Error; |
| |
| *buf = '"'; |
| buf++; |
| size--; |
| |
| while (*pos) { |
| switch(*pos) { |
| case '&': |
| quote = "&"; |
| break; |
| case '<': |
| quote = "<"; |
| break; |
| case '>': |
| quote = ">"; |
| break; |
| case '"': |
| quote = """; |
| break; |
| default: |
| *buf = *pos; |
| pos++; |
| buf++; |
| size--; |
| continue; |
| } |
| |
| pos++; |
| ret = snprintf(buf, size, "%s", quote); |
| if (ret < 0 || ret >= (int)size) |
| goto Error; |
| buf += ret; |
| size -= ret; |
| if (size < strlen(pos)) |
| goto Error; |
| } |
| |
| if (!size) |
| goto Error; |
| |
| *buf = '"'; |
| buf++; |
| *buf = '\0'; |
| |
| return; |
| |
| Error: |
| fprintf(stderr,"quote_str: buffer overflow\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| |
| void init_xml_str_attr(tag_t attr, char const *str, char *buffer, size_t max) |
| { |
| char *buf; |
| int size, ret; |
| |
| buffer[max - 1] = '\0'; |
| size = strlen(buffer); |
| buf = &buffer[size]; |
| size = max - 1 - size; |
| |
| ret = snprintf(buf, size, " %s=", xml_tag_name(attr)); |
| if (ret < 0 || ret >= size) |
| goto Error; |
| |
| buf += ret; |
| size -= ret; |
| |
| if (!size) |
| goto Error; |
| |
| xml_quote(str, buf, size); |
| return; |
| Error: |
| fprintf(stderr,"init_xml_str_attr: snprintf failed\n"); |
| exit(EXIT_FAILURE); |
| } |