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