200 lines
5.0 KiB
C
200 lines
5.0 KiB
C
/*
|
|
* s p o r t . c -- String ports management
|
|
*
|
|
* Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
|
|
*
|
|
*
|
|
* Permission to use, copy, modify, distribute,and license this
|
|
* software and its documentation for any purpose is hereby granted,
|
|
* provided that existing copyright notices are retained in all
|
|
* copies and that this notice is included verbatim in any
|
|
* distributions. No written agreement, license, or royalty fee is
|
|
* required for any of the authorized uses.
|
|
* This software is provided ``AS IS'' without express or implied
|
|
* warranty.
|
|
*
|
|
*
|
|
* Author: Erick Gallesio [eg@unice.fr]
|
|
* Creation date: 17-Feb-1993 12:27
|
|
* Last file update: 14-Sep-1999 09:26 (eg)
|
|
*
|
|
*
|
|
* This is achieved in a (surely very) dependant way. A string port is implemented
|
|
* via a pseudo FILE descriptor malloc'd when open-input-string is called. This
|
|
* descriptor is released when free-string-port is called.
|
|
*/
|
|
|
|
#include "stk.h"
|
|
#include "sport.h"
|
|
|
|
SCM STk_internal_open_input_string(char *str)
|
|
{
|
|
struct str_iob *p;
|
|
SCM z;
|
|
|
|
p = (struct str_iob *) must_malloc(sizeof (struct str_iob));
|
|
|
|
p->signature = SPORT_SIGNATURE;
|
|
p->flag = READING;
|
|
p->cnt = p->bufsiz = strlen(str);
|
|
p->base = p->ptr = must_malloc((unsigned int ) p->cnt + 1);
|
|
strcpy(p->base, str);
|
|
|
|
/* Sport_descr is a short version of a port_descr */
|
|
NEWCELL(z, tc_isport);
|
|
z->storage_as.port.p = (struct port_descr *)
|
|
must_malloc(sizeof(struct sport_descr));
|
|
PORT_UNGETC(z) = EOF;
|
|
PORT_FILE(z) = (FILE *) p;
|
|
PORT_FLAGS(z) = 0;
|
|
|
|
return z;
|
|
}
|
|
|
|
void STk_free_string_port(SCM port)
|
|
{
|
|
struct str_iob * p;
|
|
|
|
p = (struct str_iob *) PORT_FILE(port);
|
|
free(p->base);
|
|
free(p);
|
|
free(port->storage_as.port.p);
|
|
}
|
|
|
|
SCM STk_internal_read_from_string(SCM port, int *eof, int case_significant)
|
|
{
|
|
SCM result;
|
|
|
|
PUSH_ERROR_HANDLER
|
|
{
|
|
STk_err_handler->context =
|
|
(STk_err_handler->context & (ERR_IGNORED|ERR_OK)) | ERR_READ_FROM_STRING;
|
|
result = STk_readf(port, case_significant);
|
|
*eof = Eof(port);
|
|
}
|
|
WHEN_ERROR
|
|
{
|
|
result = EVAL_ERROR;
|
|
/* Two cases:
|
|
* - if we are in a catch, propagate the error to go back in the
|
|
* context of the catch
|
|
* - otherwise error has already been signaled, do nothing
|
|
*/
|
|
if (STk_err_handler->context & ERR_IGNORED) PROPAGATE_ERROR();
|
|
}
|
|
POP_ERROR_HANDLER;
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
PRIMITIVE STk_open_input_string(SCM s)
|
|
{
|
|
if (NSTRINGP(s)) Err("open-input-string: not a string", s);
|
|
return STk_internal_open_input_string(CHARS(s));
|
|
}
|
|
|
|
|
|
PRIMITIVE STk_open_output_string(void)
|
|
{
|
|
struct str_iob *p;
|
|
SCM z;
|
|
|
|
p = (struct str_iob *) must_malloc(sizeof (struct str_iob));
|
|
|
|
p->signature = SPORT_SIGNATURE;
|
|
p->flag = WRITING;
|
|
p->cnt = 0;
|
|
p->bufsiz = START_ALLOC;
|
|
p->base = p->ptr = (unsigned char *) must_malloc(START_ALLOC);
|
|
|
|
NEWCELL(z, tc_osport);
|
|
z->storage_as.port.p = (struct port_descr *)
|
|
must_malloc(sizeof(struct sport_descr));
|
|
PORT_FILE(z) = (FILE *) p;
|
|
PORT_FLAGS(z) = 0;
|
|
|
|
return z;
|
|
}
|
|
|
|
PRIMITIVE STk_get_output_string(SCM port)
|
|
{
|
|
if (NOSPORTP(port)) Err("get-output-string: Bad string-port", port);
|
|
if (PORT_FLAGS(port) & PORT_CLOSED)
|
|
Err("get-output-string: string port is closed", port);
|
|
|
|
return STk_makestrg( ((struct str_iob *)PORT_FILE(port))->cnt,
|
|
(char*) ((struct str_iob *)PORT_FILE(port))->base);
|
|
}
|
|
|
|
PRIMITIVE STk_input_string_portp(SCM port)
|
|
{
|
|
return (ISPORTP(port)) ? Truth: Ntruth;
|
|
}
|
|
|
|
PRIMITIVE STk_output_string_portp(SCM port)
|
|
{
|
|
return (OSPORTP(port)) ? Truth: Ntruth;
|
|
}
|
|
|
|
|
|
/*=============================================================================*\
|
|
*
|
|
* Redirections from/to a string
|
|
*
|
|
\*=============================================================================*/
|
|
|
|
|
|
PRIMITIVE STk_with_input_from_string(SCM string, SCM thunk)
|
|
{
|
|
ENTER_PRIMITIVE("with-input-from-string");
|
|
|
|
if (NSTRINGP(string)) Serror("bad string", string);
|
|
if (!STk_is_thunk(thunk)) Serror("bad thunk", thunk);
|
|
|
|
return STk_redirect_input(STk_internal_open_input_string(CHARS(string)), thunk);
|
|
}
|
|
|
|
PRIMITIVE STk_with_output_to_string(SCM thunk)
|
|
{
|
|
SCM p;
|
|
|
|
ENTER_PRIMITIVE("with-output-to-string");
|
|
|
|
if (!STk_is_thunk(thunk)) Serror("bad thunk", thunk);
|
|
|
|
p = STk_open_output_string();
|
|
STk_redirect_output(p, thunk);
|
|
return STk_get_output_string(p);
|
|
}
|
|
|
|
PRIMITIVE STk_with_error_to_string(SCM thunk)
|
|
{
|
|
SCM p;
|
|
|
|
ENTER_PRIMITIVE("with-error-to-string");
|
|
|
|
if (!STk_is_thunk(thunk)) Serror("bad thunk", thunk);
|
|
|
|
p = STk_open_output_string();
|
|
STk_redirect_error(p, thunk);
|
|
return STk_get_output_string(p);
|
|
}
|
|
|
|
|
|
PRIMITIVE STk_read_from_string(SCM str)
|
|
{
|
|
SCM result, port;
|
|
int eof; /* not used here */
|
|
|
|
if (NSTRINGP(str)) Err("read-from-string: Bad string", str);
|
|
|
|
/* Create a string port to read in the expression */
|
|
port = STk_internal_open_input_string(CHARS(str));
|
|
result = STk_internal_read_from_string(port, &eof, FALSE);
|
|
|
|
return result == EVAL_ERROR? UNDEFINED: result;
|
|
}
|
|
|
|
|