xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/xml-utils.cc (revision dcc4f12d8d65994207fd5f741e1a058e79538559)
1 /* Shared helper routines for manipulating XML.
2 
3    Copyright (C) 2006-2024 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 "xml-utils.h"
21 
22 /* See xml-utils.h.  */
23 
24 std::string
25 xml_escape_text (const char *text)
26 {
27   std::string result;
28 
29   xml_escape_text_append (result, text);
30 
31   return result;
32 }
33 
34 /* See xml-utils.h.  */
35 
36 void
37 xml_escape_text_append (std::string &result, const char *text)
38 {
39   /* Expand the result.  */
40   for (int i = 0; text[i] != '\0'; i++)
41     switch (text[i])
42       {
43       case '\'':
44 	result += "&apos;";
45 	break;
46       case '\"':
47 	result += "&quot;";
48 	break;
49       case '&':
50 	result += "&amp;";
51 	break;
52       case '<':
53 	result += "&lt;";
54 	break;
55       case '>':
56 	result += "&gt;";
57 	break;
58       default:
59 	result += text[i];
60 	break;
61       }
62 }
63 
64 /* See xml-utils.h.  */
65 
66 void
67 string_xml_appendf (std::string &buffer, const char *format, ...)
68 {
69   va_list ap;
70   const char *f;
71   const char *prev;
72   int percent = 0;
73 
74   va_start (ap, format);
75 
76   prev = format;
77   for (f = format; *f; f++)
78     {
79       if (percent)
80 	{
81 	  char buf[32];
82 	  char *str = buf;
83 	  const char *f_old = f;
84 
85 	  switch (*f)
86 	    {
87 	    case 's':
88 	      str = va_arg (ap, char *);
89 	      break;
90 	    case 'd':
91 	      sprintf (str, "%d", va_arg (ap, int));
92 	      break;
93 	    case 'u':
94 	      sprintf (str, "%u", va_arg (ap, unsigned int));
95 	      break;
96 	    case 'x':
97 	      sprintf (str, "%x", va_arg (ap, unsigned int));
98 	      break;
99 	    case 'o':
100 	      sprintf (str, "%o", va_arg (ap, unsigned int));
101 	      break;
102 	    case 'l':
103 	      f++;
104 	      switch (*f)
105 		{
106 		case 'd':
107 		  sprintf (str, "%ld", va_arg (ap, long));
108 		  break;
109 		case 'u':
110 		  sprintf (str, "%lu", va_arg (ap, unsigned long));
111 		  break;
112 		case 'x':
113 		  sprintf (str, "%lx", va_arg (ap, unsigned long));
114 		  break;
115 		case 'o':
116 		  sprintf (str, "%lo", va_arg (ap, unsigned long));
117 		  break;
118 		case 'l':
119 		  f++;
120 		  switch (*f)
121 		    {
122 		    case 'd':
123 		      sprintf (str, "%" PRId64,
124 			       (int64_t) va_arg (ap, long long));
125 		      break;
126 		    case 'u':
127 		      sprintf (str, "%" PRIu64,
128 			       (uint64_t) va_arg (ap, unsigned long long));
129 		      break;
130 		    case 'x':
131 		      sprintf (str, "%" PRIx64,
132 			       (uint64_t) va_arg (ap, unsigned long long));
133 		      break;
134 		    case 'o':
135 		      sprintf (str, "%" PRIo64,
136 			       (uint64_t) va_arg (ap, unsigned long long));
137 		      break;
138 		    default:
139 		      str = 0;
140 		      break;
141 		    }
142 		  break;
143 		default:
144 		  str = 0;
145 		  break;
146 		}
147 	      break;
148 	    default:
149 	      str = 0;
150 	      break;
151 	    }
152 
153 	  if (str)
154 	    {
155 	      buffer.append (prev, f_old - prev - 1);
156 	      xml_escape_text_append (buffer, str);
157 	      prev = f + 1;
158 	    }
159 	  percent = 0;
160 	}
161       else if (*f == '%')
162 	percent = 1;
163     }
164 
165   buffer.append (prev);
166   va_end (ap);
167 }
168