/* "rope.c" interface between C and SCM.
* Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1997, 2006 Free Software Foundation, Inc.
*
* This program 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.
*
* This program 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 this program. If not, see
* .
*/
/* Author: Aubrey Jaffer */
#include "scm.h"
/* Numeric conversions */
/* Convert longs to SCM */
SCM long2num(sl)
long sl;
{
if (!FIXABLE(sl)) {
# ifdef BIGDIG
return long2big(sl);
# else
# ifdef FLOATS
return makdbl((double) sl, 0.0);
# else
return BOOL_F;
# endif
# endif
}
return MAKINUM(sl);
}
SCM ulong2num(sl)
unsigned long sl;
{
if (!POSFIXABLE(sl)) {
#ifdef BIGDIG
return ulong2big(sl);
#else
# ifdef FLOATS
return makdbl((double) sl, 0.0);
# else
return BOOL_F;
# endif
#endif
}
return MAKINUM(sl);
}
/* Convert SCM to numbers */
unsigned char num2uchar(num, pos, s_caller)
SCM num;
char *pos, *s_caller;
{
unsigned long res = INUM(num);
ASRTER(INUMP(num) && (255L >= res), num, pos, s_caller);
return (unsigned char) res;
}
unsigned short num2ushort(num, pos, s_caller)
SCM num;
char *pos, *s_caller;
{
unsigned long res = INUM(num);
ASRTER(INUMP(num) && (65535L >= res), num, pos, s_caller);
return (unsigned short) res;
}
unsigned long num2ulong(num, pos, s_caller)
SCM num;
char *pos, *s_caller;
{
unsigned long res;
if (INUMP(num)) {
ASRTGO(0 < num, errout);
res = INUM((unsigned long)num);
return res;
}
ASRTGO(NIMP(num), errout);
#ifdef FLOATS
if (REALP(num)) {
double u = REALPART(num);
if ((0 <= u) && (u <= (unsigned long)~0L)) {
res = u;
return res;
}
}
#endif
#ifdef BIGDIG
if (TYP16(num)==tc16_bigpos) {
sizet l = NUMDIGS(num);
ASRTGO(DIGSPERLONG >= l, errout);
res = 0;
for (;l--;) res = BIGUP(res) + BDIGITS(num)[l];
return res;
}
#endif
errout: wta(num, pos, s_caller);
}
long num2long(num, pos, s_caller)
SCM num;
char *pos, *s_caller;
{
long res;
if (INUMP(num)) {
res = INUM((long)num);
return res;
}
ASRTGO(NIMP(num), errout);
# ifdef FLOATS
if (REALP(num)) {
double u = REALPART(num);
if (((MOST_NEGATIVE_FIXNUM * 4) <= u)
&& (u <= (MOST_POSITIVE_FIXNUM * 4 + 3))) {
res = u;
return res;
}
}
# endif
# ifdef BIGDIG
if (BIGP(num)) {
sizet l = NUMDIGS(num);
ASRTGO(DIGSPERLONG >= l, errout);
res = 0;
for (;l--;) res = BIGUP(res) + BDIGITS(num)[l];
ASRTGO(0 i) for (i = 0; argv[i]; i++);
while (i--) lst = cons(makfrom0str(argv[i]), lst);
return lst;
}
/* Converts SCM list of strings to NULL terminated array of strings. */
/* INTS must be DEFERed around this call and the use of the returned array. */
char **makargvfrmstrs(args, s_name)
SCM args;
const char *s_name;
{
char ** argv;
int argc = ilength(args);
argv = (char **)must_malloc((1L+argc)*sizeof(char *), s_vector);
for (argc = 0; NNULLP(args); args=CDR(args), ++argc) {
ASRTER(NIMP(CAR(args)) && STRINGP(CAR(args)), CAR(args), ARG2, s_name);
{
sizet len = 1 + LENGTH(CAR(args));
char *dst = (char *)must_malloc((long)len, s_string);
char *src = CHARS(CAR(args));
while (len--) dst[len] = src[len];
argv[argc] = dst;
}
}
argv[argc] = 0;
return argv;
}
void must_free_argv(argv)
char **argv;
{
sizet i;
for (i = 0; argv[i]; i++) {
must_free(argv[i], 1+strlen(argv[i]));
}
must_free((char *)argv, i*sizeof(char *));
}
/* Hooks to call SCM from C */
SCM scm_evstr(str)
char *str;
{
SCM lsym;
NEWCELL(lsym);
SETLENGTH(lsym, strlen(str), tc7_ssymbol);
SETCHARS(lsym, str);
return scm_eval_string(lsym);
}
void scm_ldstr(str)
char *str;
{
SCM lsym;
NEWCELL(lsym);
SETLENGTH(lsym, strlen(str), tc7_ssymbol);
SETCHARS(lsym, str);
scm_load_string(lsym);
}
int scm_ldfile(path)
char *path;
{
SCM name = makfrom0str(path);
*loc_errobj = name;
return BOOL_F==tryload(name, UNDEFINED);
}
int scm_ldprog(path)
char *path;
{
SCM name = makfrom0str(path);
*loc_errobj = name;
return
BOOL_F==scm_evstr("(try-load (in-vicinity (program-vicinity) errobj))");
}
/* Get byte address of SCM array */
#ifdef ARRAYS
long aind P((SCM ra, SCM args, const char *what));
void* scm_addr(args, s_name)
SCM args;
const char *s_name;
{
long pos;
void* ptr = 0; /* gratuitous assignment squelches cc warn. */
SCM v;
ASRTGO(NIMP(args), wna);
v = CAR(args);
args = CDR(args);
if (IMP(v)) {goto badarg;}
else if (ARRAYP(v)) {
pos = aind(v, args, s_name);
v = ARRAY_V(v);
}
else {
if (NIMP(args)) {
ASRTER(CONSP(args) && INUMP(CAR(args)), args, ARG2, s_name);
pos = INUM(CAR(args));
ASRTGO(NULLP(CDR(args)), wna);
}
else if (NULLP(args)) pos = 0;
else {
ASRTER(INUMP(args), args, ARG2, s_name);
pos = INUM(args);
}
ASRTGO(pos >= 0 && pos < LENGTH(v), outrng);
}
switch TYP7(v) {
case tc7_string:
ptr = (void*)&(CHARS(v)[pos]);
break;
# ifdef FLOATS
# ifdef SINGLES
case tc7_VfloC32: pos = 2 * pos;
case tc7_VfloR32: ptr = (void*)&(((float *)CDR(v))[pos]);
break;
# endif
case tc7_VfloC64: pos = 2 * pos;
case tc7_VfloR64: ptr = (void*)&(((double *)CDR(v))[pos]);
break;
# endif
case tc7_Vbool: ASRTGO(0==(pos%LONG_BIT), outrng);
pos = pos/LONG_BIT;
case tc7_VfixN32:
case tc7_VfixZ32:
case tc7_vector: ptr = (void*)&(VELTS(v)[pos]);
break;
case tc7_VfixN16:
case tc7_VfixZ16: ptr = (void*)&(((short *)CDR(v))[pos]);
break;
case tc7_VfixN8:
case tc7_VfixZ8: ptr = (void*)&(((char *)CDR(v))[pos]);
break;
outrng: wta(MAKINUM(pos), (char *)OUTOFRANGE, s_name);
default:
badarg: wta(v, (char *)ARG1, s_name);
wna: wta(UNDEFINED, (char *)WNA, s_name);
}
return ptr;
}
void* scm_base_addr(v, s_name)
SCM v;
const char *s_name;
{
long pos = 0;
void* ptr = 0; /* gratuitous assignment squelches cc warn. */
if (IMP(v)) {goto badarg;}
else if (ARRAYP(v)) {
pos = ARRAY_BASE(v);
v = ARRAY_V(v);
}
switch TYP7(v) {
case tc7_string:
ptr = (void*)&(CHARS(v)[pos]);
break;
# ifdef FLOATS
# ifdef SINGLES
case tc7_VfloC32: pos = 2 * pos;
case tc7_VfloR32:
ptr = (void*)&(((float *)CDR(v))[pos]);
break;
# endif
case tc7_VfloC64: pos = 2 * pos;
case tc7_VfloR64: ptr = (void*)&(((double *)CDR(v))[pos]);
break;
# endif
case tc7_Vbool: ASRTGO(0==(pos%LONG_BIT), outrng);
pos = pos/LONG_BIT;
case tc7_VfixN32:
case tc7_VfixZ32:
case tc7_vector: ptr = (void*)&(VELTS(v)[pos]);
break;
case tc7_VfixN16:
case tc7_VfixZ16: ptr = (void*)&(((short *)CDR(v))[pos]);
break;
case tc7_VfixN8:
case tc7_VfixZ8: ptr = (void*)&(((char *)CDR(v))[pos]);
break;
outrng: wta(MAKINUM(pos), (char *)OUTOFRANGE, s_name);
default:
badarg: wta(v, (char *)ARG1, s_name);
}
return ptr;
}
#endif /* ARRAYS */
extern sizet hplim_ind;
extern CELLPTR *hplims;
/* scm_cell_p() returns !0 if the SCM argument `x' is cell-aligned and
points into a valid heap segment. This code is duplicated from
mark_locations() and obunhash() in "sys.c", which means that
changes to these routines must be coordinated. */
int scm_cell_p(x)
SCM x;
{
register int i, j;
register CELLPTR ptr;
if (NCELLP(x)) return 0;
ptr = (CELLPTR)SCM2PTR(x);
i = 0;
j = hplim_ind;
do {
if (PTR_GT(hplims[i++], ptr)) break;
if (PTR_LE(hplims[--j], ptr)) break;
if ((i != j)
&& PTR_LE(hplims[i++], ptr)
&& PTR_GT(hplims[--j], ptr)) continue;
return !0; /* NFREEP(x) */
} while(i= len) resizuve(scm_uprotects, MAKINUM(len + (len>>2)));
VELTS(scm_uprotects)[scm_protidx++] = obj;
return obj;
}
void init_rope()
{
scm_protidx = 0;
scm_uprotects = make_vector(MAKINUM(20), UNDEFINED);
}