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