diff options
Diffstat (limited to 'libguile/print.c')
-rw-r--r-- | libguile/print.c | 340 |
1 files changed, 238 insertions, 102 deletions
diff --git a/libguile/print.c b/libguile/print.c index 1852cf19a..3bb6cb167 100644 --- a/libguile/print.c +++ b/libguile/print.c @@ -1,18 +1,19 @@ /* Copyright (C) 1995-1999,2000,2001, 2002, 2003, 2004, 2006, 2008, 2009 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 as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA */ @@ -22,6 +23,8 @@ #endif #include <errno.h> +#include <uniconv.h> +#include <unictype.h> #include "libguile/_scm.h" #include "libguile/chars.h" @@ -32,7 +35,7 @@ #include "libguile/procprop.h" #include "libguile/read.h" #include "libguile/weaks.h" -#include "libguile/unif.h" +#include "libguile/programs.h" #include "libguile/alist.h" #include "libguile/struct.h" #include "libguile/objects.h" @@ -291,13 +294,12 @@ print_circref (SCM port, scm_print_state *pstate, SCM ref) /* Print the name of a symbol. */ static int -quote_keywordish_symbol (const char *str, size_t len) +quote_keywordish_symbol (SCM symbol) { SCM option; - /* LEN is guaranteed to be > 0. - */ - if (str[0] != ':' && str[len-1] != ':') + if (scm_i_symbol_ref (symbol, 0) != ':' + && scm_i_symbol_ref (symbol, scm_i_symbol_length (symbol) - 1) != ':') return 0; option = SCM_PRINT_KEYWORD_STYLE; @@ -309,7 +311,7 @@ quote_keywordish_symbol (const char *str, size_t len) } void -scm_print_symbol_name (const char *str, size_t len, SCM port) +scm_i_print_symbol_name (SCM str, SCM port) { /* This points to the first character that has not yet been written to the * port. */ @@ -330,18 +332,20 @@ scm_print_symbol_name (const char *str, size_t len, SCM port) * simpler and faster. */ int maybe_weird = 0; size_t mw_pos = 0; + size_t len = scm_i_symbol_length (str); + scm_t_wchar str0 = scm_i_symbol_ref (str, 0); - if (len == 0 || str[0] == '\'' || str[0] == '`' || str[0] == ',' - || quote_keywordish_symbol (str, len) - || (str[0] == '.' && len == 1) - || scm_is_true (scm_c_locale_stringn_to_number (str, len, 10))) + if (len == 0 || str0 == '\'' || str0 == '`' || str0 == ',' + || quote_keywordish_symbol (str) + || (str0 == '.' && len == 1) + || scm_is_true (scm_i_string_to_number (scm_symbol_to_string (str), 10))) { scm_lfwrite ("#{", 2, port); weird = 1; } for (end = pos; end < len; ++end) - switch (str[end]) + switch (scm_i_symbol_ref (str, end)) { #ifdef BRACKETS_AS_PARENS case '[': @@ -366,11 +370,11 @@ scm_print_symbol_name (const char *str, size_t len, SCM port) weird = 1; } if (pos < end) - scm_lfwrite (str + pos, end - pos, port); + scm_lfwrite_substr (scm_symbol_to_string (str), pos, end, port); { char buf[2]; buf[0] = '\\'; - buf[1] = str[end]; + buf[1] = (char) (unsigned char) scm_i_symbol_ref (str, end); scm_lfwrite (buf, 2, port); } pos = end + 1; @@ -388,11 +392,18 @@ scm_print_symbol_name (const char *str, size_t len, SCM port) break; } if (pos < end) - scm_lfwrite (str + pos, end - pos, port); + scm_lfwrite_substr (scm_symbol_to_string (str), pos, end, port); if (weird) scm_lfwrite ("}#", 2, port); } +void +scm_print_symbol_name (const char *str, size_t len, SCM port) +{ + SCM symbol = scm_from_locale_symboln (str, len); + return scm_i_print_symbol_name (symbol, port); +} + /* Print generally. Handles both write and display according to PSTATE. */ SCM_GPROC(s_write, "write", 1, 1, 0, scm_write, g_write); @@ -435,24 +446,66 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate) case scm_tc3_imm24: if (SCM_CHARP (exp)) { - long i = SCM_CHAR (exp); + scm_t_wchar i = SCM_CHAR (exp); + const char *name; if (SCM_WRITINGP (pstate)) { scm_puts ("#\\", port); - if ((i >= 0) && (i <= ' ') && scm_charnames[i]) - scm_puts (scm_charnames[i], port); -#ifndef EBCDIC - else if (i == '\177') - scm_puts (scm_charnames[scm_n_charnames - 1], port); -#endif - else if (i < 0 || i > '\177') - scm_intprint (i, 8, port); - else - scm_putc (i, port); + name = scm_i_charname (exp); + if (name != NULL) + scm_puts (name, port); + else if (uc_is_general_category_withtable (i, UC_CATEGORY_MASK_L + | UC_CATEGORY_MASK_M + | UC_CATEGORY_MASK_N + | UC_CATEGORY_MASK_P + | UC_CATEGORY_MASK_S)) + /* Print the character if is graphic character. */ + { + scm_t_wchar *wbuf; + SCM wstr = scm_i_make_wide_string (1, &wbuf); + char *buf; + size_t len; + const char *enc; + + enc = scm_i_get_port_encoding (port); + wbuf[0] = i; + if (enc == NULL) + { + if (i <= 0xFF) + /* Character is graphic and Latin-1. Print it */ + scm_lfwrite_str (wstr, port); + else + /* Character is graphic but unrepresentable in + this port's encoding. */ + scm_intprint (i, 8, port); + } + else + { + buf = u32_conv_to_encoding (enc, + iconveh_error, + (scm_t_uint32 *) wbuf, + 1, + NULL, + NULL, &len); + if (buf != NULL) + { + /* Character is graphic. Print it. */ + scm_lfwrite_str (wstr, port); + free (buf); + } + else + /* Character is graphic but unrepresentable in + this port's encoding. */ + scm_intprint (i, 8, port); + } + } + else + /* Character is a non-graphical character. */ + scm_intprint (i, 8, port); } else - scm_putc (i, port); + scm_i_charprint (i, port); } else if (SCM_IFLAGP (exp) && ((size_t) SCM_IFLAGNUM (exp) < (sizeof iflagnames / sizeof (char *)))) @@ -545,63 +598,128 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate) break; } break; - case scm_tc7_string: - if (SCM_WRITINGP (pstate)) - { - size_t i, j, len; - const char *data; - - scm_putc ('"', port); - len = scm_i_string_length (exp); - data = scm_i_string_chars (exp); - for (i = 0, j = 0; i < len; ++i) - { - unsigned char ch = data[i]; - if ((ch < 32 && ch != '\n') || (127 <= ch && ch < 148)) - { - static char const hex[]="0123456789abcdef"; - char buf[4]; - - scm_lfwrite (data+j, i-j, port); - buf[0] = '\\'; - buf[1] = 'x'; - buf[2] = hex [ch / 16]; - buf[3] = hex [ch % 16]; - scm_lfwrite (buf, 4, port); - data = scm_i_string_chars (exp); - j = i+1; - } - else if (ch == '"' || ch == '\\') - { - scm_lfwrite (data+j, i-j, port); - scm_putc ('\\', port); - data = scm_i_string_chars (exp); - j = i; - } - } - scm_lfwrite (data+j, i-j, port); - scm_putc ('"', port); - scm_remember_upto_here_1 (exp); - } - else - scm_lfwrite (scm_i_string_chars (exp), scm_i_string_length (exp), - port); - scm_remember_upto_here_1 (exp); - break; + case scm_tc7_string: + if (SCM_WRITINGP (pstate)) + { + size_t i, j, len; + static char const hex[] = "0123456789abcdef"; + char buf[8]; + + + scm_putc ('"', port); + len = scm_i_string_length (exp); + for (i = 0; i < len; ++i) + { + scm_t_wchar ch = scm_i_string_ref (exp, i); + int printed = 0; + + if (ch == ' ' || ch == '\n') + { + scm_putc (ch, port); + printed = 1; + } + else if (ch == '"' || ch == '\\') + { + scm_putc ('\\', port); + scm_i_charprint (ch, port); + printed = 1; + } + else + if (uc_is_general_category_withtable + (ch, + UC_CATEGORY_MASK_L | UC_CATEGORY_MASK_M | + UC_CATEGORY_MASK_N | UC_CATEGORY_MASK_P | + UC_CATEGORY_MASK_S)) + { + /* Print the character since it is a graphic + character. */ + scm_t_wchar *wbuf; + SCM wstr = scm_i_make_wide_string (1, &wbuf); + char *buf; + size_t len; + + if (scm_i_get_port_encoding (port)) + { + wstr = scm_i_make_wide_string (1, &wbuf); + wbuf[0] = ch; + buf = u32_conv_to_encoding (scm_i_get_port_encoding (port), + iconveh_error, + (scm_t_uint32 *) wbuf, + 1 , + NULL, + NULL, &len); + if (buf != NULL) + { + /* Character is graphic and representable in + this encoding. Print it. */ + scm_lfwrite_str (wstr, port); + free (buf); + printed = 1; + } + } + else + if (ch <= 0xFF) + { + scm_putc (ch, port); + printed = 1; + } + } + + if (!printed) + { + /* Character is graphic but unrepresentable in + this port's encoding or is not graphic. */ + if (ch <= 0xFF) + { + buf[0] = '\\'; + buf[1] = 'x'; + buf[2] = hex[ch / 16]; + buf[3] = hex[ch % 16]; + scm_lfwrite (buf, 4, port); + } + else if (ch <= 0xFFFF) + { + buf[0] = '\\'; + buf[1] = 'u'; + buf[2] = hex[(ch & 0xF000) >> 12]; + buf[3] = hex[(ch & 0xF00) >> 8]; + buf[4] = hex[(ch & 0xF0) >> 4]; + buf[5] = hex[(ch & 0xF)]; + scm_lfwrite (buf, 6, port); + j = i + 1; + } + else if (ch > 0xFFFF) + { + buf[0] = '\\'; + buf[1] = 'U'; + buf[2] = hex[(ch & 0xF00000) >> 20]; + buf[3] = hex[(ch & 0xF0000) >> 16]; + buf[4] = hex[(ch & 0xF000) >> 12]; + buf[5] = hex[(ch & 0xF00) >> 8]; + buf[6] = hex[(ch & 0xF0) >> 4]; + buf[7] = hex[(ch & 0xF)]; + scm_lfwrite (buf, 8, port); + j = i + 1; + } + } + } + scm_putc ('"', port); + scm_remember_upto_here_1 (exp); + } + else + scm_lfwrite_str (exp, port); + scm_remember_upto_here_1 (exp); + break; case scm_tc7_symbol: if (scm_i_symbol_is_interned (exp)) { - scm_print_symbol_name (scm_i_symbol_chars (exp), - scm_i_symbol_length (exp), - port); + scm_i_print_symbol_name (exp, port); scm_remember_upto_here_1 (exp); } else { scm_puts ("#<uninterned-symbol ", port); - scm_print_symbol_name (scm_i_symbol_chars (exp), - scm_i_symbol_length (exp), - port); + scm_i_print_symbol_name (exp, port); scm_putc (' ', port); scm_uintprint (SCM_UNPACK (exp), 16, port); scm_putc ('>', port); @@ -610,6 +728,9 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate) case scm_tc7_variable: scm_i_variable_print (exp, port, pstate); break; + case scm_tc7_program: + scm_i_program_print (exp, port, pstate); + break; case scm_tc7_wvect: ENTER_NESTED_DATA (pstate, exp, circref); if (SCM_IS_WHVEC (exp)) @@ -618,6 +739,9 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate) scm_puts ("#w(", port); goto common_vector_printer; + case scm_tc7_bytevector: + scm_i_print_bytevector (exp, port, pstate); + break; case scm_tc7_vector: ENTER_NESTED_DATA (pstate, exp, circref); scm_puts ("#(", port); @@ -664,14 +788,16 @@ iprin1 (SCM exp, SCM port, scm_print_state *pstate) EXIT_NESTED_DATA (pstate); break; case scm_tcs_subrs: - scm_puts (SCM_SUBR_GENERIC (exp) - ? "#<primitive-generic " - : "#<primitive-procedure ", - port); - scm_puts (scm_i_symbol_chars (SCM_SNAME (exp)), port); - scm_putc ('>', port); - break; - + { + SCM name = scm_symbol_to_string (SCM_SUBR_NAME (exp)); + scm_puts (SCM_SUBR_GENERIC (exp) + ? "#<primitive-generic " + : "#<primitive-procedure ", + port); + scm_lfwrite_str (name, port); + scm_putc ('>', port); + break; + } case scm_tc7_pws: scm_puts ("#<procedure-with-setter", port); { @@ -763,6 +889,17 @@ scm_prin1 (SCM exp, SCM port, int writingp) } } +/* Print a character. + */ +void +scm_i_charprint (scm_t_wchar ch, SCM port) +{ + scm_t_wchar *wbuf; + SCM wstr = scm_i_make_wide_string (1, &wbuf); + + wbuf[0] = ch; + scm_lfwrite_str (wstr, port); +} /* Print an integer. */ @@ -977,9 +1114,7 @@ SCM_DEFINE (scm_simple_format, "simple-format", 2, 0, 1, SCM port, answer = SCM_UNSPECIFIED; int fReturnString = 0; int writingp; - const char *start; - const char *end; - const char *p; + size_t start, p, end; if (scm_is_eq (destination, SCM_BOOL_T)) { @@ -1002,15 +1137,16 @@ SCM_DEFINE (scm_simple_format, "simple-format", 2, 0, 1, SCM_VALIDATE_STRING (2, message); SCM_VALIDATE_REST_ARGUMENT (args); - start = scm_i_string_chars (message); - end = start + scm_i_string_length (message); + p = 0; + start = 0; + end = scm_i_string_length (message); for (p = start; p != end; ++p) - if (*p == '~') + if (scm_i_string_ref (message, p) == '~') { if (++p == end) break; - switch (*p) + switch (scm_i_string_ref (message, p)) { case 'A': case 'a': writingp = 0; @@ -1019,33 +1155,33 @@ SCM_DEFINE (scm_simple_format, "simple-format", 2, 0, 1, writingp = 1; break; case '~': - scm_lfwrite (start, p - start, port); + scm_lfwrite_substr (message, start, p, port); start = p + 1; continue; case '%': - scm_lfwrite (start, p - start - 1, port); + scm_lfwrite_substr (message, start, p - 1, port); scm_newline (port); start = p + 1; continue; default: SCM_MISC_ERROR ("FORMAT: Unsupported format option ~~~A - use (ice-9 format) instead", - scm_list_1 (SCM_MAKE_CHAR (*p))); + scm_list_1 (SCM_MAKE_CHAR (scm_i_string_ref (message, p)))); } if (!scm_is_pair (args)) SCM_MISC_ERROR ("FORMAT: Missing argument for ~~~A", - scm_list_1 (SCM_MAKE_CHAR (*p))); + scm_list_1 (SCM_MAKE_CHAR (scm_i_string_ref (message, p)))); - scm_lfwrite (start, p - start - 1, port); + scm_lfwrite_substr (message, start, p - 1, port); /* we pass destination here */ scm_prin1 (SCM_CAR (args), destination, writingp); args = SCM_CDR (args); start = p + 1; } - scm_lfwrite (start, p - start, port); + scm_lfwrite_substr (message, start, p, port); if (!scm_is_eq (args, SCM_EOL)) SCM_MISC_ERROR ("FORMAT: ~A superfluous arguments", scm_list_1 (scm_length (args))); |