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