1 /* A simple growing buffer for GDB. 2 3 Copyright (C) 2009-2020 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "common-defs.h" 21 #include "xml-utils.h" 22 #include "buffer.h" 23 #include "inttypes.h" 24 void 25 buffer_grow (struct buffer *buffer, const char *data, size_t size) 26 { 27 char *new_buffer; 28 size_t new_buffer_size; 29 30 if (size == 0) 31 return; 32 33 new_buffer_size = buffer->buffer_size; 34 35 if (new_buffer_size == 0) 36 new_buffer_size = 1; 37 38 while (buffer->used_size + size > new_buffer_size) 39 new_buffer_size *= 2; 40 new_buffer = (char *) xrealloc (buffer->buffer, new_buffer_size); 41 memcpy (new_buffer + buffer->used_size, data, size); 42 buffer->buffer = new_buffer; 43 buffer->buffer_size = new_buffer_size; 44 buffer->used_size += size; 45 } 46 47 void 48 buffer_free (struct buffer *buffer) 49 { 50 if (!buffer) 51 return; 52 53 xfree (buffer->buffer); 54 buffer->buffer = NULL; 55 buffer->buffer_size = 0; 56 buffer->used_size = 0; 57 } 58 59 void 60 buffer_init (struct buffer *buffer) 61 { 62 memset (buffer, 0, sizeof (*buffer)); 63 } 64 65 char* 66 buffer_finish (struct buffer *buffer) 67 { 68 char *ret = buffer->buffer; 69 buffer->buffer = NULL; 70 buffer->buffer_size = 0; 71 buffer->used_size = 0; 72 return ret; 73 } 74 75 void 76 buffer_xml_printf (struct buffer *buffer, const char *format, ...) 77 { 78 va_list ap; 79 const char *f; 80 const char *prev; 81 int percent = 0; 82 83 va_start (ap, format); 84 85 prev = format; 86 for (f = format; *f; f++) 87 { 88 if (percent) 89 { 90 char buf[32]; 91 char *str = buf; 92 const char *f_old = f; 93 94 switch (*f) 95 { 96 case 's': 97 str = va_arg (ap, char *); 98 break; 99 case 'd': 100 sprintf (str, "%d", va_arg (ap, int)); 101 break; 102 case 'u': 103 sprintf (str, "%u", va_arg (ap, unsigned int)); 104 break; 105 case 'x': 106 sprintf (str, "%x", va_arg (ap, unsigned int)); 107 break; 108 case 'o': 109 sprintf (str, "%o", va_arg (ap, unsigned int)); 110 break; 111 case 'l': 112 f++; 113 switch (*f) 114 { 115 case 'd': 116 sprintf (str, "%ld", va_arg (ap, long)); 117 break; 118 case 'u': 119 sprintf (str, "%lu", va_arg (ap, unsigned long)); 120 break; 121 case 'x': 122 sprintf (str, "%lx", va_arg (ap, unsigned long)); 123 break; 124 case 'o': 125 sprintf (str, "%lo", va_arg (ap, unsigned long)); 126 break; 127 case 'l': 128 f++; 129 switch (*f) 130 { 131 case 'd': 132 sprintf (str, "%" PRId64, 133 (int64_t) va_arg (ap, long long)); 134 break; 135 case 'u': 136 sprintf (str, "%" PRIu64, 137 (uint64_t) va_arg (ap, unsigned long long)); 138 break; 139 case 'x': 140 sprintf (str, "%" PRIx64, 141 (uint64_t) va_arg (ap, unsigned long long)); 142 break; 143 case 'o': 144 sprintf (str, "%" PRIo64, 145 (uint64_t) va_arg (ap, unsigned long long)); 146 break; 147 default: 148 str = 0; 149 break; 150 } 151 break; 152 default: 153 str = 0; 154 break; 155 } 156 break; 157 default: 158 str = 0; 159 break; 160 } 161 162 if (str) 163 { 164 buffer_grow (buffer, prev, f_old - prev - 1); 165 std::string p = xml_escape_text (str); 166 buffer_grow_str (buffer, p.c_str ()); 167 prev = f + 1; 168 } 169 percent = 0; 170 } 171 else if (*f == '%') 172 percent = 1; 173 } 174 175 buffer_grow_str (buffer, prev); 176 va_end (ap); 177 } 178 179