diff --git a/src/c/reader.d b/src/c/reader.d index fe4ca38a5..747a4e57c 100644 --- a/src/c/reader.d +++ b/src/c/reader.d @@ -29,40 +29,39 @@ /* * This routine inverts the case of the characters in the buffer which were not - * escaped. ESCAPE_LIST is a list of intevals of characters that were escaped, - * as in ({(low-limit . high-limit)}*). The list goes from the last interval to - * the first one, in reverse order, and thus we run the buffer from the end to - * the beginning. + * escaped. ESCAPE_INTERVALS is a vector of intevals of characters that were + * escaped, as in ({(low-limit . high-limit)}*). */ static void -invert_buffer_case(cl_object x, cl_object escape_list, int sign) +invert_buffer_case(cl_object x, cl_object escape_intervals, int sign) { cl_fixnum high_limit, low_limit; - cl_fixnum i = TOKEN_STRING_FILLP(x)-1; - do { - if (escape_list != ECL_NIL) { - cl_object escape_interval = CAR(escape_list); - high_limit = ecl_fixnum(CAR(escape_interval)); - low_limit = ecl_fixnum(CDR(escape_interval)); - escape_list = CDR(escape_list); - } else { - high_limit = low_limit = -1; - } - for (; i > high_limit; i--) { - /* The character is not escaped */ - int c = TOKEN_STRING_CHAR(x,i); + cl_fixnum str_i = 0, esc_index = 0; + int c; + /* see whether we have a bug with reversed beginning/end */ + loop_across_stack_fifo(eint, escape_intervals) { + low_limit = ecl_fixnum(CAR(eint)); + high_limit = ecl_fixnum(CDR(eint)); + for(; str_i 0)) { c = ecl_char_upcase(c); } - TOKEN_STRING_CHAR_SET(x,i,c); + TOKEN_STRING_CHAR_SET(x,str_i,c); } - for (; i > low_limit; i--) { - /* The character is within an escaped interval */ - ; + str_i=high_limit; + } end_loop_across_stack(); + for (; str_i < ecl_length(x); str_i++) { + c = TOKEN_STRING_CHAR(x,str_i); + if (ecl_upper_case_p(c) && (sign < 0)) { + c = ecl_char_downcase(c); + } else if (ecl_lower_case_p(c) && (sign > 0)) { + c = ecl_char_upcase(c); } - } while (i >= 0); + TOKEN_STRING_CHAR_SET(x,str_i,c); + } } /* @@ -127,15 +126,16 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) cl_env_ptr the_env = ecl_process_env(); cl_object rtbl = ecl_current_readtable(); enum ecl_readtable_case read_case = rtbl->readtable.read_case; - cl_object escape_list; /* intervals of escaped characters */ + cl_object escape_intervals; /* intervals of escaped characters */ cl_fixnum upcase; /* # uppercase characters - # downcase characters */ cl_fixnum count; /* number of unescaped characters */ bool suppress = read_suppress; - p = escape_list = ECL_NIL; + p = ECL_NIL; colon = upcase = count = length = 0; external_symbol = 0; token = si_get_buffer_string(); + escape_intervals = ecl_make_stack(0); if (escape_first_p) { c = 0; @@ -163,9 +163,9 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) * had the same case, we revert their case. */ if (read_case == ecl_case_invert && count != 0) { if (upcase == count) { - invert_buffer_case(token, escape_list, -1); + invert_buffer_case(token, escape_intervals, -1); } else if (upcase == -count) { - invert_buffer_case(token, escape_list, +1); + invert_buffer_case(token, escape_intervals, +1); } } if (length == 0) { @@ -182,20 +182,21 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) */ cl_object name = cl_copy_seq(token); unlikely_if (Null(the_env->packages_to_be_created_p)) { + ecl_free_stack(escape_intervals); + si_put_buffer_string(token); FEerror("There is no package with the name ~A.", 1, name); } p = _ecl_package_to_be_created(the_env, name); } TOKEN_STRING_FILLP(token) = length = 0; upcase = count = colon = 0; - escape_list = ECL_NIL; + ecl_wipe_stack(escape_intervals); } if (a == cat_single_escape) { c = ecl_read_char_noeof(in); a = cat_constituent; - escape_list = CONS(CONS(ecl_make_fixnum(length), - ecl_make_fixnum(length-1)), - escape_list); + ecl_stack_push(escape_intervals, CONS(ecl_make_fixnum(length-1), + ecl_make_fixnum(length))); ecl_string_push_extend(token, c); length++; goto NEXT; @@ -213,9 +214,8 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) ecl_string_push_extend(token, c); length++; } - escape_list = CONS(CONS(ecl_make_fixnum(begin), - ecl_make_fixnum(length-1)), - escape_list); + ecl_stack_push(escape_intervals, CONS(ecl_make_fixnum(begin), + ecl_make_fixnum(length-1))); goto NEXT; } if (a == cat_whitespace || a == cat_terminating) { @@ -223,6 +223,8 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) break; } unlikely_if (ecl_invalid_character_p(c) && !suppress) { + ecl_free_stack(escape_intervals); + si_put_buffer_string(token); FEreader_error("Found invalid character ~:C", in, 1, ECL_CODE_CHAR(c)); } if (read_case != ecl_case_preserve) { @@ -254,7 +256,7 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) /* If there are some escaped characters, it must be a symbol */ if ((flags == ECL_READ_ONLY_TOKEN) || p != ECL_NIL || - escape_list != ECL_NIL || length == 0) + ecl_length(escape_intervals) != 0 || length == 0) goto SYMBOL; /* The case in which the buffer is full of dots has to be especial cased */ @@ -263,6 +265,8 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) x = @'si::.'; goto OUTPUT; } else { + ecl_free_stack(escape_intervals); + si_put_buffer_string(token); FEreader_error("Dots appeared illegally.", in, 0); } } else { @@ -271,6 +275,8 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) if (!TOKEN_STRING_CHAR_CMP(token,i,'.')) goto MAYBE_NUMBER; } + ecl_free_stack(escape_intervals); + si_put_buffer_string(token); FEreader_error("Dots appeared illegally.", in, 0); } @@ -280,15 +286,18 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) if ((base <= 10) && ecl_alpha_char_p(TOKEN_STRING_CHAR(token,0))) goto SYMBOL; x = ecl_parse_number(token, 0, TOKEN_STRING_FILLP(token), &i, base); - unlikely_if (x == ECL_NIL) + unlikely_if (x == ECL_NIL) { + ecl_free_stack(escape_intervals); + si_put_buffer_string(token); FEreader_error("Syntax error when reading number.~%Offending string: ~S.", in, 1, token); + } if (x != OBJNULL && length == i) goto OUTPUT; SYMBOL: if (flags == ECL_READ_ONLY_TOKEN) { - the_env->nvalues = 1; - return token; + ecl_free_stack(escape_intervals); + ecl_return1(the_env, token); } /*TOKEN_STRING_CHAR_SET(token,length,'\0');*/ @@ -296,14 +305,16 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) * had the same case, we revert their case. */ if (read_case == ecl_case_invert && count != 0) { if (upcase == count) { - invert_buffer_case(token, escape_list, -1); + invert_buffer_case(token, escape_intervals, -1); } else if (upcase == -count) { - invert_buffer_case(token, escape_list, +1); + invert_buffer_case(token, escape_intervals, +1); } } if (external_symbol) { x = ecl_find_symbol(token, p, &intern_flag); unlikely_if (intern_flag != ECL_EXTERNAL) { + ecl_free_stack(escape_intervals); + si_put_buffer_string(token); FEreader_error("Cannot find the external symbol ~A in ~S.", in, 2, cl_copy_seq(token), p); } @@ -315,9 +326,9 @@ ecl_read_token(cl_object in, int flags, bool escape_first_p) x = ecl_intern(token, p, &intern_flag); } OUTPUT: + ecl_free_stack(escape_intervals); si_put_buffer_string(token); - the_env->nvalues = 1; - return x; + ecl_return1(the_env, x); } cl_object