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