1 /* Copyright (C) 1995,1996 Free Software Foundation, Inc.
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice.
50 #include "mbstrings.h"
61 #define default_case_i 0
65 scm_option scm_read_opts
[] = {
66 { SCM_OPTION_BOOLEAN
, "copy", 0,
67 "Copy source code expressions." },
68 { SCM_OPTION_BOOLEAN
, "positions", 0,
69 "Record positions of source code expressions." }
72 SCM_PROC (s_read_options
, "read-options-interface", 0, 1, 0, scm_read_options
);
75 scm_read_options (SCM setting
)
78 scm_read_options (setting
)
82 SCM ans
= scm_options (setting
,
86 if (SCM_COPY_SOURCE_P
)
87 SCM_RECORD_POSITIONS_P
= 1;
91 SCM_PROC (s_read
, "read", 0, 3, 0, scm_read
);
94 scm_read (SCM port
, SCM case_insensitive_p
, SCM sharp
)
97 scm_read (port
, case_insensitive_p
, sharp
)
99 SCM case_insensitive_p
;
107 if (SCM_UNBNDP (port
))
110 SCM_ASSERT (SCM_NIMP (port
) && SCM_OPINPORTP (port
),
115 case_i
= (SCM_UNBNDP (case_insensitive_p
)
117 : (case_insensitive_p
== SCM_BOOL_F
));
119 if (SCM_UNBNDP (sharp
))
122 c
= scm_flush_ws (port
, (char *) NULL
);
125 scm_gen_ungetc (c
, port
);
127 tok_buf
= scm_makstr (30L, 0);
128 return scm_lreadr (&tok_buf
, port
, case_i
, sharp
, ©
);
134 scm_grow_tok_buf (SCM
* tok_buf
)
137 scm_grow_tok_buf (tok_buf
)
141 scm_vector_set_length_x (*tok_buf
, SCM_MAKINUM (2 * SCM_LENGTH (*tok_buf
)));
142 return SCM_CHARS (*tok_buf
);
148 scm_flush_ws (SCM port
, char *eoferr
)
151 scm_flush_ws (port
, eoferr
)
158 switch (c
= scm_gen_getc (port
))
163 scm_wta (SCM_UNDEFINED
, "end of file in ", eoferr
);
167 switch (c
= scm_gen_getc (port
))
173 case SCM_LINE_INCREMENTORS
:
177 case SCM_LINE_INCREMENTORS
:
178 case SCM_SINGLE_SPACES
:
189 scm_casei_streq (char * s1
, char * s2
)
192 scm_casei_streq (s1
, s2
)
198 if (scm_downcase((int)*s1
) != scm_downcase((int)*s2
))
205 return !(*s1
|| *s2
);
209 /* recsexpr is used when recording expressions
210 * constructed by read:sharp.
214 recsexpr (SCM obj
, int line
, int column
, SCM filename
)
217 recsexpr (obj
, line
, column
, filename
)
224 if (SCM_IMP (obj
) || SCM_NCONSP(obj
))
228 /* If this sexpr is visible in the read:sharp source, we want to
229 keep that information, so only record non-constant cons cells
230 which haven't previously been read by the reader. */
231 if (SCM_FALSEP (scm_whash_lookup (scm_source_whash
, obj
)))
233 if (SCM_COPY_SOURCE_P
)
235 copy
= scm_cons (recsexpr (SCM_CAR (obj
), line
, column
, filename
),
237 while (SCM_NIMP (tmp
= SCM_CDR (tmp
)) && SCM_CONSP (tmp
))
238 copy
= (SCM_CDR (copy
) = scm_cons (recsexpr (SCM_CAR (tmp
),
243 SCM_CDR (copy
) = tmp
;
247 recsexpr (SCM_CAR (obj
), line
, column
, filename
);
248 while (SCM_NIMP (tmp
= SCM_CDR (tmp
)) && SCM_CONSP (tmp
))
249 recsexpr (SCM_CAR (tmp
), line
, column
, filename
);
250 copy
= SCM_UNDEFINED
;
252 scm_whash_insert (scm_source_whash
,
254 scm_make_srcprops (line
,
264 static char s_list
[]="list";
267 scm_lreadr (SCM
*tok_buf
, SCM port
, int case_i
, SCM sharp
, SCM
*copy
)
270 scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
)
283 c
= scm_flush_ws (port
, s_read
);
290 return SCM_RECORD_POSITIONS_P
291 ? scm_lreadrecparen (tok_buf
, port
, s_list
, case_i
, sharp
, copy
)
292 : scm_lreadparen (tok_buf
, port
, s_list
, case_i
, sharp
, copy
);
294 scm_wta (SCM_UNDEFINED
, "unexpected \")\"", "read");
301 p
= scm_i_quasiquote
;
304 c
= scm_gen_getc (port
);
306 p
= scm_i_uq_splicing
;
309 scm_gen_ungetc (c
, port
);
314 scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
),
316 if (SCM_RECORD_POSITIONS_P
)
317 scm_whash_insert (scm_source_whash
,
319 scm_make_srcprops (SCM_LINUM (port
),
323 ? (*copy
= scm_cons2 (SCM_CAR (p
),
324 SCM_CAR (SCM_CDR (p
)),
330 c
= scm_gen_getc (port
);
334 p
= scm_lreadparen (tok_buf
, port
, "vector", case_i
, sharp
, copy
);
335 return SCM_NULLP (p
) ? scm_nullvect
: scm_vector (p
);
356 scm_gen_ungetc (c
, port
);
361 j
= scm_read_token (c
, tok_buf
, port
, case_i
, 0);
362 p
= scm_istr2bve (SCM_CHARS (*tok_buf
) + 1, (long) (j
- 1));
369 j
= scm_read_token (c
, tok_buf
, port
, case_i
, 1);
370 p
= scm_intern (SCM_CHARS (*tok_buf
), j
);
371 if (SCM_PORT_REPRESENTATION (port
) != scm_regular_port
)
372 scm_set_symbol_multi_byte_x (SCM_CAR (p
), SCM_BOOL_T
);
376 c
= scm_gen_getc (port
);
377 j
= scm_read_token (c
, tok_buf
, port
, case_i
, 0);
379 return SCM_MAKICHR (c
);
380 if (c
>= '0' && c
< '8')
382 p
= scm_istr2int (SCM_CHARS (*tok_buf
), (long) j
, 8);
384 return SCM_MAKICHR (SCM_INUM (p
));
386 for (c
= 0; c
< scm_n_charnames
; c
++)
388 && (scm_casei_streq (scm_charnames
[c
], SCM_CHARS (*tok_buf
))))
389 return SCM_MAKICHR (scm_charnums
[c
]);
390 scm_wta (SCM_UNDEFINED
, "unknown # object: #\\", SCM_CHARS (*tok_buf
));
395 if (SCM_NIMP (sharp
))
397 int line
= SCM_LINUM (port
);
398 int column
= SCM_COL (port
) - 2;
400 got
= scm_apply (sharp
,
402 scm_acons (port
, SCM_EOL
, SCM_EOL
));
403 if (SCM_UNSPECIFIED
== got
)
405 if (SCM_RECORD_POSITIONS_P
)
406 return *copy
= recsexpr (got
, line
, column
,
407 SCM_FILENAME (port
));
411 unkshrp
:scm_wta ((SCM
) SCM_MAKICHR (c
), "unknown # object", "");
416 while ('"' != (c
= scm_gen_getc (port
)))
418 SCM_ASSERT (EOF
!= c
, SCM_UNDEFINED
, "end of file in ", "string");
420 while (j
+ sizeof(xwchar_t
) + XMB_CUR_MAX
>= SCM_LENGTH (*tok_buf
))
421 scm_grow_tok_buf (tok_buf
);
424 switch (c
= scm_gen_getc (port
))
450 if (SCM_PORT_REPRESENTATION(port
) == scm_regular_port
)
452 SCM_CHARS (*tok_buf
)[j
] = c
;
458 len
= xwctomb (SCM_CHARS (*tok_buf
) + j
, c
);
461 SCM_ASSERT (len
> 0, SCM_MAKINUM (c
), "bogus char", "read");
467 SCM_CHARS (*tok_buf
)[j
] = 0;
470 str
= scm_makfromstr (SCM_CHARS (*tok_buf
), j
, 0);
471 if (SCM_PORT_REPRESENTATION(port
) != scm_regular_port
)
473 SCM_SETLENGTH (str
, SCM_LENGTH (str
), scm_tc7_mb_string
);
478 case'0':case '1':case '2':case '3':case '4':
479 case '5':case '6':case '7':case '8':case '9':
484 j
= scm_read_token (c
, tok_buf
, port
, case_i
, 0);
485 p
= scm_istring2number (SCM_CHARS (*tok_buf
), (long) j
, 10L);
490 if ((j
== 2) && (scm_gen_getc (port
) == '('))
492 scm_gen_ungetc ('(', port
);
493 c
= SCM_CHARS (*tok_buf
)[1];
496 scm_wta (SCM_UNDEFINED
, "unknown # object", SCM_CHARS (*tok_buf
));
501 j
= scm_read_token ('-', tok_buf
, port
, case_i
, 0);
502 p
= scm_intern (SCM_CHARS (*tok_buf
), j
);
503 if (SCM_PORT_REPRESENTATION (port
) != scm_regular_port
)
504 scm_set_symbol_multi_byte_x (SCM_CAR (p
), SCM_BOOL_T
);
505 return scm_make_keyword_from_dash_symbol (SCM_CAR (p
));
508 j
= scm_read_token (c
, tok_buf
, port
, case_i
, 0);
512 p
= scm_intern (SCM_CHARS (*tok_buf
), j
);
513 if (SCM_PORT_REPRESENTATION (port
) != scm_regular_port
)
514 scm_set_symbol_multi_byte_x (SCM_CAR (p
), SCM_BOOL_T
);
520 _Pragma ("noopt"); /* # pragma _CRI noopt */
524 scm_read_token (int ic
, SCM
* tok_buf
, SCM port
, int case_i
, int weird
)
527 scm_read_token (ic
, * tok_buf
, port
, case_i
, weird
)
535 register scm_sizet j
;
540 p
= SCM_CHARS (*tok_buf
);
547 while (j
+ sizeof(xwchar_t
) + XMB_CUR_MAX
>= SCM_LENGTH (*tok_buf
))
548 p
= scm_grow_tok_buf (tok_buf
);
549 if (SCM_PORT_REPRESENTATION(port
) == scm_regular_port
)
557 len
= xwctomb (p
+ j
, c
);
560 SCM_ASSERT (len
> 0, SCM_MAKINUM (c
), "bogus char", "read");
567 while (j
+ sizeof(xwchar_t
) + XMB_CUR_MAX
>= SCM_LENGTH (*tok_buf
))
568 p
= scm_grow_tok_buf (tok_buf
);
569 c
= scm_gen_getc (port
);
576 case SCM_WHITE_SPACES
:
577 case SCM_LINE_INCREMENTORS
:
581 scm_gen_ungetc (c
, port
);
591 c
= scm_gen_getc (port
);
601 c
= scm_gen_getc (port
);
609 scm_gen_ungetc (c
, port
);
617 c
= (case_i
? scm_downcase(c
) : c
);
618 if (SCM_PORT_REPRESENTATION(port
) == scm_regular_port
)
626 len
= xwctomb (p
+ j
, c
);
629 SCM_ASSERT (len
> 0, SCM_MAKINUM (c
), "bogus char", "read");
638 _Pragma ("opt"); /* # pragma _CRI opt */
643 scm_lreadparen (SCM
* tok_buf
, SCM port
, char *name
, int case_i
, SCM sharp
, SCM
*copy
)
646 scm_lreadparen (tok_buf
, port
, name
, case_i
, sharp
, SCM
*copy
)
659 c
= scm_flush_ws (port
, name
);
662 scm_gen_ungetc (c
, port
);
663 if (scm_i_dot
== (tmp
= scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
)))
665 ans
= scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
);
667 if (')' != (c
= scm_flush_ws (port
, name
)))
668 scm_wta (SCM_UNDEFINED
, "missing close paren", "");
671 ans
= tl
= scm_cons (tmp
, SCM_EOL
);
672 while (')' != (c
= scm_flush_ws (port
, name
)))
674 scm_gen_ungetc (c
, port
);
675 if (scm_i_dot
== (tmp
= scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
)))
677 SCM_CDR (tl
) = scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
);
680 tl
= (SCM_CDR (tl
) = scm_cons (tmp
, SCM_EOL
));
687 scm_lreadrecparen (SCM
* tok_buf
, SCM port
, char *name
, int case_i
, SCM sharp
, SCM
*copy
)
690 scm_lreadrecparen (tok_buf
, port
, name
, case_i
, sharp
, copy
)
701 register SCM tl
, tl2
;
703 /* Need to capture line and column numbers here. */
704 int line
= SCM_LINUM (port
);
705 int column
= SCM_COL (port
) - 1;
707 c
= scm_flush_ws (port
, name
);
710 scm_gen_ungetc (c
, port
);
711 if (scm_i_dot
== (tmp
= scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
)))
713 ans
= scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
);
714 if (')' != (c
= scm_flush_ws (port
, name
)))
715 scm_wta (SCM_UNDEFINED
, "missing close paren", "");
718 /* Build the head of the list structure. */
719 ans
= tl
= scm_cons (tmp
, SCM_EOL
);
720 if (SCM_COPY_SOURCE_P
)
721 ans2
= tl2
= scm_cons (SCM_NIMP (tmp
) && SCM_CONSP (tmp
)
725 while (')' != (c
= scm_flush_ws (port
, name
)))
727 scm_gen_ungetc (c
, port
);
728 if (scm_i_dot
== (tmp
= scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
)))
730 SCM_SETCDR (tl
, tmp
= scm_lreadr (tok_buf
, port
, case_i
, sharp
, copy
));
731 if (SCM_COPY_SOURCE_P
)
732 SCM_SETCDR (tl2
, scm_cons (SCM_NIMP (tmp
) && SCM_CONSP (tmp
)
736 if (')' != (c
= scm_flush_ws (port
, name
)))
737 scm_wta (SCM_UNDEFINED
, "missing close paren", "");
740 tl
= SCM_SETCDR (tl
, scm_cons (tmp
, SCM_EOL
));
741 if (SCM_COPY_SOURCE_P
)
742 tl2
= SCM_SETCDR (tl2
, scm_cons (SCM_NIMP (tmp
) && SCM_CONSP (tmp
)
748 scm_whash_insert (scm_source_whash
,
750 scm_make_srcprops (line
,
772 #ifdef READER_EXTENSIONS
773 scm_init_opts (scm_read_options
, scm_read_opts
, SCM_N_READ_OPTIONS
);