Home | History | Annotate | Line # | Download | only in guile
scm-utils.c revision 1.1.1.7
      1      1.1  christos /* General utility routines for GDB/Scheme code.
      2      1.1  christos 
      3  1.1.1.7  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 "guile-internal.h"
     25      1.1  christos 
     26      1.1  christos /* Define VARIABLES in the gdb module.  */
     27      1.1  christos 
     28      1.1  christos void
     29  1.1.1.2  christos gdbscm_define_variables (const scheme_variable *variables, int is_public)
     30      1.1  christos {
     31      1.1  christos   const scheme_variable *sv;
     32      1.1  christos 
     33      1.1  christos   for (sv = variables; sv->name != NULL; ++sv)
     34      1.1  christos     {
     35      1.1  christos       scm_c_define (sv->name, sv->value);
     36  1.1.1.2  christos       if (is_public)
     37      1.1  christos 	scm_c_export (sv->name, NULL);
     38      1.1  christos     }
     39      1.1  christos }
     40      1.1  christos 
     41      1.1  christos /* Define FUNCTIONS in the gdb module.  */
     42      1.1  christos 
     43      1.1  christos void
     44  1.1.1.2  christos gdbscm_define_functions (const scheme_function *functions, int is_public)
     45      1.1  christos {
     46      1.1  christos   const scheme_function *sf;
     47      1.1  christos 
     48      1.1  christos   for (sf = functions; sf->name != NULL; ++sf)
     49      1.1  christos     {
     50      1.1  christos       SCM proc = scm_c_define_gsubr (sf->name, sf->required, sf->optional,
     51      1.1  christos 				     sf->rest, sf->func);
     52      1.1  christos 
     53      1.1  christos       scm_set_procedure_property_x (proc, gdbscm_documentation_symbol,
     54      1.1  christos 				    gdbscm_scm_from_c_string (sf->doc_string));
     55  1.1.1.2  christos       if (is_public)
     56      1.1  christos 	scm_c_export (sf->name, NULL);
     57      1.1  christos     }
     58      1.1  christos }
     59      1.1  christos 
     60      1.1  christos /* Define CONSTANTS in the gdb module.  */
     61      1.1  christos 
     62      1.1  christos void
     63      1.1  christos gdbscm_define_integer_constants (const scheme_integer_constant *constants,
     64  1.1.1.2  christos 				 int is_public)
     65      1.1  christos {
     66      1.1  christos   const scheme_integer_constant *sc;
     67      1.1  christos 
     68      1.1  christos   for (sc = constants; sc->name != NULL; ++sc)
     69      1.1  christos     {
     70      1.1  christos       scm_c_define (sc->name, scm_from_int (sc->value));
     71  1.1.1.2  christos       if (is_public)
     72      1.1  christos 	scm_c_export (sc->name, NULL);
     73      1.1  christos     }
     74      1.1  christos }
     75      1.1  christos 
     76      1.1  christos /* scm_printf, alas it doesn't exist.  */
     78      1.1  christos 
     79      1.1  christos void
     80      1.1  christos gdbscm_printf (SCM port, const char *format, ...)
     81      1.1  christos {
     82      1.1  christos   va_list args;
     83      1.1  christos 
     84  1.1.1.5  christos   va_start (args, format);
     85      1.1  christos   std::string string = string_vprintf (format, args);
     86  1.1.1.5  christos   va_end (args);
     87      1.1  christos   scm_puts (string.c_str (), port);
     88      1.1  christos }
     89      1.1  christos 
     90      1.1  christos /* Utility for calling from gdb to "display" an SCM object.  */
     91      1.1  christos 
     92      1.1  christos void
     93      1.1  christos gdbscm_debug_display (SCM obj)
     94      1.1  christos {
     95      1.1  christos   SCM port = scm_current_output_port ();
     96      1.1  christos 
     97      1.1  christos   scm_display (obj, port);
     98      1.1  christos   scm_newline (port);
     99      1.1  christos   scm_force_output (port);
    100      1.1  christos }
    101      1.1  christos 
    102      1.1  christos /* Utility for calling from gdb to "write" an SCM object.  */
    103      1.1  christos 
    104      1.1  christos void
    105      1.1  christos gdbscm_debug_write (SCM obj)
    106      1.1  christos {
    107      1.1  christos   SCM port = scm_current_output_port ();
    108      1.1  christos 
    109      1.1  christos   scm_write (obj, port);
    110      1.1  christos   scm_newline (port);
    111      1.1  christos   scm_force_output (port);
    112      1.1  christos }
    113      1.1  christos 
    114      1.1  christos /* Subroutine of gdbscm_parse_function_args to simplify it.
    116      1.1  christos    Return the number of keyword arguments.  */
    117      1.1  christos 
    118      1.1  christos static int
    119      1.1  christos count_keywords (const SCM *keywords)
    120      1.1  christos {
    121      1.1  christos   int i;
    122      1.1  christos 
    123      1.1  christos   if (keywords == NULL)
    124      1.1  christos     return 0;
    125      1.1  christos   for (i = 0; keywords[i] != SCM_BOOL_F; ++i)
    126      1.1  christos     continue;
    127      1.1  christos 
    128      1.1  christos   return i;
    129      1.1  christos }
    130      1.1  christos 
    131      1.1  christos /* Subroutine of gdbscm_parse_function_args to simplify it.
    132      1.1  christos    Validate an argument format string.
    133      1.1  christos    The result is a boolean indicating if "." was seen.  */
    134      1.1  christos 
    135      1.1  christos static int
    136      1.1  christos validate_arg_format (const char *format)
    137      1.1  christos {
    138      1.1  christos   const char *p;
    139      1.1  christos   int length = strlen (format);
    140      1.1  christos   int optional_position = -1;
    141      1.1  christos   int keyword_position = -1;
    142      1.1  christos   int dot_seen = 0;
    143      1.1  christos 
    144      1.1  christos   gdb_assert (length > 0);
    145      1.1  christos 
    146      1.1  christos   for (p = format; *p != '\0'; ++p)
    147      1.1  christos     {
    148      1.1  christos       switch (*p)
    149      1.1  christos 	{
    150      1.1  christos 	case 's':
    151      1.1  christos 	case 't':
    152      1.1  christos 	case 'i':
    153      1.1  christos 	case 'u':
    154      1.1  christos 	case 'l':
    155      1.1  christos 	case 'n':
    156      1.1  christos 	case 'L':
    157      1.1  christos 	case 'U':
    158      1.1  christos 	case 'O':
    159      1.1  christos 	  break;
    160      1.1  christos 	case '|':
    161      1.1  christos 	  gdb_assert (keyword_position < 0);
    162      1.1  christos 	  gdb_assert (optional_position < 0);
    163      1.1  christos 	  optional_position = p - format;
    164      1.1  christos 	  break;
    165      1.1  christos 	case '#':
    166      1.1  christos 	  gdb_assert (keyword_position < 0);
    167      1.1  christos 	  keyword_position = p - format;
    168      1.1  christos 	  break;
    169      1.1  christos 	case '.':
    170      1.1  christos 	  gdb_assert (p[1] == '\0');
    171      1.1  christos 	  dot_seen = 1;
    172      1.1  christos 	  break;
    173      1.1  christos 	default:
    174      1.1  christos 	  gdb_assert_not_reached ("invalid argument format character");
    175      1.1  christos 	}
    176      1.1  christos     }
    177      1.1  christos 
    178      1.1  christos   return dot_seen;
    179      1.1  christos }
    180      1.1  christos 
    181      1.1  christos /* Our version of SCM_ASSERT_TYPE that calls gdbscm_make_type_error.  */
    182      1.1  christos #define CHECK_TYPE(ok, arg, position, func_name, expected_type)		\
    183      1.1  christos   do {									\
    184      1.1  christos     if (!(ok))								\
    185      1.1  christos       {									\
    186      1.1  christos 	return gdbscm_make_type_error ((func_name), (position), (arg),	\
    187      1.1  christos 				       (expected_type));		\
    188      1.1  christos       }									\
    189      1.1  christos   } while (0)
    190      1.1  christos 
    191      1.1  christos /* Subroutine of gdbscm_parse_function_args to simplify it.
    192      1.1  christos    Check the type of ARG against FORMAT_CHAR and extract the value.
    193      1.1  christos    POSITION is the position of ARG in the argument list.
    194      1.1  christos    The result is #f upon success or a <gdb:exception> object.  */
    195      1.1  christos 
    196      1.1  christos static SCM
    197      1.1  christos extract_arg (char format_char, SCM arg, void *argp,
    198      1.1  christos 	     const char *func_name, int position)
    199      1.1  christos {
    200      1.1  christos   switch (format_char)
    201      1.1  christos     {
    202  1.1.1.3  christos     case 's':
    203      1.1  christos       {
    204      1.1  christos 	char **arg_ptr = (char **) argp;
    205      1.1  christos 
    206  1.1.1.5  christos 	CHECK_TYPE (gdbscm_is_true (scm_string_p (arg)), arg, position,
    207      1.1  christos 		    func_name, _("string"));
    208      1.1  christos 	*arg_ptr = gdbscm_scm_to_c_string (arg).release ();
    209      1.1  christos 	break;
    210      1.1  christos       }
    211  1.1.1.3  christos     case 't':
    212      1.1  christos       {
    213      1.1  christos 	int *arg_ptr = (int *) argp;
    214      1.1  christos 
    215      1.1  christos 	/* While in Scheme, anything non-#f is "true", we're strict.  */
    216      1.1  christos 	CHECK_TYPE (gdbscm_is_bool (arg), arg, position, func_name,
    217      1.1  christos 		    _("boolean"));
    218      1.1  christos 	*arg_ptr = gdbscm_is_true (arg);
    219      1.1  christos 	break;
    220      1.1  christos       }
    221  1.1.1.3  christos     case 'i':
    222      1.1  christos       {
    223      1.1  christos 	int *arg_ptr = (int *) argp;
    224      1.1  christos 
    225      1.1  christos 	CHECK_TYPE (scm_is_signed_integer (arg, INT_MIN, INT_MAX),
    226      1.1  christos 		    arg, position, func_name, _("int"));
    227      1.1  christos 	*arg_ptr = scm_to_int (arg);
    228      1.1  christos 	break;
    229      1.1  christos       }
    230  1.1.1.3  christos     case 'u':
    231      1.1  christos       {
    232      1.1  christos 	int *arg_ptr = (int *) argp;
    233      1.1  christos 
    234      1.1  christos 	CHECK_TYPE (scm_is_unsigned_integer (arg, 0, UINT_MAX),
    235      1.1  christos 		    arg, position, func_name, _("unsigned int"));
    236      1.1  christos 	*arg_ptr = scm_to_uint (arg);
    237      1.1  christos 	break;
    238      1.1  christos       }
    239  1.1.1.3  christos     case 'l':
    240      1.1  christos       {
    241      1.1  christos 	long *arg_ptr = (long *) argp;
    242      1.1  christos 
    243      1.1  christos 	CHECK_TYPE (scm_is_signed_integer (arg, LONG_MIN, LONG_MAX),
    244      1.1  christos 		    arg, position, func_name, _("long"));
    245      1.1  christos 	*arg_ptr = scm_to_long (arg);
    246      1.1  christos 	break;
    247      1.1  christos       }
    248  1.1.1.3  christos     case 'n':
    249      1.1  christos       {
    250      1.1  christos 	unsigned long *arg_ptr = (unsigned long *) argp;
    251      1.1  christos 
    252      1.1  christos 	CHECK_TYPE (scm_is_unsigned_integer (arg, 0, ULONG_MAX),
    253      1.1  christos 		    arg, position, func_name, _("unsigned long"));
    254      1.1  christos 	*arg_ptr = scm_to_ulong (arg);
    255      1.1  christos 	break;
    256      1.1  christos       }
    257  1.1.1.3  christos     case 'L':
    258      1.1  christos       {
    259      1.1  christos 	LONGEST *arg_ptr = (LONGEST *) argp;
    260      1.1  christos 
    261      1.1  christos 	CHECK_TYPE (scm_is_signed_integer (arg, INT64_MIN, INT64_MAX),
    262      1.1  christos 		    arg, position, func_name, _("LONGEST"));
    263      1.1  christos 	*arg_ptr = gdbscm_scm_to_longest (arg);
    264      1.1  christos 	break;
    265      1.1  christos       }
    266  1.1.1.3  christos     case 'U':
    267      1.1  christos       {
    268      1.1  christos 	ULONGEST *arg_ptr = (ULONGEST *) argp;
    269      1.1  christos 
    270      1.1  christos 	CHECK_TYPE (scm_is_unsigned_integer (arg, 0, UINT64_MAX),
    271      1.1  christos 		    arg, position, func_name, _("ULONGEST"));
    272      1.1  christos 	*arg_ptr = gdbscm_scm_to_ulongest (arg);
    273      1.1  christos 	break;
    274      1.1  christos       }
    275  1.1.1.3  christos     case 'O':
    276      1.1  christos       {
    277      1.1  christos 	SCM *arg_ptr = (SCM *) argp;
    278      1.1  christos 
    279      1.1  christos 	*arg_ptr = arg;
    280      1.1  christos 	break;
    281      1.1  christos       }
    282      1.1  christos     default:
    283      1.1  christos       gdb_assert_not_reached ("invalid argument format character");
    284      1.1  christos     }
    285      1.1  christos 
    286      1.1  christos   return SCM_BOOL_F;
    287      1.1  christos }
    288      1.1  christos 
    289      1.1  christos #undef CHECK_TYPE
    290      1.1  christos 
    291      1.1  christos /* Look up KEYWORD in KEYWORD_LIST.
    292      1.1  christos    The result is the index of the keyword in the list or -1 if not found.  */
    293      1.1  christos 
    294      1.1  christos static int
    295      1.1  christos lookup_keyword (const SCM *keyword_list, SCM keyword)
    296      1.1  christos {
    297      1.1  christos   int i = 0;
    298      1.1  christos 
    299      1.1  christos   while (keyword_list[i] != SCM_BOOL_F)
    300      1.1  christos     {
    301      1.1  christos       if (scm_is_eq (keyword_list[i], keyword))
    302      1.1  christos 	return i;
    303      1.1  christos       ++i;
    304      1.1  christos     }
    305      1.1  christos 
    306      1.1  christos   return -1;
    307      1.1  christos }
    308  1.1.1.5  christos 
    309  1.1.1.5  christos 
    310  1.1.1.5  christos /* Helper for gdbscm_parse_function_args that does most of the work,
    311  1.1.1.5  christos    in a separate function wrapped with gdbscm_wrap so that we can use
    312      1.1  christos    non-trivial-dtor objects here.  The result is #f upon success or a
    313  1.1.1.5  christos    <gdb:exception> object otherwise.  */
    314  1.1.1.5  christos 
    315  1.1.1.5  christos static SCM
    316  1.1.1.5  christos gdbscm_parse_function_args_1 (const char *func_name,
    317  1.1.1.5  christos 			      int beginning_arg_pos,
    318      1.1  christos 			      const SCM *keywords,
    319      1.1  christos 			      const char *format, va_list args)
    320  1.1.1.5  christos {
    321      1.1  christos   const char *p;
    322      1.1  christos   int i, have_rest, num_keywords, position;
    323      1.1  christos   int have_optional = 0;
    324      1.1  christos   SCM status;
    325  1.1.1.5  christos   SCM rest = SCM_EOL;
    326      1.1  christos   /* Keep track of malloc'd strings.  We need to free them upon error.  */
    327      1.1  christos   std::vector<char *> allocated_strings;
    328      1.1  christos 
    329      1.1  christos   have_rest = validate_arg_format (format);
    330      1.1  christos   num_keywords = count_keywords (keywords);
    331      1.1  christos 
    332      1.1  christos   p = format;
    333      1.1  christos   position = beginning_arg_pos;
    334      1.1  christos 
    335      1.1  christos   /* Process required, optional arguments.  */
    336      1.1  christos 
    337      1.1  christos   while (*p && *p != '#' && *p != '.')
    338      1.1  christos     {
    339      1.1  christos       SCM arg;
    340      1.1  christos       void *arg_ptr;
    341      1.1  christos 
    342      1.1  christos       if (*p == '|')
    343      1.1  christos 	{
    344      1.1  christos 	  have_optional = 1;
    345      1.1  christos 	  ++p;
    346      1.1  christos 	  continue;
    347      1.1  christos 	}
    348      1.1  christos 
    349      1.1  christos       arg = va_arg (args, SCM);
    350      1.1  christos       if (!have_optional || !SCM_UNBNDP (arg))
    351      1.1  christos 	{
    352      1.1  christos 	  arg_ptr = va_arg (args, void *);
    353      1.1  christos 	  status = extract_arg (*p, arg, arg_ptr, func_name, position);
    354      1.1  christos 	  if (!gdbscm_is_false (status))
    355  1.1.1.5  christos 	    goto fail;
    356      1.1  christos 	  if (*p == 's')
    357      1.1  christos 	    allocated_strings.push_back (*(char **) arg_ptr);
    358      1.1  christos 	}
    359      1.1  christos       ++p;
    360      1.1  christos       ++position;
    361      1.1  christos     }
    362      1.1  christos 
    363      1.1  christos   /* Process keyword arguments.  */
    364      1.1  christos 
    365      1.1  christos   if (have_rest || num_keywords > 0)
    366      1.1  christos     rest = va_arg (args, SCM);
    367      1.1  christos 
    368  1.1.1.3  christos   if (num_keywords > 0)
    369  1.1.1.3  christos     {
    370      1.1  christos       SCM *keyword_args = XALLOCAVEC (SCM, num_keywords);
    371      1.1  christos       int *keyword_positions = XALLOCAVEC (int, num_keywords);
    372      1.1  christos 
    373      1.1  christos       gdb_assert (*p == '#');
    374      1.1  christos       ++p;
    375      1.1  christos 
    376      1.1  christos       for (i = 0; i < num_keywords; ++i)
    377      1.1  christos 	{
    378      1.1  christos 	  keyword_args[i] = SCM_UNSPECIFIED;
    379      1.1  christos 	  keyword_positions[i] = -1;
    380      1.1  christos 	}
    381      1.1  christos 
    382      1.1  christos       while (scm_is_pair (rest)
    383      1.1  christos 	     && scm_is_keyword (scm_car (rest)))
    384      1.1  christos 	{
    385      1.1  christos 	  SCM keyword = scm_car (rest);
    386      1.1  christos 
    387      1.1  christos 	  i = lookup_keyword (keywords, keyword);
    388      1.1  christos 	  if (i < 0)
    389      1.1  christos 	    {
    390      1.1  christos 	      status = gdbscm_make_error (scm_arg_type_key, func_name,
    391      1.1  christos 					  _("Unrecognized keyword: ~a"),
    392      1.1  christos 					  scm_list_1 (keyword), keyword);
    393      1.1  christos 	      goto fail;
    394      1.1  christos 	    }
    395      1.1  christos 	  if (!scm_is_pair (scm_cdr (rest)))
    396      1.1  christos 	    {
    397      1.1  christos 	      status = gdbscm_make_error
    398      1.1  christos 		(scm_arg_type_key, func_name,
    399      1.1  christos 		 _("Missing value for keyword argument"),
    400      1.1  christos 		 scm_list_1 (keyword), keyword);
    401      1.1  christos 	      goto fail;
    402      1.1  christos 	    }
    403      1.1  christos 	  keyword_args[i] = scm_cadr (rest);
    404      1.1  christos 	  keyword_positions[i] = position + 1;
    405      1.1  christos 	  rest = scm_cddr (rest);
    406      1.1  christos 	  position += 2;
    407      1.1  christos 	}
    408      1.1  christos 
    409      1.1  christos       for (i = 0; i < num_keywords; ++i)
    410      1.1  christos 	{
    411      1.1  christos 	  int *arg_pos_ptr = va_arg (args, int *);
    412      1.1  christos 	  void *arg_ptr = va_arg (args, void *);
    413      1.1  christos 	  SCM arg = keyword_args[i];
    414      1.1  christos 
    415      1.1  christos 	  if (! scm_is_eq (arg, SCM_UNSPECIFIED))
    416      1.1  christos 	    {
    417      1.1  christos 	      *arg_pos_ptr = keyword_positions[i];
    418      1.1  christos 	      status = extract_arg (p[i], arg, arg_ptr, func_name,
    419      1.1  christos 				    keyword_positions[i]);
    420      1.1  christos 	      if (!gdbscm_is_false (status))
    421  1.1.1.5  christos 		goto fail;
    422      1.1  christos 	      if (p[i] == 's')
    423      1.1  christos 		allocated_strings.push_back (*(char **) arg_ptr);
    424      1.1  christos 	    }
    425      1.1  christos 	}
    426      1.1  christos     }
    427      1.1  christos 
    428      1.1  christos   /* Process "rest" arguments.  */
    429      1.1  christos 
    430      1.1  christos   if (have_rest)
    431      1.1  christos     {
    432      1.1  christos       if (num_keywords > 0)
    433      1.1  christos 	{
    434      1.1  christos 	  SCM *rest_ptr = va_arg (args, SCM *);
    435      1.1  christos 
    436      1.1  christos 	  *rest_ptr = rest;
    437      1.1  christos 	}
    438      1.1  christos     }
    439      1.1  christos   else
    440      1.1  christos     {
    441      1.1  christos       if (! scm_is_null (rest))
    442      1.1  christos 	{
    443      1.1  christos 	  status = gdbscm_make_error (scm_args_number_key, func_name,
    444      1.1  christos 				      _("Too many arguments"),
    445      1.1  christos 				      SCM_EOL, SCM_BOOL_F);
    446      1.1  christos 	  goto fail;
    447      1.1  christos 	}
    448  1.1.1.5  christos     }
    449  1.1.1.5  christos 
    450      1.1  christos   /* Return anything not-an-exception.  */
    451      1.1  christos   return SCM_BOOL_F;
    452  1.1.1.5  christos 
    453      1.1  christos  fail:
    454  1.1.1.5  christos   for (char *ptr : allocated_strings)
    455  1.1.1.5  christos     xfree (ptr);
    456  1.1.1.5  christos 
    457  1.1.1.5  christos   /* Return the exception, which gdbscm_wrap takes care of
    458      1.1  christos      throwing.  */
    459  1.1.1.5  christos   return status;
    460  1.1.1.5  christos }
    461  1.1.1.5  christos 
    462  1.1.1.5  christos /* Utility to parse required, optional, and keyword arguments to Scheme
    463  1.1.1.5  christos    functions.  Modelled on PyArg_ParseTupleAndKeywords, but no attempt is made
    464  1.1.1.5  christos    at similarity or functionality.
    465  1.1.1.5  christos    There is no result, if there's an error a Scheme exception is thrown.
    466  1.1.1.5  christos 
    467  1.1.1.5  christos    Guile provides scm_c_bind_keyword_arguments, and feel free to use it.
    468  1.1.1.5  christos    This is for times when we want a bit more parsing.
    469  1.1.1.5  christos 
    470  1.1.1.5  christos    BEGINNING_ARG_POS is the position of the first argument passed to this
    471  1.1.1.5  christos    routine.  It should be one of the SCM_ARGn values.  It could be > SCM_ARG1
    472  1.1.1.5  christos    if the caller chooses not to parse one or more required arguments.
    473  1.1.1.5  christos 
    474  1.1.1.5  christos    KEYWORDS may be NULL if there are no keywords.
    475  1.1.1.5  christos 
    476  1.1.1.5  christos    FORMAT:
    477  1.1.1.5  christos    s - string -> char *, malloc'd
    478  1.1.1.5  christos    t - boolean (gdb uses "t", for biT?) -> int
    479  1.1.1.5  christos    i - int
    480  1.1.1.5  christos    u - unsigned int
    481  1.1.1.5  christos    l - long
    482  1.1.1.5  christos    n - unsigned long
    483  1.1.1.5  christos    L - longest
    484  1.1.1.5  christos    U - unsigned longest
    485  1.1.1.5  christos    O - random scheme object
    486  1.1.1.5  christos    | - indicates the next set is for optional arguments
    487  1.1.1.5  christos    # - indicates the next set is for keyword arguments (must follow |)
    488  1.1.1.5  christos    . - indicates "rest" arguments are present, this character must appear last
    489  1.1.1.5  christos 
    490  1.1.1.5  christos    FORMAT must match the definition from scm_c_{make,define}_gsubr.
    491  1.1.1.5  christos    Required and optional arguments appear in order in the format string.
    492  1.1.1.5  christos    Afterwards, keyword-based arguments are processed.  There must be as many
    493  1.1.1.5  christos    remaining characters in the format string as their are keywords.
    494  1.1.1.5  christos    Except for "|#.", the number of characters in the format string must match
    495  1.1.1.5  christos    #required + #optional + #keywords.
    496  1.1.1.5  christos 
    497  1.1.1.5  christos    The function is required to be defined in a compatible manner:
    498  1.1.1.5  christos    #required-args and #optional-arguments must match, and rest-arguments
    499  1.1.1.5  christos    must be specified if keyword args are desired, and/or regular "rest" args.
    500  1.1.1.5  christos 
    501  1.1.1.5  christos    Example:  For this function,
    502  1.1.1.5  christos    scm_c_define_gsubr ("execute", 2, 3, 1, foo);
    503  1.1.1.5  christos    the format string + keyword list could be any of:
    504  1.1.1.5  christos    1) "ss|ttt#tt", { "key1", "key2", NULL }
    505  1.1.1.5  christos    2) "ss|ttt.", { NULL }
    506  1.1.1.5  christos    3) "ss|ttt#t.", { "key1", NULL }
    507  1.1.1.5  christos 
    508  1.1.1.5  christos    For required and optional args pass the SCM of the argument, and a
    509  1.1.1.5  christos    pointer to the value to hold the parsed result (type depends on format
    510  1.1.1.5  christos    char).  After that pass the SCM containing the "rest" arguments followed
    511  1.1.1.5  christos    by pointers to values to hold parsed keyword arguments, and if specified
    512  1.1.1.5  christos    a pointer to hold the remaining contents of "rest".
    513  1.1.1.5  christos 
    514  1.1.1.5  christos    For keyword arguments pass two pointers: the first is a pointer to an int
    515  1.1.1.5  christos    that will contain the position of the argument in the arg list, and the
    516  1.1.1.5  christos    second will contain result of processing the argument.  The int pointed
    517  1.1.1.5  christos    to by the first value should be initialized to -1.  It can then be used
    518  1.1.1.5  christos    to tell whether the keyword was present.
    519  1.1.1.5  christos 
    520  1.1.1.5  christos    If both keyword and rest arguments are present, the caller must pass a
    521  1.1.1.5  christos    pointer to contain the new value of rest (after keyword args have been
    522  1.1.1.5  christos    removed).
    523  1.1.1.5  christos 
    524  1.1.1.5  christos    There's currently no way, that I know of, to specify default values for
    525  1.1.1.5  christos    optional arguments in C-provided functions.  At the moment they're a
    526  1.1.1.5  christos    work-in-progress.  The caller should test SCM_UNBNDP for each optional
    527  1.1.1.5  christos    argument.  Unbound optional arguments are ignored.  */
    528  1.1.1.5  christos 
    529  1.1.1.5  christos void
    530  1.1.1.5  christos gdbscm_parse_function_args (const char *func_name,
    531  1.1.1.5  christos 			    int beginning_arg_pos,
    532  1.1.1.5  christos 			    const SCM *keywords,
    533  1.1.1.5  christos 			    const char *format, ...)
    534  1.1.1.5  christos {
    535  1.1.1.5  christos   va_list args;
    536  1.1.1.5  christos   va_start (args, format);
    537  1.1.1.5  christos 
    538  1.1.1.5  christos   gdbscm_wrap (gdbscm_parse_function_args_1, func_name,
    539  1.1.1.5  christos 	       beginning_arg_pos, keywords, format, args);
    540  1.1.1.5  christos 
    541  1.1.1.5  christos   va_end (args);
    542      1.1  christos }
    543      1.1  christos 
    544      1.1  christos 
    545      1.1  christos /* Return longest L as a scheme object.  */
    547      1.1  christos 
    548      1.1  christos SCM
    549      1.1  christos gdbscm_scm_from_longest (LONGEST l)
    550      1.1  christos {
    551      1.1  christos   return scm_from_int64 (l);
    552      1.1  christos }
    553      1.1  christos 
    554      1.1  christos /* Convert scheme object L to LONGEST.
    555      1.1  christos    It is an error to call this if L is not an integer in range of LONGEST.
    556      1.1  christos    (because the underlying Scheme function will thrown an exception,
    557      1.1  christos    which is not part of our contract with the caller).  */
    558      1.1  christos 
    559      1.1  christos LONGEST
    560      1.1  christos gdbscm_scm_to_longest (SCM l)
    561      1.1  christos {
    562      1.1  christos   return scm_to_int64 (l);
    563      1.1  christos }
    564      1.1  christos 
    565      1.1  christos /* Return unsigned longest L as a scheme object.  */
    566      1.1  christos 
    567      1.1  christos SCM
    568      1.1  christos gdbscm_scm_from_ulongest (ULONGEST l)
    569      1.1  christos {
    570      1.1  christos   return scm_from_uint64 (l);
    571      1.1  christos }
    572      1.1  christos 
    573      1.1  christos /* Convert scheme object U to ULONGEST.
    574      1.1  christos    It is an error to call this if U is not an integer in range of ULONGEST
    575      1.1  christos    (because the underlying Scheme function will thrown an exception,
    576      1.1  christos    which is not part of our contract with the caller).  */
    577      1.1  christos 
    578      1.1  christos ULONGEST
    579      1.1  christos gdbscm_scm_to_ulongest (SCM u)
    580      1.1  christos {
    581      1.1  christos   return scm_to_uint64 (u);
    582      1.1  christos }
    583      1.1  christos 
    584      1.1  christos /* Same as scm_dynwind_free, but uses xfree.  */
    585      1.1  christos 
    586      1.1  christos void
    587      1.1  christos gdbscm_dynwind_xfree (void *ptr)
    588      1.1  christos {
    589      1.1  christos   scm_dynwind_unwind_handler (xfree, ptr, SCM_F_WIND_EXPLICITLY);
    590      1.1  christos }
    591      1.1  christos 
    592      1.1  christos /* Return non-zero if PROC is a procedure.  */
    593      1.1  christos 
    594      1.1  christos int
    595      1.1  christos gdbscm_is_procedure (SCM proc)
    596      1.1  christos {
    597      1.1  christos   return gdbscm_is_true (scm_procedure_p (proc));
    598      1.1  christos }
    599      1.1  christos 
    600      1.1  christos /* Same as xstrdup, but the string is allocated on the GC heap.  */
    601      1.1  christos 
    602      1.1  christos char *
    603  1.1.1.3  christos gdbscm_gc_xstrdup (const char *str)
    604  1.1.1.3  christos {
    605      1.1  christos   size_t len = strlen (str);
    606      1.1  christos   char *result
    607      1.1  christos     = (char *) scm_gc_malloc_pointerless (len + 1, "gdbscm_gc_xstrdup");
    608      1.1  christos 
    609      1.1  christos   strcpy (result, str);
    610      1.1  christos   return result;
    611      1.1  christos }
    612      1.1  christos 
    613      1.1  christos /* Return a duplicate of ARGV living on the GC heap.  */
    614      1.1  christos 
    615      1.1  christos const char * const *
    616      1.1  christos gdbscm_gc_dup_argv (char **argv)
    617      1.1  christos {
    618      1.1  christos   int i, len;
    619      1.1  christos   size_t string_space;
    620      1.1  christos   char *p, **result;
    621      1.1  christos 
    622      1.1  christos   for (len = 0, string_space = 0; argv[len] != NULL; ++len)
    623      1.1  christos     string_space += strlen (argv[len]) + 1;
    624  1.1.1.3  christos 
    625  1.1.1.3  christos   /* Allocating "pointerless" works because the pointers are all
    626  1.1.1.3  christos      self-contained within the object.  */
    627      1.1  christos   result = (char **) scm_gc_malloc_pointerless (((len + 1) * sizeof (char *))
    628      1.1  christos 						+ string_space,
    629      1.1  christos 						"parameter enum list");
    630      1.1  christos   p = (char *) &result[len + 1];
    631      1.1  christos 
    632      1.1  christos   for (i = 0; i < len; ++i)
    633      1.1  christos     {
    634      1.1  christos       result[i] = p;
    635      1.1  christos       strcpy (p, argv[i]);
    636      1.1  christos       p += strlen (p) + 1;
    637      1.1  christos     }
    638      1.1  christos   result[i] = NULL;
    639      1.1  christos 
    640      1.1  christos   return (const char * const *) result;
    641      1.1  christos }
    642      1.1  christos 
    643      1.1  christos /* Return non-zero if the version of Guile being used it at least
    644      1.1  christos    MAJOR.MINOR.MICRO.  */
    645      1.1  christos 
    646      1.1  christos int
    647      1.1  christos gdbscm_guile_version_is_at_least (int major, int minor, int micro)
    648      1.1  christos {
    649      1.1  christos   if (major > gdbscm_guile_major_version)
    650      1.1  christos     return 0;
    651      1.1  christos   if (major < gdbscm_guile_major_version)
    652      1.1  christos     return 1;
    653      1.1  christos   if (minor > gdbscm_guile_minor_version)
    654      1.1  christos     return 0;
    655      1.1  christos   if (minor < gdbscm_guile_minor_version)
    656      1.1  christos     return 1;
    657      1.1  christos   if (micro > gdbscm_guile_micro_version)
    658                        return 0;
    659                      return 1;
    660                    }
    661