mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
* doc/ref/api-data.texi (Bit Vectors): Update. * libguile/bitvectors.h: * libguile/bitvectors.c: * libguile/deprecated.c: * libguile/deprecated.h: Deprecate scm_bitvector, scm_make_bitvector, and scm_bitvector_p. * libguile/read.c (scm_read_guile_bit_vector): Use scm_list_to_bitvector instead of scm_bitvector.
581 lines
15 KiB
C
581 lines
15 KiB
C
/* Copyright 2003-2004,2006,2008-2018,2020
|
||
Free Software Foundation, Inc.
|
||
|
||
This file is part of Guile.
|
||
|
||
Guile is free software: you can redistribute it and/or modify it
|
||
under the terms of the GNU Lesser General Public License as published
|
||
by the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
Guile is distributed in the hope that it will be useful, but WITHOUT
|
||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||
License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public
|
||
License along with Guile. If not, see
|
||
<https://www.gnu.org/licenses/>. */
|
||
|
||
#ifdef HAVE_CONFIG_H
|
||
# include <config.h>
|
||
#endif
|
||
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
|
||
#define SCM_BUILDING_DEPRECATED_CODE
|
||
|
||
#include "boolean.h"
|
||
#include "bitvectors.h"
|
||
#include "deprecation.h"
|
||
#include "gc.h"
|
||
#include "gsubr.h"
|
||
#include "srfi-4.h"
|
||
#include "strings.h"
|
||
|
||
#include "deprecated.h"
|
||
|
||
#if (SCM_ENABLE_DEPRECATED == 1)
|
||
|
||
|
||
|
||
#ifndef MAXPATHLEN
|
||
#define MAXPATHLEN 80
|
||
#endif /* ndef MAXPATHLEN */
|
||
#ifndef X_OK
|
||
#define X_OK 1
|
||
#endif /* ndef X_OK */
|
||
|
||
char *
|
||
scm_find_executable (const char *name)
|
||
{
|
||
char tbuf[MAXPATHLEN];
|
||
int i = 0, c;
|
||
FILE *f;
|
||
|
||
scm_c_issue_deprecation_warning ("scm_find_executable is deprecated.");
|
||
|
||
/* fprintf(stderr, "s_f_e checking access %s ->%d\n", name, access(name, X_OK)); fflush(stderr); */
|
||
if (access (name, X_OK))
|
||
return 0L;
|
||
f = fopen (name, "r");
|
||
if (!f)
|
||
return 0L;
|
||
if ((fgetc (f) == '#') && (fgetc (f) == '!'))
|
||
{
|
||
while (1)
|
||
switch (c = fgetc (f))
|
||
{
|
||
case /*WHITE_SPACES */ ' ':
|
||
case '\t':
|
||
case '\r':
|
||
case '\f':
|
||
case EOF:
|
||
tbuf[i] = 0;
|
||
fclose (f);
|
||
return strdup (tbuf);
|
||
default:
|
||
tbuf[i++] = c;
|
||
break;
|
||
}
|
||
}
|
||
fclose (f);
|
||
return strdup (name);
|
||
}
|
||
|
||
|
||
|
||
|
||
SCM
|
||
scm_bitvector_p (SCM vec)
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("scm_bitvector_p is deprecated. Use scm_is_bitvector instead.");
|
||
|
||
return scm_from_bool (scm_is_bitvector (vec));
|
||
}
|
||
|
||
SCM
|
||
scm_bitvector (SCM list)
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("scm_bitvector is deprecated. Use scm_list_to_bitvector instead.");
|
||
|
||
return scm_list_to_bitvector (list);
|
||
}
|
||
|
||
SCM
|
||
scm_make_bitvector (SCM len, SCM fill)
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("scm_make_bitvector is deprecated. Use scm_c_make_bitvector instead.");
|
||
|
||
return scm_c_make_bitvector (scm_to_size_t (len), fill);
|
||
}
|
||
|
||
SCM
|
||
scm_bitvector_length (SCM vec)
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("scm_bitvector_length is deprecated. Use scm_c_bitvector_length "
|
||
"instead.");
|
||
|
||
return scm_from_size_t (scm_c_bitvector_length (vec));
|
||
}
|
||
|
||
SCM
|
||
scm_c_bitvector_ref (SCM vec, size_t idx)
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("bitvector-ref is deprecated. Use bitvector-bit-set? instead.");
|
||
|
||
if (scm_is_bitvector (vec))
|
||
return scm_from_bool (scm_c_bitvector_bit_is_set (vec, idx));
|
||
|
||
SCM res;
|
||
scm_t_array_handle handle;
|
||
size_t len, off;
|
||
ssize_t inc;
|
||
|
||
const uint32_t *bits =
|
||
scm_bitvector_elements (vec, &handle, &off, &len, &inc);
|
||
|
||
if (idx >= len)
|
||
scm_out_of_range (NULL, scm_from_size_t (idx));
|
||
idx = idx*inc + off;
|
||
res = scm_from_bool (bits[idx/32] & (1L << (idx%32)));
|
||
scm_array_handle_release (&handle);
|
||
return res;
|
||
}
|
||
|
||
SCM_DEFINE (scm_bitvector_ref, "bitvector-ref", 2, 0, 0,
|
||
(SCM vec, SCM idx),
|
||
"Return the element at index @var{idx} of the bitvector\n"
|
||
"@var{vec}.")
|
||
#define FUNC_NAME s_scm_bitvector_ref
|
||
{
|
||
return scm_c_bitvector_ref (vec, scm_to_size_t (idx));
|
||
}
|
||
#undef FUNC_NAME
|
||
|
||
void
|
||
scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val)
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("bitvector-set! is deprecated. Use bitvector-set-bit! or "
|
||
"bitvector-clear-bit! instead.");
|
||
|
||
if (scm_is_bitvector (vec))
|
||
{
|
||
if (scm_is_true (val))
|
||
scm_c_bitvector_set_bit_x (vec, idx);
|
||
else
|
||
scm_c_bitvector_clear_bit_x (vec, idx);
|
||
}
|
||
else
|
||
{
|
||
scm_t_array_handle handle;
|
||
uint32_t *bits, mask;
|
||
size_t len, off;
|
||
ssize_t inc;
|
||
|
||
bits = scm_bitvector_writable_elements (vec, &handle, &off, &len, &inc);
|
||
if (idx >= len)
|
||
scm_out_of_range (NULL, scm_from_size_t (idx));
|
||
idx = idx*inc + off;
|
||
|
||
mask = 1L << (idx%32);
|
||
if (scm_is_true (val))
|
||
bits[idx/32] |= mask;
|
||
else
|
||
bits[idx/32] &= ~mask;
|
||
|
||
scm_array_handle_release (&handle);
|
||
}
|
||
}
|
||
|
||
SCM_DEFINE (scm_bitvector_set_x, "bitvector-set!", 3, 0, 0,
|
||
(SCM vec, SCM idx, SCM val),
|
||
"Set the element at index @var{idx} of the bitvector\n"
|
||
"@var{vec} when @var{val} is true, else clear it.")
|
||
#define FUNC_NAME s_scm_bitvector_set_x
|
||
{
|
||
scm_c_bitvector_set_x (vec, scm_to_size_t (idx), val);
|
||
return SCM_UNSPECIFIED;
|
||
}
|
||
#undef FUNC_NAME
|
||
|
||
SCM_DEFINE (scm_bitvector_fill_x, "bitvector-fill!", 2, 0, 0,
|
||
(SCM vec, SCM val),
|
||
"Set all elements of the bitvector\n"
|
||
"@var{vec} when @var{val} is true, else clear them.")
|
||
#define FUNC_NAME s_scm_bitvector_fill_x
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("bitvector-fill! is deprecated. Use bitvector-set-all-bits! or "
|
||
"bitvector-clear-all-bits! instead.");
|
||
|
||
if (scm_is_bitvector (vec))
|
||
{
|
||
if (scm_is_true (val))
|
||
scm_c_bitvector_set_all_bits_x (vec);
|
||
else
|
||
scm_c_bitvector_clear_all_bits_x (vec);
|
||
|
||
return SCM_UNSPECIFIED;
|
||
}
|
||
|
||
scm_t_array_handle handle;
|
||
size_t off, len;
|
||
ssize_t inc;
|
||
|
||
scm_bitvector_writable_elements (vec, &handle, &off, &len, &inc);
|
||
|
||
size_t i;
|
||
for (i = 0; i < len; i++)
|
||
scm_array_handle_set (&handle, i*inc, val);
|
||
|
||
scm_array_handle_release (&handle);
|
||
|
||
return SCM_UNSPECIFIED;
|
||
}
|
||
#undef FUNC_NAME
|
||
|
||
SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
|
||
(SCM v),
|
||
"Modify the bit vector @var{v} by replacing each element with\n"
|
||
"its negation.")
|
||
#define FUNC_NAME s_scm_bit_invert_x
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("bit-invert! is deprecated. Use bitvector-flip-all-bits!, or "
|
||
"scalar array accessors in a loop for generic arrays.");
|
||
|
||
if (scm_is_bitvector (v))
|
||
scm_c_bitvector_flip_all_bits_x (v);
|
||
else
|
||
{
|
||
size_t off, len;
|
||
ssize_t inc;
|
||
scm_t_array_handle handle;
|
||
|
||
scm_bitvector_writable_elements (v, &handle, &off, &len, &inc);
|
||
for (size_t i = 0; i < len; i++)
|
||
scm_array_handle_set (&handle, i*inc,
|
||
scm_not (scm_array_handle_ref (&handle, i*inc)));
|
||
scm_array_handle_release (&handle);
|
||
}
|
||
|
||
return SCM_UNSPECIFIED;
|
||
}
|
||
#undef FUNC_NAME
|
||
|
||
SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
|
||
(SCM b, SCM bitvector),
|
||
"Return the number of occurrences of the boolean @var{b} in\n"
|
||
"@var{bitvector}.")
|
||
#define FUNC_NAME s_scm_bit_count
|
||
{
|
||
int bit = scm_to_bool (b);
|
||
size_t count = 0, len;
|
||
|
||
scm_c_issue_deprecation_warning
|
||
("bit-count is deprecated. Use bitvector-count, or a loop over array-ref "
|
||
"if array support is needed.");
|
||
|
||
if (scm_is_bitvector (bitvector))
|
||
{
|
||
len = scm_to_size_t (scm_bitvector_length (bitvector));
|
||
count = scm_c_bitvector_count (bitvector);
|
||
}
|
||
else
|
||
{
|
||
scm_t_array_handle handle;
|
||
size_t off;
|
||
ssize_t inc;
|
||
|
||
scm_bitvector_elements (bitvector, &handle, &off, &len, &inc);
|
||
|
||
for (size_t i = 0; i < len; i++)
|
||
if (scm_is_true (scm_array_handle_ref (&handle, i*inc)))
|
||
count++;
|
||
|
||
scm_array_handle_release (&handle);
|
||
}
|
||
|
||
return scm_from_size_t (bit ? count : len-count);
|
||
}
|
||
#undef FUNC_NAME
|
||
|
||
SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
|
||
(SCM v, SCM kv, SCM obj),
|
||
"Return a count of how many entries in bit vector @var{v} are\n"
|
||
"equal to @var{obj}, with @var{kv} selecting the entries to\n"
|
||
"consider.\n"
|
||
"\n"
|
||
"If @var{kv} is a bit vector, then those entries where it has\n"
|
||
"@code{#t} are the ones in @var{v} which are considered.\n"
|
||
"@var{kv} and @var{v} must be the same length.\n"
|
||
"\n"
|
||
"If @var{kv} is a u32vector, then it contains\n"
|
||
"the indexes in @var{v} to consider.\n"
|
||
"\n"
|
||
"For example,\n"
|
||
"\n"
|
||
"@example\n"
|
||
"(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
|
||
"(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
|
||
"@end example")
|
||
#define FUNC_NAME s_scm_bit_count_star
|
||
{
|
||
size_t count = 0;
|
||
|
||
scm_c_issue_deprecation_warning
|
||
("bit-count* is deprecated. Use bitvector-count-bits instead, and in the "
|
||
"case of counting false bits, subtract from a bitvector-count on the "
|
||
"selection bitvector.");
|
||
|
||
/* Validate that OBJ is a boolean so this is done even if we don't
|
||
need BIT.
|
||
*/
|
||
int bit = scm_to_bool (obj);
|
||
|
||
if (scm_is_bitvector (v) && scm_is_bitvector (kv))
|
||
{
|
||
count = scm_c_bitvector_count_bits (v, kv);
|
||
if (count == 0)
|
||
count = scm_c_bitvector_count (kv) - count;
|
||
}
|
||
else
|
||
{
|
||
scm_t_array_handle v_handle;
|
||
size_t v_off, v_len;
|
||
ssize_t v_inc;
|
||
|
||
scm_bitvector_elements (v, &v_handle, &v_off, &v_len, &v_inc);
|
||
|
||
if (scm_is_bitvector (kv))
|
||
{
|
||
size_t kv_len = scm_c_bitvector_length (kv);
|
||
for (size_t i = 0; i < kv_len; i++)
|
||
if (scm_c_bitvector_bit_is_set (kv, i))
|
||
{
|
||
SCM elt = scm_array_handle_ref (&v_handle, i*v_inc);
|
||
if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
|
||
count++;
|
||
}
|
||
}
|
||
else if (scm_is_true (scm_u32vector_p (kv)))
|
||
{
|
||
scm_t_array_handle kv_handle;
|
||
size_t i, kv_len;
|
||
ssize_t kv_inc;
|
||
const uint32_t *kv_elts;
|
||
|
||
kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
|
||
|
||
for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
|
||
{
|
||
SCM elt = scm_array_handle_ref (&v_handle, (*kv_elts)*v_inc);
|
||
if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
|
||
count++;
|
||
}
|
||
|
||
scm_array_handle_release (&kv_handle);
|
||
}
|
||
else
|
||
scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
|
||
|
||
scm_array_handle_release (&v_handle);
|
||
}
|
||
|
||
return scm_from_size_t (count);
|
||
}
|
||
#undef FUNC_NAME
|
||
|
||
SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
|
||
(SCM item, SCM v, SCM k),
|
||
"Return the index of the first occurrence of @var{item} in bit\n"
|
||
"vector @var{v}, starting from @var{k}. If there is no\n"
|
||
"@var{item} entry between @var{k} and the end of\n"
|
||
"@var{v}, then return @code{#f}. For example,\n"
|
||
"\n"
|
||
"@example\n"
|
||
"(bit-position #t #*000101 0) @result{} 3\n"
|
||
"(bit-position #f #*0001111 3) @result{} #f\n"
|
||
"@end example")
|
||
#define FUNC_NAME s_scm_bit_position
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("bit-position is deprecated. Use bitvector-position, or "
|
||
"array-ref in a loop if you need generic arrays instead.");
|
||
|
||
if (scm_is_bitvector (v))
|
||
return scm_bitvector_position (v, item, k);
|
||
|
||
scm_t_array_handle handle;
|
||
size_t off, len;
|
||
ssize_t inc;
|
||
scm_bitvector_elements (v, &handle, &off, &len, &inc);
|
||
int bit = scm_to_bool (item);
|
||
size_t first_bit = scm_to_unsigned_integer (k, 0, len);
|
||
SCM res = SCM_BOOL_F;
|
||
for (size_t i = first_bit; i < len; i++)
|
||
{
|
||
SCM elt = scm_array_handle_ref (&handle, i*inc);
|
||
if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
|
||
{
|
||
res = scm_from_size_t (i);
|
||
break;
|
||
}
|
||
}
|
||
scm_array_handle_release (&handle);
|
||
|
||
return res;
|
||
}
|
||
#undef FUNC_NAME
|
||
|
||
SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
|
||
(SCM v, SCM kv, SCM obj),
|
||
"Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
|
||
"selecting the entries to change. The return value is\n"
|
||
"unspecified.\n"
|
||
"\n"
|
||
"If @var{kv} is a bit vector, then those entries where it has\n"
|
||
"@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
|
||
"@var{v} must be at least as long as @var{kv}. When @var{obj}\n"
|
||
"is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
|
||
"@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
|
||
"\n"
|
||
"@example\n"
|
||
"(define bv #*01000010)\n"
|
||
"(bit-set*! bv #*10010001 #t)\n"
|
||
"bv\n"
|
||
"@result{} #*11010011\n"
|
||
"@end example\n"
|
||
"\n"
|
||
"If @var{kv} is a u32vector, then its elements are\n"
|
||
"indices into @var{v} which are set to @var{obj}.\n"
|
||
"\n"
|
||
"@example\n"
|
||
"(define bv #*01000010)\n"
|
||
"(bit-set*! bv #u32(5 2 7) #t)\n"
|
||
"bv\n"
|
||
"@result{} #*01100111\n"
|
||
"@end example")
|
||
#define FUNC_NAME s_scm_bit_set_star_x
|
||
{
|
||
scm_c_issue_deprecation_warning
|
||
("bit-set*! is deprecated. Use bitvector-set-bits! or "
|
||
"bitvector-clear-bits! on bitvectors, or array-set! in a loop "
|
||
"if you need to work on generic arrays.");
|
||
|
||
int bit = scm_to_bool (obj);
|
||
if (scm_is_bitvector (v) && scm_is_bitvector (kv))
|
||
{
|
||
if (bit)
|
||
scm_c_bitvector_set_bits_x (v, kv);
|
||
else
|
||
scm_c_bitvector_clear_bits_x (v, kv);
|
||
|
||
return SCM_UNSPECIFIED;
|
||
}
|
||
|
||
scm_t_array_handle v_handle;
|
||
size_t v_off, v_len;
|
||
ssize_t v_inc;
|
||
scm_bitvector_writable_elements (v, &v_handle, &v_off, &v_len, &v_inc);
|
||
|
||
if (scm_is_bitvector (kv))
|
||
{
|
||
size_t kv_len = scm_c_bitvector_length (kv);
|
||
|
||
if (v_len < kv_len)
|
||
scm_misc_error (NULL,
|
||
"selection bitvector longer than target bitvector",
|
||
SCM_EOL);
|
||
|
||
for (size_t i = 0; i < kv_len; i++)
|
||
if (scm_is_true (scm_c_bitvector_ref (kv, i)))
|
||
scm_array_handle_set (&v_handle, i*v_inc, obj);
|
||
}
|
||
else if (scm_is_true (scm_u32vector_p (kv)))
|
||
{
|
||
scm_t_array_handle kv_handle;
|
||
size_t kv_len;
|
||
ssize_t kv_inc;
|
||
const uint32_t *kv_elts;
|
||
|
||
kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
|
||
for (size_t i = 0; i < kv_len; i++, kv_elts += kv_inc)
|
||
scm_array_handle_set (&v_handle, (*kv_elts)*v_inc, obj);
|
||
|
||
scm_array_handle_release (&kv_handle);
|
||
}
|
||
else
|
||
scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
|
||
|
||
scm_array_handle_release (&v_handle);
|
||
|
||
return SCM_UNSPECIFIED;
|
||
}
|
||
#undef FUNC_NAME
|
||
|
||
SCM
|
||
scm_istr2bve (SCM str)
|
||
{
|
||
scm_t_array_handle handle;
|
||
size_t len = scm_i_string_length (str);
|
||
SCM vec = scm_c_make_bitvector (len, SCM_UNDEFINED);
|
||
SCM res = vec;
|
||
|
||
uint32_t mask;
|
||
size_t k, j;
|
||
const char *c_str;
|
||
uint32_t *data;
|
||
|
||
scm_c_issue_deprecation_warning
|
||
("scm_istr2bve is deprecated. "
|
||
"Read from a string instead, prefixed with `#*'.");
|
||
|
||
data = scm_bitvector_writable_elements (vec, &handle, NULL, NULL, NULL);
|
||
c_str = scm_i_string_chars (str);
|
||
|
||
for (k = 0; k < (len + 31) / 32; k++)
|
||
{
|
||
data[k] = 0L;
|
||
j = len - k * 32;
|
||
if (j > 32)
|
||
j = 32;
|
||
for (mask = 1L; j--; mask <<= 1)
|
||
switch (*c_str++)
|
||
{
|
||
case '0':
|
||
break;
|
||
case '1':
|
||
data[k] |= mask;
|
||
break;
|
||
default:
|
||
res = SCM_BOOL_F;
|
||
goto exit;
|
||
}
|
||
}
|
||
|
||
exit:
|
||
scm_array_handle_release (&handle);
|
||
scm_remember_upto_here_1 (str);
|
||
return res;
|
||
}
|
||
|
||
|
||
|
||
|
||
void
|
||
scm_i_init_deprecated ()
|
||
{
|
||
#include "deprecated.x"
|
||
}
|
||
|
||
#endif /* SCM_ENABLE_DEPRECATD == 1 */
|