1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-07-03 08:10:31 +02:00

Move string-pointer-array handling to posix.c

* libguile/posix.c (free_string_pointers):
(free_string_pointers_on_unwind):
(allocate_string_pointers): Move here from string.c, and use malloc/free
instead of GC facilities. Adapt all users.
* libguile/strings.h:
* libguile/strings.c (scm_i_allocate_string_pointers): Remove.
This commit is contained in:
Andy Wingo 2025-06-20 09:48:43 +02:00
parent ce2f7847e8
commit a793d371cd
3 changed files with 65 additions and 55 deletions

View file

@ -1138,6 +1138,55 @@ SCM_DEFINE (scm_tcsetpgrp, "tcsetpgrp", 2, 0, 0,
#undef FUNC_NAME #undef FUNC_NAME
#endif /* HAVE_TCSETPGRP */ #endif /* HAVE_TCSETPGRP */
/* Return a newly allocated array of char pointers to each of the strings
in args, with a terminating NULL pointer. The strings are encoded using
the current locale. */
static void
free_string_pointers (char **pointers)
{
for (char **walk = pointers; *walk; walk++)
free (*walk);
free (pointers);
}
static void
free_string_pointers_on_unwind (void *data)
{
free_string_pointers (data);
}
static char **
allocate_string_pointers (SCM list)
{
int list_len = scm_ilength (list);
int i;
if (list_len < 0)
scm_wrong_type_arg_msg (NULL, 0, list, "proper list");
char **result = scm_calloc ((list_len + 1) * sizeof (char *));
scm_dynwind_begin (0);
scm_dynwind_unwind_handler (free_string_pointers_on_unwind, result, 0);
for (i = 0; i < list_len; i++, list = scm_cdr (list))
{
SCM str = scm_car (list);
size_t len; /* String length in bytes */
char *c_str = scm_to_locale_stringn (str, &len);
result[i] = malloc (len + 1);
memcpy (result[i], c_str, len);
result[i][len] = '\0';
free (c_str);
}
scm_dynwind_end ();
return result;
}
SCM_DEFINE (scm_execl, "execl", 1, 0, 1, SCM_DEFINE (scm_execl, "execl", 1, 0, 1,
(SCM filename, SCM args), (SCM filename, SCM args),
"Executes the file named by @var{filename} as a new process image.\n" "Executes the file named by @var{filename} as a new process image.\n"
@ -1159,7 +1208,7 @@ SCM_DEFINE (scm_execl, "execl", 1, 0, 1,
exec_file = scm_to_locale_string (filename); exec_file = scm_to_locale_string (filename);
scm_dynwind_free (exec_file); scm_dynwind_free (exec_file);
exec_argv = scm_i_allocate_string_pointers (args); exec_argv = allocate_string_pointers (args);
#ifdef __MINGW32__ #ifdef __MINGW32__
execv (exec_file, (const char * const *)exec_argv); execv (exec_file, (const char * const *)exec_argv);
@ -1192,7 +1241,7 @@ SCM_DEFINE (scm_execlp, "execlp", 1, 0, 1,
exec_file = scm_to_locale_string (filename); exec_file = scm_to_locale_string (filename);
scm_dynwind_free (exec_file); scm_dynwind_free (exec_file);
exec_argv = scm_i_allocate_string_pointers (args); exec_argv = allocate_string_pointers (args);
#ifdef __MINGW32__ #ifdef __MINGW32__
execvp (exec_file, (const char * const *)exec_argv); execvp (exec_file, (const char * const *)exec_argv);
@ -1229,8 +1278,8 @@ SCM_DEFINE (scm_execle, "execle", 2, 0, 1,
exec_file = scm_to_locale_string (filename); exec_file = scm_to_locale_string (filename);
scm_dynwind_free (exec_file); scm_dynwind_free (exec_file);
exec_argv = scm_i_allocate_string_pointers (args); exec_argv = allocate_string_pointers (args);
exec_env = scm_i_allocate_string_pointers (env); exec_env = allocate_string_pointers (env);
#ifdef __MINGW32__ #ifdef __MINGW32__
execve (exec_file, (const char * const *) exec_argv, (const char * const *) exec_env); execve (exec_file, (const char * const *) exec_argv, (const char * const *) exec_env);
@ -1474,12 +1523,18 @@ SCM_DEFINE (scm_spawn_process, "spawn", 2, 0, 1,
exec_file = scm_to_locale_string (program); exec_file = scm_to_locale_string (program);
scm_dynwind_free (exec_file); scm_dynwind_free (exec_file);
exec_argv = scm_i_allocate_string_pointers (arguments); exec_argv = allocate_string_pointers (arguments);
scm_dynwind_unwind_handler (free_string_pointers_on_unwind, exec_argv,
SCM_F_WIND_EXPLICITLY);
if (SCM_UNBNDP (env)) if (SCM_UNBNDP (env))
exec_env = environ; exec_env = environ;
else else
exec_env = scm_i_allocate_string_pointers (env); {
exec_env = allocate_string_pointers (env);
scm_dynwind_unwind_handler (free_string_pointers_on_unwind, exec_env,
SCM_F_WIND_EXPLICITLY);
}
if (SCM_UNBNDP (in_scm)) if (SCM_UNBNDP (in_scm))
in_scm = scm_current_input_port (); in_scm = scm_current_input_port ();
@ -1530,7 +1585,7 @@ piped_process (pid_t *pid, SCM prog, SCM args, SCM from, SCM to)
char **exec_env = environ; char **exec_env = environ;
exec_file = scm_to_locale_string (prog); exec_file = scm_to_locale_string (prog);
exec_argv = scm_i_allocate_string_pointers (scm_cons (prog, args)); exec_argv = allocate_string_pointers (scm_cons (prog, args));
reading = scm_is_pair (from); reading = scm_is_pair (from);
writing = scm_is_pair (to); writing = scm_is_pair (to);
@ -1575,6 +1630,8 @@ piped_process (pid_t *pid, SCM prog, SCM args, SCM from, SCM to)
*pid = do_spawn (exec_file, exec_argv, exec_env, in, out, err, 1); *pid = do_spawn (exec_file, exec_argv, exec_env, in, out, err, 1);
int errno_save = (*pid < 0) ? errno : 0; int errno_save = (*pid < 0) ? errno : 0;
free_string_pointers (exec_argv);
if (reading) if (reading)
close (c2p[1]); close (c2p[1]);
if (writing) if (writing)

View file

@ -2430,52 +2430,6 @@ scm_makfromstrs (int argc, char **argv)
return lst; return lst;
} }
/* Return a newly allocated array of char pointers to each of the strings
in args, with a terminating NULL pointer. The strings are encoded using
the current locale. */
char **
scm_i_allocate_string_pointers (SCM list)
#define FUNC_NAME "scm_i_allocate_string_pointers"
{
char **result;
int list_len = scm_ilength (list);
int i;
if (list_len < 0)
scm_wrong_type_arg_msg (NULL, 0, list, "proper list");
result = scm_gc_malloc ((list_len + 1) * sizeof (char *),
"string pointers");
result[list_len] = NULL;
/* The list might have been modified in another thread, so
we check LIST before each access.
*/
for (i = 0; i < list_len && scm_is_pair (list); i++)
{
SCM str = SCM_CAR (list);
size_t len; /* String length in bytes */
char *c_str = scm_to_locale_stringn (str, &len);
/* OPTIMIZE-ME: Right now, scm_to_locale_stringn always uses
scm_malloc to allocate the returned string, which must be
explicitly deallocated. This forces us to copy the string a
second time into a new buffer. Ideally there would be variants
of scm_to_*_stringn that can return garbage-collected buffers. */
result[i] = scm_gc_malloc_pointerless (len + 1, "string");
memcpy (result[i], c_str, len);
result[i][len] = '\0';
free (c_str);
list = SCM_CDR (list);
}
return result;
}
#undef FUNC_NAME
void void
scm_i_get_substring_spec (size_t len, scm_i_get_substring_spec (size_t len,
SCM start, size_t *cstart, SCM start, size_t *cstart,

View file

@ -1,7 +1,7 @@
#ifndef SCM_STRINGS_H #ifndef SCM_STRINGS_H
#define SCM_STRINGS_H #define SCM_STRINGS_H
/* Copyright 1995-1998,2000-2001,2004-2006,2008-2011,2013,2015-2019,2022 /* Copyright 1995-1998,2000-2001,2004-2006,2008-2011,2013,2015-2019,2022,2025
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of Guile. This file is part of Guile.
@ -265,7 +265,6 @@ SCM_INTERNAL void scm_decoding_error (const char *subr, int err,
/* internal utility functions. */ /* internal utility functions. */
SCM_INTERNAL char **scm_i_allocate_string_pointers (SCM list);
SCM_INTERNAL void scm_i_get_substring_spec (size_t len, SCM_INTERNAL void scm_i_get_substring_spec (size_t len,
SCM start, size_t *cstart, SCM start, size_t *cstart,
SCM end, size_t *cend); SCM end, size_t *cend);