151 lines
3.8 KiB
C
151 lines
3.8 KiB
C
|
/* Generic routines for Scheme48/C interfacing -- mostly for converting
|
||
|
** strings and null-terminated vectors back and forth.
|
||
|
** Copyright (c) 1993 by Olin Shivers.
|
||
|
*/
|
||
|
|
||
|
#include "libcig.h"
|
||
|
#include <string.h>
|
||
|
#include <stddef.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#define Malloc(type,n) ((type *) malloc(sizeof(type)*(n)))
|
||
|
#define Free(p) (free((char *)(p)))
|
||
|
|
||
|
/* (c2scheme_strcpy dest_scheme_string source_C_string)
|
||
|
** Copies C string's chars into Scheme string. Return #t.
|
||
|
** If C string is NULL, do nothing and return #f.
|
||
|
*/
|
||
|
|
||
|
int c2scheme_strcpy(scheme_value sstr, char *cstr)
|
||
|
{
|
||
|
if( cstr ) {
|
||
|
strncpy( (char*) StobData(sstr), cstr, STRING_LENGTH(sstr) );
|
||
|
return 1;
|
||
|
}
|
||
|
else return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Same as above, but free the C string when we are done. */
|
||
|
int c2scheme_strcpy_free(scheme_value sstr, char *cstr)
|
||
|
{
|
||
|
if( cstr ) {
|
||
|
strncpy( (char*) StobData(sstr), cstr, STRING_LENGTH(sstr) );
|
||
|
Free(cstr);
|
||
|
return 1;
|
||
|
}
|
||
|
else return 0;
|
||
|
}
|
||
|
|
||
|
char *scheme2c_strcpy(scheme_value sstr)
|
||
|
{
|
||
|
char *result;
|
||
|
int slen;
|
||
|
extern void *memcpy(void*, const void*, size_t);
|
||
|
extern int errno;
|
||
|
|
||
|
slen = STRING_LENGTH(sstr);
|
||
|
result = (char*) malloc(slen+1);
|
||
|
|
||
|
if( result == NULL ) {
|
||
|
fprintf(stderr,
|
||
|
"Fatal error: C stub tried to copy Scheme string,\n"
|
||
|
"but malloc failed on arg 0x%x, errno %d.\n",
|
||
|
sstr, errno);
|
||
|
exit(-1);
|
||
|
}
|
||
|
|
||
|
memcpy(result, (void *) cig_string_body(sstr), slen);
|
||
|
result[slen] = '\000';
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* One arg, a zero-terminated C word vec. Returns length.
|
||
|
** The terminating null is not counted. Returns #f on NULL.
|
||
|
*/
|
||
|
|
||
|
scheme_value c_veclen(long *vec)
|
||
|
{
|
||
|
long *vptr = vec;
|
||
|
if( !vptr ) return SCHFALSE;
|
||
|
while( *vptr ) vptr++;
|
||
|
return ENTER_FIXNUM(vptr - vec);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Copy string from into string to. If to is NULL, malloc a fresh string
|
||
|
** (if the malloc loses, return NULL).
|
||
|
** If from is NULL, then
|
||
|
** - if to is NULL, do nothing and return NULL.
|
||
|
** - Otherwise, deposit a single nul byte.
|
||
|
** Under normal conditions, this routine returns the destination string.
|
||
|
**
|
||
|
** The little boundary cases of this procedure are a study in obfuscation
|
||
|
** because C doesn't have a reasonable string data type. Give me a break.
|
||
|
*/
|
||
|
char *copystring(char *to, const char *from)
|
||
|
{
|
||
|
if( from ) {
|
||
|
int slen = strlen(from)+1;
|
||
|
if( !to && !(to = Malloc(char, slen)) ) return NULL;
|
||
|
else return memcpy(to, from, slen);
|
||
|
}
|
||
|
|
||
|
else
|
||
|
return to ? *to = '\000', to : NULL;
|
||
|
}
|
||
|
|
||
|
/* As in copystring, but if malloc loses, print out an error msg and croak. */
|
||
|
char *copystring_or_die(const char *str ) /* Note: NULL -> NULL. */
|
||
|
{
|
||
|
if( str ) {
|
||
|
int len = strlen(str)+1;
|
||
|
char *new_str = Malloc(char, len);
|
||
|
if( ! new_str ) {
|
||
|
fprintf(stderr, "copystring: Malloc failed.\n");
|
||
|
exit(-1);
|
||
|
}
|
||
|
return memcpy(new_str, str, len);
|
||
|
}
|
||
|
else return NULL;
|
||
|
}
|
||
|
|
||
|
int cstring_nullp( char *s ) { return ! s; }
|
||
|
|
||
|
scheme_value strlen_or_false(const char *s)
|
||
|
{ return s ? ENTER_FIXNUM(strlen(s)) : SCHFALSE; }
|
||
|
|
||
|
|
||
|
|
||
|
/* svec is a Scheme vector of C string carriers. Scan over the C strings
|
||
|
** in cvec, and initialise the corresponding string carriers in svec.
|
||
|
*/
|
||
|
void set_strvec_carriers(scheme_value svec, char const * const * cvec)
|
||
|
{
|
||
|
int svec_len = VECTOR_LENGTH(svec);
|
||
|
char const * const * cv = cvec;
|
||
|
scheme_value *sv = &VECTOR_REF(svec,0);
|
||
|
|
||
|
for(; svec_len > 0; cv++, sv++, svec_len-- ) {
|
||
|
/* *sv is a (cons (make-alien <c-string>) <string-length>). */
|
||
|
scheme_value carrier = *sv;
|
||
|
scheme_value alien = CAR(carrier);
|
||
|
CDR(carrier) = ENTER_FIXNUM(strlen(*cv));
|
||
|
AlienVal(alien) = (long) *cv;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Helper function for arg checking. Why bother, actually? */
|
||
|
void cig_check_nargs(int arity, int nargs, char *fn)
|
||
|
{
|
||
|
if( arity != nargs ) {
|
||
|
fprintf(stderr,
|
||
|
"Cig fatal error (%s) -- C stub expected %d arg%s, "
|
||
|
"but got %d.\n",
|
||
|
fn, arity, (arity == 1) ? "" : "s", nargs);
|
||
|
exit(-1);
|
||
|
}
|
||
|
}
|