Add some more casts (1/2)
[external/binutils.git] / gdb / guile / scm-string.c
1 /* GDB/Scheme charset interface.
2
3    Copyright (C) 2014-2015 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 \f
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 }