Home | History | Annotate | Line # | Download | only in guile
      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