scm-string.c revision 1.8 1 1.1 christos /* GDB/Scheme charset interface.
2 1.1 christos
3 1.8 christos Copyright (C) 2014-2023 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GDB.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1 christos /* See README file in this directory for implementation notes, coding
21 1.1 christos conventions, et.al. */
22 1.1 christos
23 1.1 christos #include "defs.h"
24 1.1 christos #include "charset.h"
25 1.1 christos #include "guile-internal.h"
26 1.8 christos #include "gdbsupport/buildargv.h"
27 1.1 christos
28 1.1 christos /* Convert STRING to an int.
29 1.1 christos STRING must be a valid integer. */
30 1.1 christos
31 1.1 christos int
32 1.1 christos gdbscm_scm_string_to_int (SCM string)
33 1.1 christos {
34 1.1 christos char *s = scm_to_latin1_string (string);
35 1.1 christos int r = atoi (s);
36 1.1 christos
37 1.1 christos free (s);
38 1.1 christos return r;
39 1.1 christos }
40 1.1 christos
41 1.1 christos /* Convert a C (latin1) string to an SCM string.
42 1.1 christos "latin1" is chosen because Guile won't throw an exception. */
43 1.1 christos
44 1.1 christos SCM
45 1.1 christos gdbscm_scm_from_c_string (const char *string)
46 1.1 christos {
47 1.1 christos return scm_from_latin1_string (string);
48 1.1 christos }
49 1.1 christos
50 1.1 christos /* Convert an SCM string to a C (latin1) string.
51 1.1 christos "latin1" is chosen because Guile won't throw an exception.
52 1.1 christos It is an error to call this if STRING is not a string. */
53 1.1 christos
54 1.6 christos gdb::unique_xmalloc_ptr<char>
55 1.1 christos gdbscm_scm_to_c_string (SCM string)
56 1.1 christos {
57 1.6 christos return gdb::unique_xmalloc_ptr<char> (scm_to_latin1_string (string));
58 1.1 christos }
59 1.1 christos
60 1.1 christos /* Use printf to construct a Scheme string. */
61 1.1 christos
62 1.1 christos SCM
63 1.1 christos gdbscm_scm_from_printf (const char *format, ...)
64 1.1 christos {
65 1.1 christos va_list args;
66 1.1 christos SCM result;
67 1.1 christos
68 1.1 christos va_start (args, format);
69 1.6 christos std::string string = string_vprintf (format, args);
70 1.1 christos va_end (args);
71 1.6 christos result = scm_from_latin1_string (string.c_str ());
72 1.1 christos
73 1.1 christos return result;
74 1.1 christos }
75 1.1 christos
76 1.1 christos /* Struct to pass data from gdbscm_scm_to_string to
77 1.1 christos gdbscm_call_scm_to_stringn. */
78 1.1 christos
79 1.1 christos struct scm_to_stringn_data
80 1.1 christos {
81 1.1 christos SCM string;
82 1.1 christos size_t *lenp;
83 1.1 christos const char *charset;
84 1.4 christos scm_t_string_failed_conversion_handler conversion_kind;
85 1.1 christos char *result;
86 1.1 christos };
87 1.1 christos
88 1.1 christos /* Helper for gdbscm_scm_to_string to call scm_to_stringn
89 1.1 christos from within scm_c_catch. */
90 1.1 christos
91 1.1 christos static SCM
92 1.1 christos gdbscm_call_scm_to_stringn (void *datap)
93 1.1 christos {
94 1.4 christos struct scm_to_stringn_data *data = (struct scm_to_stringn_data *) datap;
95 1.1 christos
96 1.1 christos data->result = scm_to_stringn (data->string, data->lenp, data->charset,
97 1.1 christos data->conversion_kind);
98 1.1 christos return SCM_BOOL_F;
99 1.1 christos }
100 1.1 christos
101 1.1 christos /* Convert an SCM string to a string in charset CHARSET.
102 1.1 christos This function is guaranteed to not throw an exception.
103 1.1 christos
104 1.1 christos If LENP is NULL then the returned string is NUL-terminated,
105 1.1 christos and an exception is thrown if the string contains embedded NULs.
106 1.1 christos Otherwise the string is not guaranteed to be NUL-terminated, but worse
107 1.1 christos there's no space to put a NUL if we wanted to (scm_to_stringn limitation).
108 1.1 christos
109 1.1 christos If STRICT is non-zero, and there's a conversion error, then a
110 1.1 christos <gdb:exception> object is stored in *EXCEPT_SCMP, and NULL is returned.
111 1.1 christos If STRICT is zero, then escape sequences are used for characters that
112 1.1 christos can't be converted, and EXCEPT_SCMP may be passed as NULL.
113 1.1 christos
114 1.1 christos It is an error to call this if STRING is not a string. */
115 1.1 christos
116 1.6 christos gdb::unique_xmalloc_ptr<char>
117 1.1 christos gdbscm_scm_to_string (SCM string, size_t *lenp,
118 1.1 christos const char *charset, int strict, SCM *except_scmp)
119 1.1 christos {
120 1.1 christos struct scm_to_stringn_data data;
121 1.1 christos SCM scm_result;
122 1.1 christos
123 1.1 christos data.string = string;
124 1.1 christos data.lenp = lenp;
125 1.1 christos data.charset = charset;
126 1.1 christos data.conversion_kind = (strict
127 1.1 christos ? SCM_FAILED_CONVERSION_ERROR
128 1.1 christos : SCM_FAILED_CONVERSION_ESCAPE_SEQUENCE);
129 1.1 christos data.result = NULL;
130 1.1 christos
131 1.1 christos scm_result = gdbscm_call_guile (gdbscm_call_scm_to_stringn, &data, NULL);
132 1.1 christos
133 1.1 christos if (gdbscm_is_false (scm_result))
134 1.1 christos {
135 1.1 christos gdb_assert (data.result != NULL);
136 1.6 christos return gdb::unique_xmalloc_ptr<char> (data.result);
137 1.1 christos }
138 1.1 christos gdb_assert (gdbscm_is_exception (scm_result));
139 1.1 christos *except_scmp = scm_result;
140 1.1 christos return NULL;
141 1.1 christos }
142 1.1 christos
143 1.1 christos /* Struct to pass data from gdbscm_scm_from_string to
144 1.1 christos gdbscm_call_scm_from_stringn. */
145 1.1 christos
146 1.1 christos struct scm_from_stringn_data
147 1.1 christos {
148 1.1 christos const char *string;
149 1.1 christos size_t len;
150 1.1 christos const char *charset;
151 1.4 christos scm_t_string_failed_conversion_handler conversion_kind;
152 1.1 christos SCM result;
153 1.1 christos };
154 1.1 christos
155 1.1 christos /* Helper for gdbscm_scm_from_string to call scm_from_stringn
156 1.1 christos from within scm_c_catch. */
157 1.1 christos
158 1.1 christos static SCM
159 1.1 christos gdbscm_call_scm_from_stringn (void *datap)
160 1.1 christos {
161 1.4 christos struct scm_from_stringn_data *data = (struct scm_from_stringn_data *) datap;
162 1.1 christos
163 1.1 christos data->result = scm_from_stringn (data->string, data->len, data->charset,
164 1.1 christos data->conversion_kind);
165 1.1 christos return SCM_BOOL_F;
166 1.1 christos }
167 1.1 christos
168 1.1 christos /* Convert STRING to a Scheme string in charset CHARSET.
169 1.1 christos This function is guaranteed to not throw an exception.
170 1.1 christos
171 1.1 christos If STRICT is non-zero, and there's a conversion error, then a
172 1.1 christos <gdb:exception> object is returned.
173 1.1 christos If STRICT is zero, then question marks are used for characters that
174 1.1 christos can't be converted (limitation of underlying Guile conversion support). */
175 1.1 christos
176 1.1 christos SCM
177 1.1 christos gdbscm_scm_from_string (const char *string, size_t len,
178 1.1 christos const char *charset, int strict)
179 1.1 christos {
180 1.1 christos struct scm_from_stringn_data data;
181 1.1 christos SCM scm_result;
182 1.1 christos
183 1.1 christos data.string = string;
184 1.1 christos data.len = len;
185 1.1 christos data.charset = charset;
186 1.1 christos /* The use of SCM_FAILED_CONVERSION_QUESTION_MARK is specified by Guile. */
187 1.1 christos data.conversion_kind = (strict
188 1.1 christos ? SCM_FAILED_CONVERSION_ERROR
189 1.1 christos : SCM_FAILED_CONVERSION_QUESTION_MARK);
190 1.1 christos data.result = SCM_UNDEFINED;
191 1.1 christos
192 1.1 christos scm_result = gdbscm_call_guile (gdbscm_call_scm_from_stringn, &data, NULL);
193 1.1 christos
194 1.1 christos if (gdbscm_is_false (scm_result))
195 1.1 christos {
196 1.1 christos gdb_assert (!SCM_UNBNDP (data.result));
197 1.1 christos return data.result;
198 1.1 christos }
199 1.1 christos gdb_assert (gdbscm_is_exception (scm_result));
200 1.1 christos return scm_result;
201 1.1 christos }
202 1.1 christos
203 1.1 christos /* Convert an SCM string to a host string.
204 1.1 christos This function is guaranteed to not throw an exception.
205 1.1 christos
206 1.1 christos If LENP is NULL then the returned string is NUL-terminated,
207 1.1 christos and if the string contains embedded NULs then NULL is returned with
208 1.1 christos an exception object stored in *EXCEPT_SCMP.
209 1.1 christos Otherwise the string is not guaranteed to be NUL-terminated, but worse
210 1.1 christos there's no space to put a NUL if we wanted to (scm_to_stringn limitation).
211 1.1 christos
212 1.1 christos Returns NULL if there is a conversion error, with the exception object
213 1.1 christos stored in *EXCEPT_SCMP.
214 1.1 christos It is an error to call this if STRING is not a string. */
215 1.1 christos
216 1.6 christos gdb::unique_xmalloc_ptr<char>
217 1.1 christos gdbscm_scm_to_host_string (SCM string, size_t *lenp, SCM *except_scmp)
218 1.1 christos {
219 1.1 christos return gdbscm_scm_to_string (string, lenp, host_charset (), 1, except_scmp);
220 1.1 christos }
221 1.1 christos
222 1.1 christos /* Convert a host string to an SCM string.
223 1.1 christos This function is guaranteed to not throw an exception.
224 1.1 christos Returns a <gdb:exception> object if there's a conversion error. */
225 1.1 christos
226 1.1 christos SCM
227 1.1 christos gdbscm_scm_from_host_string (const char *string, size_t len)
228 1.1 christos {
229 1.1 christos return gdbscm_scm_from_string (string, len, host_charset (), 1);
230 1.1 christos }
231 1.1 christos
232 1.1 christos /* (string->argv string) -> list
233 1.1 christos Return list of strings split up according to GDB's argv parsing rules.
234 1.1 christos This is useful when writing GDB commands in Scheme. */
235 1.1 christos
236 1.1 christos static SCM
237 1.1 christos gdbscm_string_to_argv (SCM string_scm)
238 1.1 christos {
239 1.1 christos char *string;
240 1.1 christos SCM result = SCM_EOL;
241 1.1 christos
242 1.1 christos gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, NULL, "s",
243 1.1 christos string_scm, &string);
244 1.1 christos
245 1.1 christos if (string == NULL || *string == '\0')
246 1.1 christos {
247 1.1 christos xfree (string);
248 1.1 christos return SCM_EOL;
249 1.1 christos }
250 1.1 christos
251 1.6 christos gdb_argv c_argv (string);
252 1.6 christos for (char *arg : c_argv)
253 1.6 christos result = scm_cons (gdbscm_scm_from_c_string (arg), result);
254 1.1 christos
255 1.1 christos xfree (string);
256 1.1 christos
257 1.1 christos return scm_reverse_x (result, SCM_EOL);
258 1.1 christos }
259 1.1 christos
260 1.1 christos /* Initialize the Scheme charset interface to GDB. */
262 1.1 christos
263 1.1 christos static const scheme_function string_functions[] =
264 1.4 christos {
265 1.1 christos { "string->argv", 1, 0, 0, as_a_scm_t_subr (gdbscm_string_to_argv),
266 1.1 christos "\
267 1.1 christos Convert a string to a list of strings split up according to\n\
268 1.1 christos gdb's argv parsing rules." },
269 1.1 christos
270 1.1 christos END_FUNCTIONS
271 1.1 christos };
272 1.1 christos
273 1.1 christos void
274 1.1 christos gdbscm_initialize_strings (void)
275 1.1 christos {
276 1.1 christos gdbscm_define_functions (string_functions, 1);
277 }
278