* libguile/private-options.h: Introduce a new enum indexing the read options, and use its values as indices for scm_read_opts. * libguile/read.c: Get rid of the bit field offsets #define-s, and instead use the enum values to caculate them.
* libguile/read.c (enum t_keyword_style, scm_t_read_opts): Moved to libguile/private-options.h, the names of the keyword style enum having been prefixed with "SCM_" (use sites adapted accordingly). These have been moved out of the C file so that they can be used in other parts of libguile -- they are needed by the scm_i_read()'s interface. * libguile/read.h (scm_i_read): New procedure, marked SCM_INTERNAL. (scm_t_read_opts): Opaque typedef for the struct defined in private-options.h. * libguile/read.c (init_read_options): Add an additional argument `preset', to allow the caller to specify reader options that are preset and should not be changed. (scm_i_read): New internal procedure, allowing to fix (part of) the reader options. --- libguile/private-options.h | 51 ++++++++++++++++---- libguile/read.c | 115 +++++++++++++++++++------------------------- libguile/read.h | 6 ++- 3 files changed, 95 insertions(+), 77 deletions(-) diff --git a/libguile/private-options.h b/libguile/private-options.h index ed0f314..0c85d0c 100644 --- a/libguile/private-options.h +++ b/libguile/private-options.h @@ -4,7 +4,7 @@ * We put this in a private header, since layout of data structures * is an implementation detail that we want to hide. * - * Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc. + * Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -60,15 +60,46 @@ SCM_INTERNAL scm_t_option scm_print_opts[]; */ SCM_INTERNAL scm_t_option scm_read_opts[]; -#define SCM_COPY_SOURCE_P scm_read_opts[0].val -#define SCM_RECORD_POSITIONS_P scm_read_opts[1].val -#define SCM_CASE_INSENSITIVE_P scm_read_opts[2].val -#define SCM_KEYWORD_STYLE scm_read_opts[3].val -#define SCM_R6RS_ESCAPES_P scm_read_opts[4].val -#define SCM_SQUARE_BRACKETS_P scm_read_opts[5].val -#define SCM_HUNGRY_EOL_ESCAPES_P scm_read_opts[6].val -#define SCM_CURLY_INFIX_P scm_read_opts[7].val +enum + { + SCM_READ_OPTION_COPY_SOURCE_P, + SCM_READ_OPTION_RECORD_POSITIONS_P, + SCM_READ_OPTION_CASE_INSENSITIVE_P, + SCM_READ_OPTION_KEYWORD_STYLE, + SCM_READ_OPTION_R6RS_ESCAPES_P, + SCM_READ_OPTION_SQUARE_BRACKETS_P, + SCM_READ_OPTION_HUNGRY_EOL_ESCAPES_P, + SCM_READ_OPTION_CURLY_INFIX_P, + SCM_N_READ_OPTIONS + }; -#define SCM_N_READ_OPTIONS 7 +typedef enum + { + SCM_KEYWORD_STYLE_HASH_PREFIX, + SCM_KEYWORD_STYLE_PREFIX, + SCM_KEYWORD_STYLE_POSTFIX + } scm_t_keyword_style; + +struct scm_struct_read_opts +{ + scm_t_keyword_style keyword_style; + unsigned int copy_source_p : 1; + unsigned int record_positions_p : 1; + unsigned int case_insensitive_p : 1; + unsigned int r6rs_escapes_p : 1; + unsigned int square_brackets_p : 1; + unsigned int hungry_eol_escapes_p : 1; + unsigned int curly_infix_p : 1; + unsigned int neoteric_p : 1; +}; + +#define SCM_COPY_SOURCE_P scm_read_opts[SCM_READ_OPTION_COPY_SOURCE_P].val +#define SCM_RECORD_POSITIONS_P scm_read_opts[SCM_READ_OPTION_RECORD_POSITIONS_P].val +#define SCM_CASE_INSENSITIVE_P scm_read_opts[SCM_READ_OPTION_CASE_INSENSITIVE_P].val +#define SCM_KEYWORD_STYLE scm_read_opts[SCM_READ_OPTION_KEYWORD_STYLE].val +#define SCM_R6RS_ESCAPES_P scm_read_opts[SCM_READ_OPTION_R6RS_ESCAPES_P].val +#define SCM_SQUARE_BRACKETS_P scm_read_opts[SCM_READ_OPTION_SQUARE_BRACKETS_P].val +#define SCM_HUNGRY_EOL_ESCAPES_P scm_read_opts[SCM_READ_OPTION_HUNGRY_EOL_ESCAPES_P].val +#define SCM_CURLY_INFIX_P scm_read_opts[SCM_READ_OPTION_CURLY_INFIX_P].val #endif /* PRIVATE_OPTIONS */ diff --git a/libguile/read.c b/libguile/read.c index 222891b..754ea99 100644 --- a/libguile/read.c +++ b/libguile/read.c @@ -93,29 +93,6 @@ scm_t_option scm_read_opts[] = from the global and per-port read options, and a pointer is passed down to all helper functions. */ -enum t_keyword_style - { - KEYWORD_STYLE_HASH_PREFIX, - KEYWORD_STYLE_PREFIX, - KEYWORD_STYLE_POSTFIX - }; - -struct t_read_opts -{ - enum t_keyword_style keyword_style; - unsigned int copy_source_p : 1; - unsigned int record_positions_p : 1; - unsigned int case_insensitive_p : 1; - unsigned int r6rs_escapes_p : 1; - unsigned int square_brackets_p : 1; - unsigned int hungry_eol_escapes_p : 1; - unsigned int curly_infix_p : 1; - unsigned int neoteric_p : 1; -}; - -typedef struct t_read_opts scm_t_read_opts; - - /* Give meaningful error messages for errors @@ -737,7 +714,7 @@ scm_read_mixed_case_symbol (scm_t_wchar chr, SCM port, scm_t_read_opts *opts) SCM result; int ends_with_colon = 0; size_t bytes_read; - int postfix = (opts->keyword_style == KEYWORD_STYLE_POSTFIX); + int postfix = (opts->keyword_style == SCM_KEYWORD_STYLE_POSTFIX); char local_buffer[READER_BUFFER_SIZE], *buffer; scm_t_port *pt = SCM_PTAB_ENTRY (port); SCM str; @@ -1771,7 +1748,7 @@ read_inner_expression (SCM port, scm_t_read_opts *opts) case EOF: return SCM_EOF_VAL; case ':': - if (opts->keyword_style == KEYWORD_STYLE_PREFIX) + if (opts->keyword_style == SCM_KEYWORD_STYLE_PREFIX) return scm_symbol_to_keyword (scm_read_expression (port, opts)); /* Fall through. */ @@ -1859,7 +1836,7 @@ scm_read_expression (SCM port, scm_t_read_opts *opts) /* Actual reader. */ -static void init_read_options (SCM port, scm_t_read_opts *opts); +static void init_read_options (SCM port, scm_t_read_opts *opts, unsigned int mask); SCM_DEFINE (scm_read, "read", 0, 1, 0, (SCM port), @@ -1875,7 +1852,7 @@ SCM_DEFINE (scm_read, "read", 0, 1, 0, port = scm_current_input_port (); SCM_VALIDATE_OPINPORT (1, port); - init_read_options (port, &opts); + init_read_options (port, &opts, 0); c = flush_ws (port, &opts, (char *) NULL); if (EOF == c) @@ -1887,6 +1864,21 @@ SCM_DEFINE (scm_read, "read", 0, 1, 0, #undef FUNC_NAME +SCM scm_i_read (SCM port, const scm_t_read_opts *opts, unsigned int preset) +{ + int c; + scm_t_read_opts local_opts = *opts; + + init_read_options (port, &local_opts, preset); + + c = flush_ws (port, &local_opts, (char *) NULL); + if (EOF == c) + return SCM_EOF_VAL; + scm_ungetc (c, port); + + return (scm_read_expression (port, &local_opts)); +} + /* Manipulate the read-hash-procedures alist. This could be written in @@ -2158,18 +2150,8 @@ SCM_DEFINE (scm_file_encoding, "file-encoding", 1, 0, 0, /* Key to read options in per-port alists. */ SCM_SYMBOL (sym_port_read_options, "port-read-options"); -/* Offsets of bit fields for each per-port override */ -#define READ_OPTION_COPY_SOURCE_P 0 -#define READ_OPTION_RECORD_POSITIONS_P 2 -#define READ_OPTION_CASE_INSENSITIVE_P 4 -#define READ_OPTION_KEYWORD_STYLE 6 -#define READ_OPTION_R6RS_ESCAPES_P 8 -#define READ_OPTION_SQUARE_BRACKETS_P 10 -#define READ_OPTION_HUNGRY_EOL_ESCAPES_P 12 -#define READ_OPTION_CURLY_INFIX_P 14 - /* The total width in bits of the per-port overrides */ -#define READ_OPTIONS_NUM_BITS 16 +#define READ_OPTIONS_NUM_BITS (SCM_N_READ_OPTIONS * 2) #define READ_OPTIONS_INHERIT_ALL ((1UL << READ_OPTIONS_NUM_BITS) - 1) #define READ_OPTIONS_MAX_VALUE READ_OPTIONS_INHERIT_ALL @@ -2191,8 +2173,8 @@ set_port_read_option (SCM port, int option, int new_value) read_options = scm_to_uint (scm_read_options); else read_options = READ_OPTIONS_INHERIT_ALL; - read_options &= ~(READ_OPTION_MASK << option); - read_options |= new_value << option; + read_options &= ~(READ_OPTION_MASK << (option * 2)); + read_options |= new_value << (option * 2); scm_read_options = scm_from_uint (read_options); alist = scm_assq_set_x (alist, sym_port_read_options, scm_read_options); scm_hashq_set_x (scm_i_port_weak_hash, port, alist); @@ -2205,7 +2187,7 @@ set_port_case_insensitive_p (SCM port, scm_t_read_opts *opts, int value) { value = !!value; opts->case_insensitive_p = value; - set_port_read_option (port, READ_OPTION_CASE_INSENSITIVE_P, value); + set_port_read_option (port, SCM_READ_OPTION_CASE_INSENSITIVE_P, value); } /* Set OPTS and PORT's square_brackets_p option according to VALUE. */ @@ -2214,7 +2196,7 @@ set_port_square_brackets_p (SCM port, scm_t_read_opts *opts, int value) { value = !!value; opts->square_brackets_p = value; - set_port_read_option (port, READ_OPTION_SQUARE_BRACKETS_P, value); + set_port_read_option (port, SCM_READ_OPTION_SQUARE_BRACKETS_P, value); } /* Set OPTS and PORT's curly_infix_p option according to VALUE. */ @@ -2223,13 +2205,13 @@ set_port_curly_infix_p (SCM port, scm_t_read_opts *opts, int value) { value = !!value; opts->curly_infix_p = value; - set_port_read_option (port, READ_OPTION_CURLY_INFIX_P, value); + set_port_read_option (port, SCM_READ_OPTION_CURLY_INFIX_P, value); } /* Initialize OPTS based on PORT's read options and the global read options. */ static void -init_read_options (SCM port, scm_t_read_opts *opts) +init_read_options (SCM port, scm_t_read_opts *opts, unsigned int preset) { SCM alist, val, scm_read_options; unsigned int read_options, x; @@ -2244,28 +2226,29 @@ init_read_options (SCM port, scm_t_read_opts *opts) else read_options = READ_OPTIONS_INHERIT_ALL; - x = READ_OPTION_MASK & (read_options >> READ_OPTION_KEYWORD_STYLE); - if (x == READ_OPTION_INHERIT) - { - val = SCM_PACK (SCM_KEYWORD_STYLE); - if (scm_is_eq (val, scm_keyword_prefix)) - x = KEYWORD_STYLE_PREFIX; - else if (scm_is_eq (val, scm_keyword_postfix)) - x = KEYWORD_STYLE_POSTFIX; - else - x = KEYWORD_STYLE_HASH_PREFIX; - } - opts->keyword_style = x; - -#define RESOLVE_BOOLEAN_OPTION(NAME, name) \ - do \ - { \ - x = READ_OPTION_MASK & (read_options >> READ_OPTION_ ## NAME); \ - if (x == READ_OPTION_INHERIT) \ - x = !!SCM_ ## NAME; \ - opts->name = x; \ - } \ - while (0) + if ((preset & (1 << SCM_READ_OPTION_KEYWORD_STYLE)) == 0) { + x = READ_OPTION_MASK & (read_options >> (SCM_READ_OPTION_KEYWORD_STYLE * 2)); + if (x == READ_OPTION_INHERIT) + { + val = SCM_PACK (SCM_KEYWORD_STYLE); + if (scm_is_eq (val, scm_keyword_prefix)) + x = SCM_KEYWORD_STYLE_PREFIX; + else if (scm_is_eq (val, scm_keyword_postfix)) + x = SCM_KEYWORD_STYLE_POSTFIX; + else + x = SCM_KEYWORD_STYLE_HASH_PREFIX; + } + opts->keyword_style = x; + } + +#define RESOLVE_BOOLEAN_OPTION(NAME, name) \ + if ((preset & (1 << SCM_READ_OPTION_ ## NAME)) == 0) { \ + x = (READ_OPTION_MASK \ + & (read_options >> (SCM_READ_OPTION_ ## NAME * 2))); \ + if (x == READ_OPTION_INHERIT) \ + x = !!SCM_ ## NAME; \ + opts->name = x; \ + } RESOLVE_BOOLEAN_OPTION (COPY_SOURCE_P, copy_source_p); RESOLVE_BOOLEAN_OPTION (RECORD_POSITIONS_P, record_positions_p); diff --git a/libguile/read.h b/libguile/read.h index 3c47afd..c460d2f 100644 --- a/libguile/read.h +++ b/libguile/read.h @@ -3,7 +3,7 @@ #ifndef SCM_READ_H #define SCM_READ_H -/* Copyright (C) 1995,1996,2000, 2006, 2008, 2009 Free Software Foundation, Inc. +/* Copyright (C) 1995,1996,2000, 2006, 2008, 2009, 2012 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -49,12 +49,16 @@ +typedef struct scm_struct_read_opts scm_t_read_opts; SCM_API SCM scm_sym_dot; SCM_API SCM scm_read_options (SCM setting); SCM_API SCM scm_read (SCM port); SCM_API SCM scm_read_hash_extend (SCM chr, SCM proc); +SCM_INTERNAL SCM scm_i_read(SCM port, + const scm_t_read_opts *opts, + unsigned int preset); SCM_INTERNAL char *scm_i_scan_for_encoding (SCM port); SCM_API SCM scm_file_encoding (SCM port); -- 1.7.10.4