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