#include "libguile/strports.h"
#include "libguile/vectors.h"
#include "libguile/validate.h"
+#include "libguile/srfi-4.h"
#include "libguile/read.h"
*/
-static void
-scm_input_error(char const * function,
- SCM port, const char * message, SCM arg)
+void
+scm_i_input_error (char const *function,
+ SCM port, const char *message, SCM arg)
{
- char *fn = SCM_STRINGP (SCM_FILENAME(port))
- ? SCM_STRING_CHARS(SCM_FILENAME(port))
- : "#<unknown port>";
+ SCM fn = (scm_is_string (SCM_FILENAME(port))
+ ? SCM_FILENAME(port)
+ : scm_from_locale_string ("#<unknown port>"));
- SCM string_port = scm_open_output_string ();
+ SCM string_port = scm_open_output_string ();
SCM string = SCM_EOL;
scm_simple_format (string_port,
- scm_makfrom0str ("~A:~S:~S: ~A"),
- scm_list_4 (scm_makfrom0str (fn),
- scm_int2num (SCM_LINUM (port) + 1),
- scm_int2num (SCM_COL (port) + 1),
- scm_makfrom0str (message)));
-
+ scm_from_locale_string ("~A:~S:~S: ~A"),
+ scm_list_4 (fn,
+ scm_from_int (SCM_LINUM (port) + 1),
+ scm_from_int (SCM_COL (port) + 1),
+ scm_from_locale_string (message)));
string = scm_get_output_string (string_port);
scm_close_output_port (string_port);
- scm_error_scm (scm_str2symbol ("read-error"),
- scm_makfrom0str (function),
+ scm_error_scm (scm_from_locale_symbol ("read-error"),
+ function? scm_from_locale_string (function) : SCM_BOOL_F,
string,
arg,
SCM_BOOL_F);
return SCM_EOF_VAL;
scm_ungetc (c, port);
- tok_buf = scm_allocate_string (30);
+ tok_buf = scm_c_make_string (30, SCM_UNDEFINED);
return scm_lreadr (&tok_buf, port, ©);
}
#undef FUNC_NAME
char *
scm_grow_tok_buf (SCM *tok_buf)
{
- size_t oldlen = SCM_STRING_LENGTH (*tok_buf);
- SCM newstr = scm_allocate_string (2 * oldlen);
+ size_t oldlen = scm_i_string_length (*tok_buf);
+ const char *olddata = scm_i_string_chars (*tok_buf);
+ char *newdata;
+ SCM newstr = scm_i_make_string (2 * oldlen, &newdata);
size_t i;
for (i = 0; i != oldlen; ++i)
- SCM_STRING_CHARS (newstr) [i] = SCM_STRING_CHARS (*tok_buf) [i];
+ newdata[i] = olddata[i];
*tok_buf = newstr;
- return SCM_STRING_CHARS (newstr);
+ return newdata;
}
+/* Consume an SCSH-style block comment. Assume that we've already
+ read the initial `#!', and eat characters until we get a
+ exclamation-point/sharp-sign sequence.
+*/
+
+static void
+skip_scsh_block_comment (SCM port)
+{
+ int bang_seen = 0;
+ for (;;)
+ {
+ int c = scm_getc (port);
+
+ if (c == EOF)
+ scm_i_input_error ("skip_block_comment", port,
+ "unterminated `#! ... !#' comment", SCM_EOL);
+
+ if (c == '!')
+ bang_seen = 1;
+ else if (c == '#' && bang_seen)
+ return;
+ else
+ bang_seen = 0;
+ }
+}
int
scm_flush_ws (SCM port, const char *eoferr)
goteof:
if (eoferr)
{
- scm_input_error (eoferr,
- port,
- "end of file",
- SCM_EOL);
+ scm_i_input_error (eoferr,
+ port,
+ "end of file",
+ SCM_EOL);
}
return c;
case ';':
break;
}
break;
+ case '#':
+ switch (c = scm_getc (port))
+ {
+ case EOF:
+ eoferr = "read_sharp";
+ goto goteof;
+ case '!':
+ skip_scsh_block_comment (port);
+ break;
+ default:
+ scm_ungetc (c, port);
+ return '#';
+ }
+ break;
case SCM_LINE_INCREMENTORS:
case SCM_SINGLE_SPACES:
case '\t':
return !(*s1 || *s2);
}
+static int
+scm_i_casei_streq (const char *s1, const char *s2, size_t len2)
+{
+ while (*s1 && len2 > 0)
+ if (scm_c_downcase((int)*s1) != scm_c_downcase((int)*s2))
+ return 0;
+ else
+ {
+ ++s1;
+ ++s2;
+ --len2;
+ }
+ return !(*s1 || len2 > 0);
+}
/* recsexpr is used when recording expressions
* constructed by read:sharp.
static SCM
recsexpr (SCM obj, long line, int column, SCM filename)
{
- if (!SCM_CONSP(obj)) {
+ if (!scm_is_pair(obj)) {
return obj;
} else {
SCM tmp = obj, copy;
{
copy = scm_cons (recsexpr (SCM_CAR (obj), line, column, filename),
SCM_UNDEFINED);
- while ((tmp = SCM_CDR (tmp)) && SCM_CONSP (tmp))
+ while ((tmp = SCM_CDR (tmp)) && scm_is_pair (tmp))
{
SCM_SETCDR (copy, scm_cons (recsexpr (SCM_CAR (tmp),
line,
else
{
recsexpr (SCM_CAR (obj), line, column, filename);
- while ((tmp = SCM_CDR (tmp)) && SCM_CONSP (tmp))
+ while ((tmp = SCM_CDR (tmp)) && scm_is_pair (tmp))
recsexpr (SCM_CAR (tmp), line, column, filename);
copy = SCM_UNDEFINED;
}
}
}
-/* Consume an SCSH-style block comment. Assume that we've already
- read the initial `#!', and eat characters until we get a
- newline/exclamation-point/sharp-sign/newline sequence.
-
- A carriage return is also reocgnized as a newline. */
-
-static void
-skip_scsh_block_comment (SCM port)
-#define FUNC_NAME "skip_scsh_block_comment"
-{
- int state = 0;
-
- for (;;)
- {
- int c = scm_getc (port);
-
- if (c == EOF)
- SCM_MISC_ERROR ("unterminated `#! ... !#' comment", SCM_EOL);
-
- if (state == 1 && c == '!')
- state = 2;
- else if (state == 2 && c == '#')
- state = 3;
- else if (state == 3 && (c == '\n' || c == '\r'))
- return;
- else if (c == '\n' || c == '\r')
- state = 1;
- else
- state = 0;
- }
-}
-#undef FUNC_NAME
-
static SCM scm_get_hash_procedure(int c);
static SCM scm_i_lreadparen (SCM *, SCM, char *, SCM *, char);
tryagain:
c = scm_flush_ws (port, s_scm_read);
- tryagain_no_flush_ws:
switch (c)
{
case EOF:
? scm_lreadrecparen (tok_buf, port, s_list, copy)
: scm_i_lreadparen (tok_buf, port, s_list, copy, ')');
case ')':
- scm_input_error (FUNC_NAME, port,"unexpected \")\"", SCM_EOL);
+ scm_i_input_error (FUNC_NAME, port,"unexpected \")\"", SCM_EOL);
goto tryagain;
#if SCM_ENABLE_ELISP
if (SCM_ELISP_VECTORS_P)
{
p = scm_i_lreadparen (tok_buf, port, s_vector, copy, ']');
- return SCM_NULLP (p) ? scm_nullvect : scm_vector (p);
+ return scm_is_null (p) ? scm_nullvect : scm_vector (p);
}
goto read_token;
#endif
handle_sharp:
switch (c)
{
+ /* Vector, arrays, both uniform and not are handled by this
+ one function. It also disambiguates between '#f' and
+ '#f32' and '#f64'.
+ */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'u': case 's': case 'f':
+ case '@':
case '(':
- p = scm_i_lreadparen (tok_buf, port, s_vector, copy, ')');
- return SCM_NULLP (p) ? scm_nullvect : scm_vector (p);
+#if SCM_ENABLE_DEPRECATED
+ /* See below for 'i' and 'e'. */
+ case 'a':
+ case 'c':
+ case 'y':
+ case 'h':
+ case 'l':
+#endif
+ return scm_i_read_array (port, c);
case 't':
case 'T':
return SCM_BOOL_T;
- case 'f':
+
case 'F':
+ /* See above for lower case 'f'. */
return SCM_BOOL_F;
+
+ case 'i':
+ case 'e':
+#if SCM_ENABLE_DEPRECATED
+ {
+ /* When next char is '(', it really is an old-style
+ uniform array. */
+ int next_c = scm_getc (port);
+ if (next_c != EOF)
+ scm_ungetc (next_c, port);
+ if (next_c == '(')
+ return scm_i_read_array (port, c);
+ /* Fall through. */
+ }
+#endif
case 'b':
case 'B':
case 'o':
case 'D':
case 'x':
case 'X':
- case 'i':
case 'I':
- case 'e':
case 'E':
scm_ungetc (c, port);
c = '#';
goto num;
case '!':
- /* start of a shell script. Parse as a block comment,
- terminated by !#, just like SCSH. */
- skip_scsh_block_comment (port);
- /* EOF is not an error here */
- c = scm_flush_ws (port, (char *)NULL);
- goto tryagain_no_flush_ws;
-
-#if SCM_HAVE_ARRAYS
+ /* should never happen, #!...!# block comments are skipped
+ over in scm_flush_ws. */
+ abort ();
+
case '*':
j = scm_read_token (c, tok_buf, port, 0);
- p = scm_istr2bve (SCM_STRING_CHARS (*tok_buf) + 1, (long) (j - 1));
+ p = scm_istr2bve (scm_c_substring_shared (*tok_buf, 1, j));
if (scm_is_true (p))
return p;
else
goto unkshrp;
-#endif
case '{':
j = scm_read_token (c, tok_buf, port, 1);
- return scm_mem2symbol (SCM_STRING_CHARS (*tok_buf), j);
+ return scm_string_to_symbol (scm_c_substring_copy (*tok_buf, 0, j));
case '\\':
c = scm_getc (port);
* does only consist of octal digits. Finally, it should be
* checked whether the resulting fixnum is in the range of
* characters. */
- p = scm_i_mem2number (SCM_STRING_CHARS (*tok_buf), j, 8);
+ p = scm_i_mem2number (scm_i_string_chars (*tok_buf), j, 8);
if (SCM_I_INUMP (p))
return SCM_MAKE_CHAR (SCM_I_INUM (p));
}
for (c = 0; c < scm_n_charnames; c++)
if (scm_charnames[c]
- && (scm_casei_streq (scm_charnames[c], SCM_STRING_CHARS (*tok_buf))))
+ && (scm_i_casei_streq (scm_charnames[c],
+ scm_i_string_chars (*tok_buf), j)))
return SCM_MAKE_CHAR (scm_charnums[c]);
- scm_input_error (FUNC_NAME, port, "unknown # object", SCM_EOL);
+ scm_i_input_error (FUNC_NAME, port, "unknown character name ~a",
+ scm_list_1 (scm_c_substring (*tok_buf, 0, j)));
/* #:SYMBOL is a syntax for keywords supported in all contexts. */
case ':':
- j = scm_read_token ('-', tok_buf, port, 0);
- p = scm_mem2symbol (SCM_STRING_CHARS (*tok_buf), j);
- return scm_make_keyword_from_dash_symbol (p);
+ return scm_symbol_to_keyword (scm_read (port));
default:
callshrp:
}
}
unkshrp:
- scm_input_error (FUNC_NAME, port, "Unknown # object: ~S",
- scm_list_1 (SCM_MAKE_CHAR (c)));
+ scm_i_input_error (FUNC_NAME, port, "Unknown # object: ~S",
+ scm_list_1 (SCM_MAKE_CHAR (c)));
}
case '"':
while ('"' != (c = scm_getc (port)))
{
if (c == EOF)
- str_eof: scm_input_error (FUNC_NAME, port, "end of file in string constant", SCM_EOL);
+ str_eof: scm_i_input_error (FUNC_NAME, port,
+ "end of file in string constant",
+ SCM_EOL);
- while (j + 2 >= SCM_STRING_LENGTH (*tok_buf))
+ while (j + 2 >= scm_i_string_length (*tok_buf))
scm_grow_tok_buf (tok_buf);
if (c == '\\')
}
default:
bad_escaped:
- scm_input_error(FUNC_NAME, port,
- "illegal character in escape sequence: ~S",
- scm_list_1 (SCM_MAKE_CHAR (c)));
+ scm_i_input_error(FUNC_NAME, port,
+ "illegal character in escape sequence: ~S",
+ scm_list_1 (SCM_MAKE_CHAR (c)));
}
- SCM_STRING_CHARS (*tok_buf)[j] = c;
+ scm_c_string_set_x (*tok_buf, j, SCM_MAKE_CHAR (c));
++j;
}
if (j == 0)
return scm_nullstr;
- SCM_STRING_CHARS (*tok_buf)[j] = 0;
- return scm_mem2string (SCM_STRING_CHARS (*tok_buf), j);
+
+ /* Change this to scm_c_substring_read_only when
+ SCM_STRING_CHARS has been removed.
+ */
+ return scm_c_substring_copy (*tok_buf, 0, j);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/* Shortcut: Detected symbol '+ or '- */
goto tok;
- p = scm_i_mem2number (SCM_STRING_CHARS (*tok_buf), j, 10);
+ p = scm_i_mem2number (scm_i_string_chars (*tok_buf), j, 10);
if (scm_is_true (p))
return p;
if (c == '#')
if ((j == 2) && (scm_getc (port) == '('))
{
scm_ungetc ('(', port);
- c = SCM_STRING_CHARS (*tok_buf)[1];
+ c = scm_i_string_chars (*tok_buf)[1];
goto callshrp;
}
- scm_input_error (FUNC_NAME, port, "unknown # object", SCM_EOL);
+ scm_i_input_error (FUNC_NAME, port, "unknown # object", SCM_EOL);
}
goto tok;
case ':':
if (scm_is_eq (SCM_PACK (SCM_KEYWORD_STYLE), scm_keyword_prefix))
- {
- j = scm_read_token ('-', tok_buf, port, 0);
- p = scm_mem2symbol (SCM_STRING_CHARS (*tok_buf), j);
- return scm_make_keyword_from_dash_symbol (p);
- }
+ return scm_symbol_to_keyword (scm_read (port));
+
/* fallthrough */
default:
#if SCM_ENABLE_ELISP
/* fallthrough */
tok:
- return scm_mem2symbol (SCM_STRING_CHARS (*tok_buf), j);
+ return scm_string_to_symbol (scm_c_substring (*tok_buf, 0, j));
}
}
#undef FUNC_NAME
size_t
scm_read_token (int ic, SCM *tok_buf, SCM port, int weird)
{
- register size_t j;
- register int c;
- register char *p;
+ size_t j;
+ int c;
c = (SCM_CASE_INSENSITIVE_P ? scm_c_downcase(ic) : ic);
- p = SCM_STRING_CHARS (*tok_buf);
-
+
if (weird)
j = 0;
else
{
j = 0;
- while (j + 2 >= SCM_STRING_LENGTH (*tok_buf))
- p = scm_grow_tok_buf (tok_buf);
- p[j] = c;
+ while (j + 2 >= scm_i_string_length (*tok_buf))
+ scm_grow_tok_buf (tok_buf);
+ scm_c_string_set_x (*tok_buf, j, SCM_MAKE_CHAR (c));
++j;
}
while (1)
{
- while (j + 2 >= SCM_STRING_LENGTH (*tok_buf))
- p = scm_grow_tok_buf (tok_buf);
+ while (j + 2 >= scm_i_string_length (*tok_buf))
+ scm_grow_tok_buf (tok_buf);
c = scm_getc (port);
switch (c)
{
scm_ungetc (c, port);
case EOF:
eof_case:
- p[j] = 0;
return j;
case '\\':
if (!weird)
c = scm_getc (port);
if (c == '#')
{
- p[j] = 0;
return j;
}
else
default_case:
{
c = (SCM_CASE_INSENSITIVE_P ? scm_c_downcase(c) : c);
- p[j] = c;
+ scm_c_string_set_x (*tok_buf, j, SCM_MAKE_CHAR (c));
++j;
}
ans = scm_lreadr (tok_buf, port, copy);
closeit:
if (term_char != (c = scm_flush_ws (port, name)))
- scm_input_error (FUNC_NAME, port, "missing close paren", SCM_EOL);
+ scm_i_input_error (FUNC_NAME, port, "missing close paren", SCM_EOL);
return ans;
}
ans = tl = scm_cons (tmp, SCM_EOL);
{
ans = scm_lreadr (tok_buf, port, copy);
if (')' != (c = scm_flush_ws (port, name)))
- scm_input_error (FUNC_NAME, port, "missing close paren", SCM_EOL);
+ scm_i_input_error (FUNC_NAME, port, "missing close paren", SCM_EOL);
return ans;
}
/* Build the head of the list structure. */
ans = tl = scm_cons (tmp, SCM_EOL);
if (SCM_COPY_SOURCE_P)
- ans2 = tl2 = scm_cons (SCM_CONSP (tmp)
+ ans2 = tl2 = scm_cons (scm_is_pair (tmp)
? *copy
: tmp,
SCM_EOL);
{
SCM_SETCDR (tl, tmp = scm_lreadr (tok_buf, port, copy));
if (SCM_COPY_SOURCE_P)
- SCM_SETCDR (tl2, scm_cons (SCM_CONSP (tmp)
+ SCM_SETCDR (tl2, scm_cons (scm_is_pair (tmp)
? *copy
: tmp,
SCM_EOL));
if (')' != (c = scm_flush_ws (port, name)))
- scm_input_error (FUNC_NAME, port, "missing close paren", SCM_EOL);
+ scm_i_input_error (FUNC_NAME, port,
+ "missing close paren", SCM_EOL);
goto exit;
}
if (SCM_COPY_SOURCE_P)
{
- SCM new_tail2 = scm_cons (SCM_CONSP (tmp) ? *copy : tmp, SCM_EOL);
+ SCM new_tail2 = scm_cons (scm_is_pair (tmp) ? *copy : tmp, SCM_EOL);
SCM_SETCDR (tl2, new_tail2);
tl2 = new_tail2;
}
prev = SCM_BOOL_F;
while (1)
{
- if (SCM_NULLP (this))
+ if (scm_is_null (this))
{
/* not found, so add it to the beginning. */
if (scm_is_true (proc))
while (1)
{
- if (SCM_NULLP (rest))
+ if (scm_is_null (rest))
return SCM_BOOL_F;
if (SCM_CHAR (SCM_CAAR (rest)) == c)