summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2011-04-25 23:17:52 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2011-04-25 23:17:52 -0700
commit671875dac181f7f1337f21d013a9c3d5f235ddf2 (patch)
tree4091c2537439713df8efe8d3376116a6db3eb1c5 /src
parentf904488ff40dcee3e340b63a6386dde124d1241c (diff)
parent0c6b7b19e52ba18b5d4fd2d4b73b133a0a721603 (diff)
downloademacs-671875dac181f7f1337f21d013a9c3d5f235ddf2.tar.gz
Merge from mainline.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog178
-rw-r--r--src/Makefile.in6
-rw-r--r--src/buffer.c3
-rw-r--r--src/callint.c7
-rw-r--r--src/character.c35
-rw-r--r--src/charset.c10
-rw-r--r--src/coding.c4
-rw-r--r--src/deps.mk4
-rw-r--r--src/dispextern.h2
-rw-r--r--src/doc.c4
-rw-r--r--src/doprnt.c193
-rw-r--r--src/eval.c30
-rw-r--r--src/font.c6
-rw-r--r--src/gnutls.c360
-rw-r--r--src/gnutls.h2
-rw-r--r--src/lisp.h3
-rw-r--r--src/makefile.w32-in16
-rw-r--r--src/msdos.c12
-rw-r--r--src/msdos.h8
-rw-r--r--src/process.c16
-rw-r--r--src/s/ms-w32.h1
-rw-r--r--src/syntax.c2
-rw-r--r--src/sysdep.c2
-rw-r--r--src/term.c4
-rw-r--r--src/textprop.c14
-rw-r--r--src/w32.c91
-rw-r--r--src/w32.h12
-rw-r--r--src/xdisp.c27
-rw-r--r--src/xfaces.c2
29 files changed, 859 insertions, 195 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 87e703b3dab..6614375a7c6 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,4 +1,4 @@
-2011-04-25 Paul Eggert <eggert@cs.ucla.edu>
+2011-04-26 Paul Eggert <eggert@cs.ucla.edu>
lisp.h: Fix a problem with aliasing and vector headers.
GCC 4.6.0 optimizes based on type-based alias analysis. For
@@ -50,12 +50,8 @@
* process.c (Fformat_network_address): Use local var for size,
for brevity.
-2011-04-24 Paul Eggert <eggert@cs.ucla.edu>
-
* bytecode.c (exec_byte_code): Don't use XVECTOR before CHECK_VECTOR.
-2011-04-21 Paul Eggert <eggert@cs.ucla.edu>
-
Make the Lisp reader and string-to-float more consistent.
* data.c (atof): Remove decl; no longer used or needed.
(digit_to_number): Move to lread.c.
@@ -86,8 +82,6 @@
so that overflow for non-base-10 numbers is reported only when
there's no portable and simple way to convert to floating point.
-2011-04-20 Paul Eggert <eggert@cs.ucla.edu>
-
* textprop.c (set_text_properties_1): Rewrite for clarity,
and to avoid GCC warning about integer overflow.
@@ -188,6 +182,176 @@
alignof(EMACS_INT) < sizeof (EMACS_INT).
(check_sblock, check_string_bytes, check_string_free_list): Protoize.
+2011-04-25 Dan Nicolaescu <dann@ics.uci.edu>
+
+ * alloc.c (check_sblock, check_string_bytes)
+ (check_string_free_list): Convert to standard C.
+
+2011-04-25 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * w32.c (emacs_gnutls_push): Fix typo.
+
+2011-04-25 Eli Zaretskii <eliz@gnu.org>
+
+ * gnutls.c (emacs_gnutls_handshake): Avoid compiler warnings about
+ "cast to pointer from integer of different size".
+
+ Improve doprnt and its use in verror. (Bug#8545)
+ * doprnt.c (doprnt): Document the set of format control sequences
+ supported by the function. Use SAFE_ALLOCA instead of always
+ using `alloca'.
+
+ * eval.c (verror): Don't limit the buffer size at size_max-1, that
+ is one byte too soon. Don't use xrealloc; instead xfree and
+ xmalloc anew.
+
+2011-04-24 Teodor Zlatanov <tzz@lifelogs.com>
+
+ * gnutls.h: Add GNUTLS_STAGE_CALLBACKS enum to denote we're in the
+ callbacks stage.
+
+ * gnutls.c: Renamed global_initialized to
+ gnutls_global_initialized. Added internals for the
+ :verify-hostname-error, :verify-error, and :verify-flags
+ parameters of `gnutls-boot' and documented those parameters in the
+ docstring. Start callback support.
+ (emacs_gnutls_handshake): Add Woe32 support. Retry handshake
+ unless a fatal error occured. Call gnutls_alert_send_appropriate
+ on error. Return error code.
+ (emacs_gnutls_write): Call emacs_gnutls_handle_error.
+ (emacs_gnutls_read): Likewise.
+ (Fgnutls_boot): Return handshake error code.
+ (emacs_gnutls_handle_error): New function.
+ (wsaerror_to_errno): Likewise.
+
+ * w32.h (emacs_gnutls_pull): Add prototype.
+ (emacs_gnutls_push): Likewise.
+
+ * w32.c (emacs_gnutls_pull): New function for GnuTLS on Woe32.
+ (emacs_gnutls_push): Likewise.
+
+2011-04-24 Claudio Bley <claudio.bley@gmail.com> (tiny change)
+
+ * process.c (wait_reading_process_output): Check if GnuTLS
+ buffered some data internally if no FDs are set for TLS
+ connections.
+
+ * makefile.w32-in (OBJ2): Add gnutls.$(O).
+ (LIBS): Link to USER_LIBS.
+ ($(BLD)/gnutls.$(0)): New target.
+
+2011-04-24 Eli Zaretskii <eliz@gnu.org>
+
+ * xdisp.c (handle_single_display_spec): Rename the
+ display_replaced_before_p argument into display_replaced_p, to
+ make it consistent with the commentary. Fix typos in the
+ commentary.
+
+ * textprop.c (syms_of_textprop): Remove dead code.
+ (copy_text_properties): Delete obsolete commentary about an
+ interface that was deleted long ago. Fix typos in the description
+ of arguments.
+
+ * msdos.c (XMenuActivate, XMenuAddSelection): Adjust argument list
+ to changes in oldXMenu/XMenu.h from 2011-04-16.
+ <menu_help_message, prev_menu_help_message>: Constify.
+ (IT_menu_make_room): menu->help_text is now `const char **';
+ adjust.
+
+ * msdos.h (XMenuActivate, XMenuAddSelection): Adjust prototypes
+ to changes in oldXMenu/XMenu.h from 2011-04-16.
+ (struct XMenu): Declare `help_text' `const char **'.
+
+ * xfaces.c <Qunspecified>: Make extern again.
+
+ * syntax.c: Include sys/types.h before including regex.h, as
+ required by Posix.
+
+ * doc.c (get_doc_string): Improve the format passed to `error'.
+
+ * doprnt.c (doprnt): Improve commentary.
+
+ * term.c (init_tty) [MSDOS]: Fix 1st argument to maybe_fatal.
+
+ * Makefile.in (TAGS): Depend on $(M_FILE) and $(S_FILE), and scan
+ them with etags.
+
+ * makefile.w32-in (globals.h): Add a dummy recipe, to make any
+ changes in globals.h immediately force recompilation.
+ (TAGS): Depend on $(CURDIR)/m/intel386.h and
+ $(CURDIR)/s/ms-w32.h.
+ (TAGS-gmake): Scan $(CURDIR)/m/intel386.h and $(CURDIR)/s/ms-w32.h.
+
+ * character.c (Fchar_direction): Function deleted.
+ (syms_of_character): Don't defsubr it.
+ <char-direction-table>: Deleted.
+
+2011-04-23 Eli Zaretskii <eliz@gnu.org>
+
+ Fix doprnt so it could be used again safely in `verror'. (Bug#8435)
+ * doprnt.c: Include limits.h.
+ (SIZE_MAX): New macro.
+ (doprnt): Return a size_t value. 2nd arg is now size_t. Many
+ local variables are now size_t instead of int or unsigned.
+ Improve overflow protection. Support `l' modifier for integer
+ conversions. Support %l conversion. Don't assume an EMACS_INT
+ argument for integer conversions and for %c.
+
+ * lisp.h (doprnt): Restore prototype.
+
+ * makefile.w32-in ($(BLD)/callint.$(O)): Depend on
+ $(SRC)/character.h.
+
+ * Makefile.in (base_obj): Add back doprnt.o.
+
+ * deps.mk (doprnt.o): Add back prerequisites.
+ (callint.o): Depend on character.h.
+
+ * eval.c (internal_lisp_condition_case): Include the handler
+ representation in the error message.
+ (verror): Call doprnt instead of vsnprintf. Fix an off-by-one bug
+ when breaking from the loop.
+
+ * xdisp.c (vmessage): Call doprnt instead of vsnprintf.
+
+ * callint.c (Fcall_interactively): When displaying error message
+ about invalid control letter, pass the character's codepoint, not
+ a pointer to its multibyte form. Improve display of the character
+ in octal and display also its hex code.
+
+ * character.c (char_string): Use %x to display the (unsigned)
+ codepoint of an invalid character, to avoid displaying a bogus
+ negative value.
+
+ * font.c (check_otf_features): Pass SDATA of SYMBOL_NAME to
+ `error', not SYMBOL_NAME itself.
+
+ * coding.c (Fencode_sjis_char, Fencode_big5_char): Use %c for
+ character arguments to `error'.
+
+ * charset.c (check_iso_charset_parameter): Fix incorrect argument
+ to `error' in error message about FINAL_CHAR argument. Make sure
+ FINAL_CHAR is a character, and use %c when it is passed as
+ argument to `error'.
+
+2011-04-23 Eli Zaretskii <eliz@gnu.org>
+
+ * s/ms-w32.h (localtime): Redirect to sys_localtime.
+
+ * w32.c: Include <time.h>.
+ (sys_localtime): New function.
+
+2011-04-23 Chong Yidong <cyd@stupidchicken.com>
+
+ * xdisp.c (init_xdisp): Initialize echo_area_window (Bug#6451).
+
+ * buffer.c (syms_of_buffer): Doc fix (Bug#6902).
+
+2011-04-23 Samuel Thibault <sthibault@debian.org> (tiny change)
+
+ * sysdep.c (wait_for_termination): On GNU Hurd, kill returns -1 on
+ zombies (Bug#8467).
+
2011-04-19 Eli Zaretskii <eliz@gnu.org>
* syntax.h (SETUP_SYNTAX_TABLE_FOR_OBJECT): Fix setting of
diff --git a/src/Makefile.in b/src/Makefile.in
index 154d6abba4e..8b596430cf5 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -354,7 +354,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
syntax.o $(UNEXEC_OBJ) bytecode.o \
process.o gnutls.o callproc.o \
region-cache.o sound.o atimer.o \
- intervals.o textprop.o composite.o xml.o \
+ doprnt.o intervals.o textprop.o composite.o xml.o \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ)
obj = $(base_obj) $(NS_OBJC_OBJ)
@@ -748,10 +748,10 @@ extraclean: distclean
ctagsfiles1 = [xyzXYZ]*.[hcm]
ctagsfiles2 = [a-wA-W]*.[hcm]
-TAGS: $(srcdir)/$(ctagsfiles1) $(srcdir)/$(ctagsfiles2)
+TAGS: $(srcdir)/$(ctagsfiles1) $(srcdir)/$(ctagsfiles2) $(M_FILE) $(S_FILE)
../lib-src/etags --include=TAGS-LISP --include=$(lwlibdir)/TAGS \
--regex='/[ ]*DEFVAR_[A-Z_ (]+"\([^"]+\)"/' \
- $(srcdir)/$(ctagsfiles1) $(srcdir)/$(ctagsfiles2)
+ $(srcdir)/$(ctagsfiles1) $(srcdir)/$(ctagsfiles2) $(M_FILE) $(S_FILE)
frc:
TAGS-LISP: frc
$(MAKE) -f $(lispdir)/Makefile TAGS-LISP ETAGS=../lib-src/etags
diff --git a/src/buffer.c b/src/buffer.c
index ddaacd93707..d9949045444 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5551,7 +5551,8 @@ Linefeed indents to this column in Fundamental mode. */);
DEFVAR_PER_BUFFER ("tab-width", &BVAR (current_buffer, tab_width),
make_number (LISP_INT_TAG),
- doc: /* *Distance between tab stops (for display of tab characters), in columns. */);
+ doc: /* *Distance between tab stops (for display of tab characters), in columns.
+This should be an integer greater than zero. */);
DEFVAR_PER_BUFFER ("ctl-arrow", &BVAR (current_buffer, ctl_arrow), Qnil,
doc: /* *Non-nil means display control chars with uparrow.
diff --git a/src/callint.c b/src/callint.c
index 44d7a02f6bf..2cc3a7cb537 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "window.h"
#include "keymap.h"
+#include "character.h"
Lisp_Object Qminus, Qplus;
Lisp_Object Qcall_interactively;
@@ -786,8 +787,10 @@ invoke it. If KEYS is omitted or nil, the return value of
if anyone tries to define one here. */
case '+':
default:
- error ("Invalid control letter `%c' (%03o) in interactive calling string",
- *tem, (unsigned char) *tem);
+ error ("Invalid control letter `%c' (#o%03o, #x%04x) in interactive calling string",
+ STRING_CHAR ((unsigned char *) tem),
+ (unsigned) STRING_CHAR ((unsigned char *) tem),
+ (unsigned) STRING_CHAR ((unsigned char *) tem));
}
if (varies[i] == 0)
diff --git a/src/character.c b/src/character.c
index 12888e0f806..64ea2625abb 100644
--- a/src/character.c
+++ b/src/character.c
@@ -156,17 +156,17 @@ char_string (unsigned int c, unsigned char *p)
bytes = BYTE8_STRING (c, p);
}
else
- error ("Invalid character: %d", c);
+ error ("Invalid character: %x", c);
return bytes;
}
-/* Return a character whose multibyte form is at P. Set LEN is not
+/* Return a character whose multibyte form is at P. If LEN is not
NULL, it must be a pointer to integer. In that case, set *LEN to
- the byte length of the multibyte form. If ADVANCED is not NULL, is
+ the byte length of the multibyte form. If ADVANCED is not NULL, it
must be a pointer to unsigned char. In that case, set *ADVANCED to
- the ending address (i.e. the starting address of the next
+ the ending address (i.e., the starting address of the next
character) of the multibyte form. */
int
@@ -206,11 +206,10 @@ string_char (const unsigned char *p, const unsigned char **advanced, int *len)
}
-/* Translate character C by translation table TABLE. If C is
- negative, translate a character specified by CHARSET and CODE. If
- no translation is found in TABLE, return the untranslated
- character. If TABLE is a list, elements are char tables. In this
- case, translace C by all tables. */
+/* Translate character C by translation table TABLE. If no translation is
+ found in TABLE, return the untranslated character. If TABLE is a list,
+ elements are char tables. In that case, recursively translate C by all the
+ tables in the list. */
int
translate_char (Lisp_Object table, int c)
@@ -494,19 +493,6 @@ usage: (string-width STRING) */)
return val;
}
-DEFUN ("char-direction", Fchar_direction, Schar_direction, 1, 1, 0,
- doc: /* Return the direction of CHAR.
-The returned value is 0 for left-to-right and 1 for right-to-left.
-usage: (char-direction CHAR) */)
- (Lisp_Object ch)
-{
- int c;
-
- CHECK_CHARACTER (ch);
- c = XINT (ch);
- return CHAR_TABLE_REF (Vchar_direction_table, c);
-}
-
/* Return the number of characters in the NBYTES bytes at PTR.
This works by looking at the contents and checking for multibyte
sequences while assuming that there's no invalid sequence.
@@ -1038,7 +1024,6 @@ syms_of_character (void)
defsubr (&Smultibyte_char_to_unibyte);
defsubr (&Schar_width);
defsubr (&Sstring_width);
- defsubr (&Schar_direction);
defsubr (&Sstring);
defsubr (&Sunibyte_string);
defsubr (&Schar_resolve_modifiers);
@@ -1067,10 +1052,6 @@ A char-table for width (columns) of each character. */);
char_table_set_range (Vchar_width_table, MAX_5_BYTE_CHAR + 1, MAX_CHAR,
make_number (4));
- DEFVAR_LISP ("char-direction-table", Vchar_direction_table,
- doc: /* A char-table for direction of each character. */);
- Vchar_direction_table = Fmake_char_table (Qnil, make_number (1));
-
DEFVAR_LISP ("printable-chars", Vprintable_chars,
doc: /* A char-table for each printable character. */);
Vprintable_chars = Fmake_char_table (Qnil, Qnil);
diff --git a/src/charset.c b/src/charset.c
index 9a7a56d9379..52c2ebdcc4e 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1436,7 +1436,7 @@ check_iso_charset_parameter (Lisp_Object dimension, Lisp_Object chars, Lisp_Obje
{
CHECK_NATNUM (dimension);
CHECK_NATNUM (chars);
- CHECK_NATNUM (final_char);
+ CHECK_CHARACTER (final_char);
if (XINT (dimension) > 3)
error ("Invalid DIMENSION %"pI"d, it should be 1, 2, or 3",
@@ -1444,12 +1444,8 @@ check_iso_charset_parameter (Lisp_Object dimension, Lisp_Object chars, Lisp_Obje
if (XINT (chars) != 94 && XINT (chars) != 96)
error ("Invalid CHARS %"pI"d, it should be 94 or 96", XINT (chars));
if (XINT (final_char) < '0' || XINT (final_char) > '~')
- {
- unsigned char str[MAX_MULTIBYTE_LENGTH + 1];
- int len = CHAR_STRING (XINT (chars), str);
- str[len] = '\0';
- error ("Invalid FINAL-CHAR %s, it should be `0'..`~'", str);
- }
+ error ("Invalid FINAL-CHAR %c, it should be `0'..`~'",
+ (int)XINT (final_char));
}
diff --git a/src/coding.c b/src/coding.c
index 6cd039a0903..c14a41036ac 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -9071,7 +9071,7 @@ Return the corresponding code in SJIS. */)
charset_list = CODING_ATTR_CHARSET_LIST (attrs);
charset = char_charset (c, charset_list, &code);
if (code == CHARSET_INVALID_CODE (charset))
- error ("Can't encode by shift_jis encoding: %d", c);
+ error ("Can't encode by shift_jis encoding: %c", c);
JIS_TO_SJIS (code);
return make_number (code);
@@ -9142,7 +9142,7 @@ Return the corresponding character code in Big5. */)
charset_list = CODING_ATTR_CHARSET_LIST (attrs);
charset = char_charset (c, charset_list, &code);
if (code == CHARSET_INVALID_CODE (charset))
- error ("Can't encode by Big5 encoding: %d", c);
+ error ("Can't encode by Big5 encoding: %c", c);
return make_number (code);
}
diff --git a/src/deps.mk b/src/deps.mk
index 2df1577ef78..8d0e0e69589 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -44,7 +44,8 @@ buffer.o: buffer.c buffer.h region-cache.h commands.h window.h \
$(INTERVALS_H) blockinput.h atimer.h systime.h character.h ../lib/unistd.h \
indent.h keyboard.h coding.h keymap.h frame.h lisp.h globals.h $(config_h)
callint.o: callint.c window.h commands.h buffer.h keymap.h globals.h msdos.h \
- keyboard.h dispextern.h systime.h coding.h composite.h lisp.h $(config_h)
+ keyboard.h dispextern.h systime.h coding.h composite.h lisp.h \
+ character.h $(config_h)
callproc.o: callproc.c epaths.h buffer.h commands.h lisp.h $(config_h) \
process.h systty.h syssignal.h character.h coding.h ccl.h msdos.h \
composite.h w32.h blockinput.h atimer.h systime.h frame.h termhooks.h \
@@ -82,6 +83,7 @@ dispnew.o: dispnew.c systime.h commands.h process.h frame.h coding.h \
# doc.o's dependency on buildobj.h is in src/Makefile.in.
doc.o: doc.c lisp.h $(config_h) buffer.h keyboard.h keymap.h \
character.h systime.h coding.h composite.h ../lib/unistd.h globals.h
+doprnt.o: doprnt.c character.h lisp.h globals.h ../lib/unistd.h $(config_h)
dosfns.o: buffer.h termchar.h termhooks.h frame.h blockinput.h window.h \
msdos.h dosfns.h dispextern.h charset.h coding.h atimer.h systime.h \
lisp.h $(config_h)
diff --git a/src/dispextern.h b/src/dispextern.h
index 1f2189adeca..72e23e6642a 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -62,7 +62,7 @@ typedef HDC XImagePtr_or_DC;
#ifdef HAVE_NS
#include "nsgui.h"
-/* following typedef needed to accomodate the MSDOS port, believe it or not */
+/* Following typedef needed to accommodate the MSDOS port, believe it or not. */
typedef struct ns_display_info Display_Info;
typedef Pixmap XImagePtr;
typedef XImagePtr XImagePtr_or_DC;
diff --git a/src/doc.c b/src/doc.c
index 29f232e666d..d27fa3f792d 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -253,7 +253,9 @@ get_doc_string (Lisp_Object filepos, int unibyte, int definition)
else if (c == '_')
*to++ = 037;
else
- error ("Invalid data in documentation file -- ^A followed by code 0%o", c);
+ error ("\
+Invalid data in documentation file -- %c followed by code %03o",
+ 1, (unsigned)c);
}
else
*to++ = *from++;
diff --git a/src/doprnt.c b/src/doprnt.c
index 36eb272caae..3ac1d9963a9 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -1,6 +1,6 @@
/* Output like sprintf to a buffer of specified size.
- Also takes args differently: pass one pointer to an array of strings
- in addition to the format string which is separate.
+ Also takes args differently: pass one pointer to the end
+ of the format string in addition to the format string itself.
Copyright (C) 1985, 2001-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -18,6 +18,79 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+/* If you think about replacing this with some similar standard C function of
+ the printf family (such as vsnprintf), please note that this function
+ supports the following Emacs-specific features:
+
+ . For %c conversions, it produces a string with the multibyte representation
+ of the (`int') argument, suitable for display in an Emacs buffer.
+
+ . For %s and %c, when field width is specified (e.g., %25s), it accounts for
+ the diplay width of each character, according to char-width-table. That
+ is, it does not assume that each character takes one column on display.
+
+ . If the size of the buffer is not enough to produce the formatted string in
+ its entirety, it makes sure that truncation does not chop the last
+ character in the middle of its multibyte sequence, producing an invalid
+ sequence.
+
+ . It accepts a pointer to the end of the format string, so the format string
+ could include embedded null characters.
+
+ . It signals an error if the length of the formatted string is about to
+ overflow MOST_POSITIVE_FIXNUM, to avoid producing strings longer than what
+ Emacs can handle.
+
+ OTOH, this function supports only a small subset of the standard C formatted
+ output facilities. E.g., %u and %ll are not supported, and precision is
+ ignored %s and %c conversions. (See below for the detailed documentation of
+ what is supported.) However, this is okay, as this function is supposed to
+ be called from `error' and similar functions, and thus does not need to
+ support features beyond those in `Fformat', which is used by `error' on the
+ Lisp level. */
+
+/* This function supports the following %-sequences in the `format'
+ argument:
+
+ %s means print a string argument.
+ %S is silently treated as %s, for loose compatibility with `Fformat'.
+ %d means print a `signed int' argument in decimal.
+ %l means print a `long int' argument in decimal.
+ %o means print an `unsigned int' argument in octal.
+ %x means print an `unsigned int' argument in hex.
+ %e means print a `double' argument in exponential notation.
+ %f means print a `double' argument in decimal-point notation.
+ %g means print a `double' argument in exponential notation
+ or in decimal-point notation, whichever uses fewer characters.
+ %c means print a `signed int' argument as a single character.
+ %% means produce a literal % character.
+
+ A %-sequence may contain optional flag, width, and precision specifiers, as
+ follows:
+
+ %<flags><width><precision>character
+
+ where flags is [+ -0l], width is [0-9]+, and precision is .[0-9]+
+
+ The + flag character inserts a + before any positive number, while a space
+ inserts a space before any positive number; these flags only affect %d, %l,
+ %o, %x, %e, %f, and %g sequences. The - and 0 flags affect the width
+ specifier, as described below.
+
+ The l (lower-case letter ell) flag is a `long' data type modifier: it is
+ supported for %d, %o, and %x conversions of integral arguments, and means
+ that the respective argument is to be treated as `long int' or `unsigned
+ long int'. The EMACS_INT data type should use this modifier.
+
+ The width specifier supplies a lower limit for the length of the printed
+ representation. The padding, if any, normally goes on the left, but it goes
+ on the right if the - flag is present. The padding character is normally a
+ space, but (for numerical arguments only) it is 0 if the 0 flag is present.
+ The - flag takes precedence over the 0 flag.
+
+ For %e, %f, and %g sequences, the number after the "." in the precision
+ specifier says how many decimal places to show; if zero, the decimal point
+ itself is omitted. For %s and %S, the precision specifier is ignored. */
#include <config.h>
#include <stdio.h>
@@ -30,6 +103,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
+#include <limits.h>
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
#include "lisp.h"
/* Since we use the macro CHAR_HEAD_P, we have to include this, but
@@ -45,14 +123,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
terminated at position FORMAT_END.
Output goes in BUFFER, which has room for BUFSIZE chars.
If the output does not fit, truncate it to fit.
- Returns the number of bytes stored into BUFFER.
- ARGS points to the vector of arguments, and NARGS says how many.
- A double counts as two arguments.
+ Returns the number of bytes stored into BUFFER, excluding
+ the terminating null byte. Output is always null-terminated.
String arguments are passed as C strings.
Integers are passed as C integers. */
-EMACS_INT
-doprnt (char *buffer, register int bufsize, const char *format,
+size_t
+doprnt (char *buffer, register size_t bufsize, const char *format,
const char *format_end, va_list ap)
{
const char *fmt = format; /* Pointer into format string */
@@ -62,20 +139,21 @@ doprnt (char *buffer, register int bufsize, const char *format,
char tembuf[DBL_MAX_10_EXP + 100];
/* Size of sprintf_buffer. */
- unsigned size_allocated = sizeof (tembuf);
+ size_t size_allocated = sizeof (tembuf);
/* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */
char *sprintf_buffer = tembuf;
/* Buffer we have got with malloc. */
- char *big_buffer = 0;
+ char *big_buffer = NULL;
- register int tem;
+ register size_t tem;
char *string;
char fixed_buffer[20]; /* Default buffer for small formatting. */
char *fmtcpy;
int minlen;
char charbuf[MAX_MULTIBYTE_LENGTH + 1]; /* Used for %c. */
+ USE_SAFE_ALLOCA;
if (format_end == 0)
format_end = format + strlen (format);
@@ -83,7 +161,7 @@ doprnt (char *buffer, register int bufsize, const char *format,
if ((format_end - format + 1) < sizeof (fixed_buffer))
fmtcpy = fixed_buffer;
else
- fmtcpy = (char *) alloca (format_end - format + 1);
+ SAFE_ALLOCA (fmtcpy, char *, format_end - format + 1);
bufsize--;
@@ -92,8 +170,9 @@ doprnt (char *buffer, register int bufsize, const char *format,
{
if (*fmt == '%') /* Check for a '%' character */
{
- unsigned size_bound = 0;
- EMACS_INT width; /* Columns occupied by STRING. */
+ size_t size_bound = 0;
+ EMACS_INT width; /* Columns occupied by STRING on display. */
+ int long_flag = 0;
fmt++;
/* Copy this one %-spec into fmtcpy. */
@@ -108,10 +187,11 @@ doprnt (char *buffer, register int bufsize, const char *format,
This might be a field width or a precision; e.g.
%1.1000f and %1000.1f both might need 1000+ bytes.
Parse the width or precision, checking for overflow. */
- unsigned n = *fmt - '0';
+ size_t n = *fmt - '0';
while ('0' <= fmt[1] && fmt[1] <= '9')
{
- if (n * 10 + fmt[1] - '0' < n)
+ if (n >= SIZE_MAX / 10
+ || n * 10 > SIZE_MAX - (fmt[1] - '0'))
error ("Format width or precision too large");
n = n * 10 + fmt[1] - '0';
*string++ = *++fmt;
@@ -122,6 +202,13 @@ doprnt (char *buffer, register int bufsize, const char *format,
}
else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || *fmt == '+')
;
+ else if (*fmt == 'l')
+ {
+ long_flag = 1;
+ if (!strchr ("dox", fmt[1]))
+ /* %l as conversion specifier, not as modifier. */
+ break;
+ }
else
break;
fmt++;
@@ -130,7 +217,7 @@ doprnt (char *buffer, register int bufsize, const char *format,
/* Make the size bound large enough to handle floating point formats
with large numbers. */
- if (size_bound + DBL_MAX_10_EXP + 50 < size_bound)
+ if (size_bound > SIZE_MAX - DBL_MAX_10_EXP - 50)
error ("Format width or precision too large");
size_bound += DBL_MAX_10_EXP + 50;
@@ -151,23 +238,47 @@ doprnt (char *buffer, register int bufsize, const char *format,
error ("Invalid format operation %%%c", fmt[-1]);
/* case 'b': */
+ case 'l':
case 'd':
+ {
+ int i;
+ long l;
+
+ if (long_flag)
+ {
+ l = va_arg(ap, long);
+ sprintf (sprintf_buffer, fmtcpy, l);
+ }
+ else
+ {
+ i = va_arg(ap, int);
+ sprintf (sprintf_buffer, fmtcpy, i);
+ }
+ /* Now copy into final output, truncating as necessary. */
+ string = sprintf_buffer;
+ goto doit;
+ }
+
case 'o':
case 'x':
- if (sizeof (int) == sizeof (EMACS_INT))
- ;
- else if (sizeof (long) == sizeof (EMACS_INT))
- /* Insert an `l' the right place. */
- string[1] = string[0],
- string[0] = string[-1],
- string[-1] = 'l',
- string++;
- else
- abort ();
- sprintf (sprintf_buffer, fmtcpy, va_arg(ap, char *));
- /* Now copy into final output, truncating as nec. */
- string = sprintf_buffer;
- goto doit;
+ {
+ unsigned u;
+ unsigned long ul;
+
+ if (long_flag)
+ {
+ ul = va_arg(ap, unsigned long);
+ sprintf (sprintf_buffer, fmtcpy, ul);
+ }
+ else
+ {
+ u = va_arg(ap, unsigned);
+ sprintf (sprintf_buffer, fmtcpy, u);
+ }
+ /* Now copy into final output, truncating as necessary. */
+ string = sprintf_buffer;
+ goto doit;
+ }
case 'f':
case 'e':
@@ -175,7 +286,7 @@ doprnt (char *buffer, register int bufsize, const char *format,
{
double d = va_arg(ap, double);
sprintf (sprintf_buffer, fmtcpy, d);
- /* Now copy into final output, truncating as nec. */
+ /* Now copy into final output, truncating as necessary. */
string = sprintf_buffer;
goto doit;
}
@@ -187,13 +298,18 @@ doprnt (char *buffer, register int bufsize, const char *format,
minlen = atoi (&fmtcpy[1]);
string = va_arg (ap, char *);
tem = strlen (string);
+ if (tem > MOST_POSITIVE_FIXNUM)
+ error ("String for %%s or %%S format is too long");
width = strwidth (string, tem);
goto doit1;
/* Copy string into final output, truncating if no room. */
doit:
/* Coming here means STRING contains ASCII only. */
- width = tem = strlen (string);
+ tem = strlen (string);
+ if (tem > MOST_POSITIVE_FIXNUM)
+ error ("Format width or precision too large");
+ width = tem;
doit1:
/* We have already calculated:
TEM -- length of STRING,
@@ -236,13 +352,8 @@ doprnt (char *buffer, register int bufsize, const char *format,
case 'c':
{
- /* Sometimes for %c we pass a char, which would widen
- to int. Sometimes we pass XFASTINT() or XINT()
- values, which would be EMACS_INT. Let's hope that
- both are passed the same way, otherwise we'll need
- to rewrite callers. */
- EMACS_INT chr = va_arg(ap, EMACS_INT);
- tem = CHAR_STRING ((int) chr, (unsigned char *) charbuf);
+ int chr = va_arg(ap, int);
+ tem = CHAR_STRING (chr, (unsigned char *) charbuf);
string = charbuf;
string[tem] = 0;
width = strwidth (string, tem);
@@ -274,6 +385,8 @@ doprnt (char *buffer, register int bufsize, const char *format,
/* If we had to malloc something, free it. */
xfree (big_buffer);
- *bufptr = 0; /* Make sure our string end with a '\0' */
+ *bufptr = 0; /* Make sure our string ends with a '\0' */
+
+ SAFE_FREE ();
return bufptr - buffer;
}
diff --git a/src/eval.c b/src/eval.c
index b843ca5b2ec..d1f327021e6 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1416,7 +1416,8 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
|| (CONSP (tem)
&& (SYMBOLP (XCAR (tem))
|| CONSP (XCAR (tem))))))
- error ("Invalid condition handler");
+ error ("Invalid condition handler: %s",
+ SDATA (Fprin1_to_string (tem, Qt)));
}
c.tag = Qnil;
@@ -1995,27 +1996,26 @@ verror (const char *m, va_list ap)
size_t size = sizeof buf;
size_t size_max =
min (MOST_POSITIVE_FIXNUM, min (INT_MAX, SIZE_MAX - 1)) + 1;
+ size_t mlen = strlen (m);
char *buffer = buf;
- int used;
+ size_t used;
Lisp_Object string;
while (1)
{
- used = vsnprintf (buffer, size, m, ap);
+ used = doprnt (buffer, size, m, m + mlen, ap);
- if (used < 0)
- {
- /* Non-C99 vsnprintf, such as w32, returns -1 when SIZE is too small.
- Guess a larger USED to work around the incompatibility. */
- used = (size <= size_max / 2 ? 2 * size
- : size < size_max ? size_max - 1
- : size_max);
- }
- else if (used < size)
+ /* Note: the -1 below is because `doprnt' returns the number of bytes
+ excluding the terminating null byte, and it always terminates with a
+ null byte, even when producing a truncated message. */
+ if (used < size - 1)
break;
- if (size_max <= used)
- memory_full ();
- size = used + 1;
+ if (size <= size_max / 2)
+ size *= 2;
+ else if (size < size_max)
+ size = size_max;
+ else
+ break; /* and leave the message truncated */
if (buffer != buf)
xfree (buffer);
diff --git a/src/font.c b/src/font.c
index 12b280f6c36..edbdc958539 100644
--- a/src/font.c
+++ b/src/font.c
@@ -1794,14 +1794,16 @@ check_otf_features (otf_features)
{
CHECK_SYMBOL (Fcar (val));
if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
- error ("Invalid OTF GSUB feature: %s", SYMBOL_NAME (XCAR (val)));
+ error ("Invalid OTF GSUB feature: %s",
+ SDATA (SYMBOL_NAME (XCAR (val))));
}
otf_features = XCDR (otf_features);
for (val = Fcar (otf_features); ! NILP (val); val = Fcdr (val))
{
CHECK_SYMBOL (Fcar (val));
if (SBYTES (SYMBOL_NAME (XCAR (val))) > 4)
- error ("Invalid OTF GPOS feature: %s", SYMBOL_NAME (XCAR (val)));
+ error ("Invalid OTF GPOS feature: %s",
+ SDATA (SYMBOL_NAME (XCAR (val))));
}
}
diff --git a/src/gnutls.c b/src/gnutls.c
index 38932c9fa47..ea0a9857035 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -26,11 +26,20 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
+#ifdef WINDOWSNT
+#include <windows.h>
+#include "w32.h"
+#endif
+
+static int
+emacs_gnutls_handle_error (gnutls_session_t, int err);
+
+Lisp_Object Qgnutls_log_level;
Lisp_Object Qgnutls_code;
Lisp_Object Qgnutls_anon, Qgnutls_x509pki;
Lisp_Object Qgnutls_e_interrupted, Qgnutls_e_again,
Qgnutls_e_invalid_session, Qgnutls_e_not_ready_for_handshake;
-int global_initialized;
+int gnutls_global_initialized;
/* The following are for the property list of `gnutls-boot'. */
Lisp_Object Qgnutls_bootprop_priority;
@@ -38,8 +47,27 @@ Lisp_Object Qgnutls_bootprop_trustfiles;
Lisp_Object Qgnutls_bootprop_keyfiles;
Lisp_Object Qgnutls_bootprop_callbacks;
Lisp_Object Qgnutls_bootprop_loglevel;
+Lisp_Object Qgnutls_bootprop_hostname;
+Lisp_Object Qgnutls_bootprop_verify_flags;
+Lisp_Object Qgnutls_bootprop_verify_error;
+Lisp_Object Qgnutls_bootprop_verify_hostname_error;
+
+/* Callback keys for `gnutls-boot'. Unused currently. */
+Lisp_Object Qgnutls_bootprop_callbacks_verify;
static void
+gnutls_log_function (int level, const char* string)
+{
+ message ("gnutls.c: [%d] %s", level, string);
+}
+
+static void
+gnutls_log_function2 (int level, const char* string, const char* extra)
+{
+ message ("gnutls.c: [%d] %s %s", level, string, extra);
+}
+
+static int
emacs_gnutls_handshake (struct Lisp_Process *proc)
{
gnutls_session_t state = proc->gnutls_state;
@@ -50,24 +78,55 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
if (proc->gnutls_initstage < GNUTLS_STAGE_TRANSPORT_POINTERS_SET)
{
+#ifdef WINDOWSNT
+ /* On W32 we cannot transfer socket handles between different runtime
+ libraries, so we tell GnuTLS to use our special push/pull
+ functions. */
+ gnutls_transport_set_ptr2 (state,
+ (gnutls_transport_ptr_t) proc,
+ (gnutls_transport_ptr_t) proc);
+ gnutls_transport_set_push_function (state, &emacs_gnutls_push);
+ gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
+
+ /* For non blocking sockets or other custom made pull/push
+ functions the gnutls_transport_set_lowat must be called, with
+ a zero low water mark value. (GnuTLS 2.10.4 documentation)
+
+ (Note: this is probably not strictly necessary as the lowat
+ value is only used when no custom pull/push functions are
+ set.) */
+ gnutls_transport_set_lowat (state, 0);
+#else
/* This is how GnuTLS takes sockets: as file descriptors passed
in. For an Emacs process socket, infd and outfd are the
same but we use this two-argument version for clarity. */
gnutls_transport_set_ptr2 (state,
- (gnutls_transport_ptr_t) (long) proc->infd,
- (gnutls_transport_ptr_t) (long) proc->outfd);
+ (gnutls_transport_ptr_t) (long) proc->infd,
+ (gnutls_transport_ptr_t) (long) proc->outfd);
+#endif
proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
}
- ret = gnutls_handshake (state);
+ do
+ {
+ ret = gnutls_handshake (state);
+ emacs_gnutls_handle_error (state, ret);
+ }
+ while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
+
proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
if (ret == GNUTLS_E_SUCCESS)
{
- /* here we're finally done. */
+ /* Here we're finally done. */
proc->gnutls_initstage = GNUTLS_STAGE_READY;
}
+ else
+ {
+ gnutls_alert_send_appropriate (state, ret);
+ }
+ return ret;
}
EMACS_INT
@@ -107,6 +166,7 @@ emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
bytes_written += rtnval;
}
+ emacs_gnutls_handle_error (state, rtnval);
return (bytes_written);
}
@@ -122,19 +182,68 @@ emacs_gnutls_read (int fildes, struct Lisp_Process *proc, char *buf,
emacs_gnutls_handshake (proc);
return -1;
}
-
rtnval = gnutls_read (state, buf, nbyte);
if (rtnval >= 0)
return rtnval;
+ else if (emacs_gnutls_handle_error (state, rtnval) == 0)
+ /* non-fatal error */
+ return -1;
else {
- if (rtnval == GNUTLS_E_AGAIN ||
- rtnval == GNUTLS_E_INTERRUPTED)
- return -1;
- else
- return 0;
+ /* a fatal error occured */
+ return 0;
}
}
+/* report a GnuTLS error to the user.
+ Returns zero if the error code was successfully handled. */
+static int
+emacs_gnutls_handle_error (gnutls_session_t session, int err)
+{
+ Lisp_Object gnutls_log_level = Fsymbol_value (Qgnutls_log_level);
+ int max_log_level = 0;
+
+ int alert, ret;
+ const char *str;
+
+ /* TODO: use a Lisp_Object generated by gnutls_make_error? */
+ if (err >= 0)
+ return 0;
+
+ if (NUMBERP (gnutls_log_level))
+ max_log_level = XINT (gnutls_log_level);
+
+ /* TODO: use gnutls-error-fatalp and gnutls-error-string. */
+
+ str = gnutls_strerror (err);
+ if (!str)
+ str = "unknown";
+
+ if (gnutls_error_is_fatal (err))
+ {
+ ret = err;
+ GNUTLS_LOG2 (0, max_log_level, "fatal error:", str);
+ }
+ else
+ {
+ ret = 0;
+ GNUTLS_LOG2 (1, max_log_level, "non-fatal error:", str);
+ /* TODO: EAGAIN AKA Qgnutls_e_again should be level 2. */
+ }
+
+ if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
+ || err == GNUTLS_E_FATAL_ALERT_RECEIVED)
+ {
+ int alert = gnutls_alert_get (session);
+ int level = (err == GNUTLS_E_FATAL_ALERT_RECEIVED) ? 0 : 1;
+ str = gnutls_alert_get_name (alert);
+ if (!str)
+ str = "unknown";
+
+ GNUTLS_LOG2 (level, max_log_level, "Received alert: ", str);
+ }
+ return ret;
+}
+
/* convert an integer error to a Lisp_Object; it will be either a
known symbol like `gnutls_e_interrupted' and `gnutls_e_again' or
simply the integer value of the error. GNUTLS_E_SUCCESS is mapped
@@ -262,14 +371,14 @@ See also `gnutls-init'. */)
Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
Returns zero on success. */
static Lisp_Object
-gnutls_emacs_global_init (void)
+emacs_gnutls_global_init (void)
{
int ret = GNUTLS_E_SUCCESS;
- if (!global_initialized)
+ if (!gnutls_global_initialized)
ret = gnutls_global_init ();
- global_initialized = 1;
+ gnutls_global_initialized = 1;
return gnutls_make_error (ret);
}
@@ -278,29 +387,17 @@ gnutls_emacs_global_init (void)
/* Deinitializes global GnuTLS state.
See also `gnutls-global-init'. */
static Lisp_Object
-gnutls_emacs_global_deinit (void)
+emacs_gnutls_global_deinit (void)
{
- if (global_initialized)
+ if (gnutls_global_initialized)
gnutls_global_deinit ();
- global_initialized = 0;
+ gnutls_global_initialized = 0;
return gnutls_make_error (GNUTLS_E_SUCCESS);
}
#endif
-static void
-gnutls_log_function (int level, const char* string)
-{
- message ("gnutls.c: [%d] %s", level, string);
-}
-
-static void
-gnutls_log_function2 (int level, const char* string, const char* extra)
-{
- message ("gnutls.c: [%d] %s %s", level, string, extra);
-}
-
DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
Currently only client mode is supported. Returns a success/failure
@@ -309,12 +406,27 @@ value you can check with `gnutls-errorp'.
TYPE is a symbol, either `gnutls-anon' or `gnutls-x509pki'.
PROPLIST is a property list with the following keys:
+:hostname is a string naming the remote host.
+
:priority is a GnuTLS priority string, defaults to "NORMAL".
+
:trustfiles is a list of PEM-encoded trust files for `gnutls-x509pki'.
+
:keyfiles is a list of PEM-encoded key files for `gnutls-x509pki'.
-:callbacks is an alist of callback functions (TODO).
+
+:callbacks is an alist of callback functions, see below.
+
:loglevel is the debug level requested from GnuTLS, try 4.
+:verify-flags is a bitset as per GnuTLS'
+gnutls_certificate_set_verify_flags.
+
+:verify-error, if non-nil, makes failure of the certificate validation
+an error. Otherwise it will be just a series of warnings.
+
+:verify-hostname-error, if non-nil, makes a hostname mismatch an
+error. Otherwise it will be just a warning.
+
The debug level will be set for this process AND globally for GnuTLS.
So if you set it higher or lower at any point, it affects global
debugging.
@@ -327,6 +439,9 @@ Processes must be initialized with this function before other GnuTLS
functions are used. This function allocates resources which can only
be deallocated by calling `gnutls-deinit' or by calling it again.
+The callbacks alist can have a `verify' key, associated with a
+verification function (UNUSED).
+
Each authentication type may need additional information in order to
work. For X.509 PKI (`gnutls-x509pki'), you probably need at least
one trustfile (usually a CA bundle). */)
@@ -339,12 +454,19 @@ one trustfile (usually a CA bundle). */)
/* TODO: GNUTLS_X509_FMT_DER is also an option. */
int file_format = GNUTLS_X509_FMT_PEM;
+ unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
+ gnutls_x509_crt_t gnutls_verify_cert;
+ unsigned int gnutls_verify_cert_list_size;
+ const gnutls_datum_t *gnutls_verify_cert_list;
+
gnutls_session_t state;
gnutls_certificate_credentials_t x509_cred;
gnutls_anon_client_credentials_t anon_cred;
Lisp_Object global_init;
char const *priority_string_ptr = "NORMAL"; /* default priority string. */
Lisp_Object tail;
+ int peer_verification;
+ char* c_hostname;
/* Placeholders for the property list elements. */
Lisp_Object priority_string;
@@ -352,16 +474,29 @@ one trustfile (usually a CA bundle). */)
Lisp_Object keyfiles;
/* Lisp_Object callbacks; */
Lisp_Object loglevel;
+ Lisp_Object hostname;
+ Lisp_Object verify_flags;
+ Lisp_Object verify_error;
+ Lisp_Object verify_hostname_error;
CHECK_PROCESS (proc);
CHECK_SYMBOL (type);
CHECK_LIST (proplist);
- priority_string = Fplist_get (proplist, Qgnutls_bootprop_priority);
- trustfiles = Fplist_get (proplist, Qgnutls_bootprop_trustfiles);
- keyfiles = Fplist_get (proplist, Qgnutls_bootprop_keyfiles);
- /* callbacks = Fplist_get (proplist, Qgnutls_bootprop_callbacks); */
- loglevel = Fplist_get (proplist, Qgnutls_bootprop_loglevel);
+ hostname = Fplist_get (proplist, Qgnutls_bootprop_hostname);
+ priority_string = Fplist_get (proplist, Qgnutls_bootprop_priority);
+ trustfiles = Fplist_get (proplist, Qgnutls_bootprop_trustfiles);
+ keyfiles = Fplist_get (proplist, Qgnutls_bootprop_keyfiles);
+ /* callbacks = Fplist_get (proplist, Qgnutls_bootprop_callbacks); */
+ loglevel = Fplist_get (proplist, Qgnutls_bootprop_loglevel);
+ verify_flags = Fplist_get (proplist, Qgnutls_bootprop_verify_flags);
+ verify_error = Fplist_get (proplist, Qgnutls_bootprop_verify_error);
+ verify_hostname_error = Fplist_get (proplist, Qgnutls_bootprop_verify_hostname_error);
+
+ if (!STRINGP (hostname))
+ error ("gnutls-boot: invalid :hostname parameter");
+
+ c_hostname = SSDATA (hostname);
state = XPROCESS (proc)->gnutls_state;
XPROCESS (proc)->gnutls_p = 1;
@@ -375,7 +510,7 @@ one trustfile (usually a CA bundle). */)
}
/* always initialize globals. */
- global_init = gnutls_emacs_global_init ();
+ global_init = emacs_gnutls_global_init ();
if (! NILP (Fgnutls_errorp (global_init)))
return global_init;
@@ -419,6 +554,23 @@ one trustfile (usually a CA bundle). */)
x509_cred = XPROCESS (proc)->gnutls_x509_cred;
if (gnutls_certificate_allocate_credentials (&x509_cred) < 0)
memory_full ();
+
+ if (NUMBERP (verify_flags))
+ {
+ gnutls_verify_flags = XINT (verify_flags);
+ GNUTLS_LOG (2, max_log_level, "setting verification flags");
+ }
+ else if (NILP (verify_flags))
+ {
+ /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */
+ GNUTLS_LOG (2, max_log_level, "using default verification flags");
+ }
+ else
+ {
+ /* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */
+ GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
+ }
+ gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
}
else if (EQ (type, Qgnutls_anon))
{
@@ -487,6 +639,14 @@ one trustfile (usually a CA bundle). */)
GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_FILES;
+ GNUTLS_LOG (1, max_log_level, "gnutls callbacks");
+
+ GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CALLBACKS;
+
+#ifdef HAVE_GNUTLS_CALLBACK_CERTIFICATE_VERIFY
+#else
+#endif
+
GNUTLS_LOG (1, max_log_level, "gnutls_init");
ret = gnutls_init (&state, GNUTLS_CLIENT);
@@ -544,9 +704,113 @@ one trustfile (usually a CA bundle). */)
GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET;
- emacs_gnutls_handshake (XPROCESS (proc));
+ ret = emacs_gnutls_handshake (XPROCESS (proc));
- return gnutls_make_error (GNUTLS_E_SUCCESS);
+ if (ret < GNUTLS_E_SUCCESS)
+ return gnutls_make_error (ret);
+
+ /* Now verify the peer, following
+ http://www.gnu.org/software/gnutls/manual/html_node/Verifying-peer_0027s-certificate.html.
+ The peer should present at least one certificate in the chain; do a
+ check of the certificate's hostname with
+ gnutls_x509_crt_check_hostname() against :hostname. */
+
+ ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
+
+ if (ret < GNUTLS_E_SUCCESS)
+ return gnutls_make_error (ret);
+
+ if (XINT (loglevel) > 0 && peer_verification & GNUTLS_CERT_INVALID)
+ message ("%s certificate could not be verified.",
+ c_hostname);
+
+ if (peer_verification & GNUTLS_CERT_REVOKED)
+ GNUTLS_LOG2 (1, max_log_level, "certificate was revoked (CRL):",
+ c_hostname);
+
+ if (peer_verification & GNUTLS_CERT_SIGNER_NOT_FOUND)
+ GNUTLS_LOG2 (1, max_log_level, "certificate signer was not found:",
+ c_hostname);
+
+ if (peer_verification & GNUTLS_CERT_SIGNER_NOT_CA)
+ GNUTLS_LOG2 (1, max_log_level, "certificate signer is not a CA:",
+ c_hostname);
+
+ if (peer_verification & GNUTLS_CERT_INSECURE_ALGORITHM)
+ GNUTLS_LOG2 (1, max_log_level,
+ "certificate was signed with an insecure algorithm:",
+ c_hostname);
+
+ if (peer_verification & GNUTLS_CERT_NOT_ACTIVATED)
+ GNUTLS_LOG2 (1, max_log_level, "certificate is not yet activated:",
+ c_hostname);
+
+ if (peer_verification & GNUTLS_CERT_EXPIRED)
+ GNUTLS_LOG2 (1, max_log_level, "certificate has expired:",
+ c_hostname);
+
+ if (peer_verification != 0)
+ {
+ if (NILP (verify_hostname_error))
+ {
+ GNUTLS_LOG2 (1, max_log_level, "certificate validation failed:",
+ c_hostname);
+ }
+ else
+ {
+ error ("Certificate validation failed %s, verification code %d",
+ c_hostname, peer_verification);
+ }
+ }
+
+ /* Up to here the process is the same for X.509 certificates and
+ OpenPGP keys. From now on X.509 certificates are assumed. This
+ can be easily extended to work with openpgp keys as well. */
+ if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
+ {
+ ret = gnutls_x509_crt_init (&gnutls_verify_cert);
+
+ if (ret < GNUTLS_E_SUCCESS)
+ return gnutls_make_error (ret);
+
+ gnutls_verify_cert_list =
+ gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
+
+ if (NULL == gnutls_verify_cert_list)
+ {
+ error ("No x509 certificate was found!\n");
+ }
+
+ /* We only check the first certificate in the given chain. */
+ ret = gnutls_x509_crt_import (gnutls_verify_cert,
+ &gnutls_verify_cert_list[0],
+ GNUTLS_X509_FMT_DER);
+
+ if (ret < GNUTLS_E_SUCCESS)
+ {
+ gnutls_x509_crt_deinit (gnutls_verify_cert);
+ return gnutls_make_error (ret);
+ }
+
+ if (!gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname))
+ {
+ if (NILP (verify_hostname_error))
+ {
+ GNUTLS_LOG2 (1, max_log_level, "x509 certificate does not match:",
+ c_hostname);
+ }
+ else
+ {
+ gnutls_x509_crt_deinit (gnutls_verify_cert);
+ error ("The x509 certificate does not match \"%s\"",
+ c_hostname);
+ }
+ }
+
+ gnutls_x509_crt_deinit (gnutls_verify_cert);
+ }
+
+ return gnutls_make_error (ret);
}
DEFUN ("gnutls-bye", Fgnutls_bye,
@@ -581,7 +845,10 @@ This function may also return `gnutls-e-again', or
void
syms_of_gnutls (void)
{
- global_initialized = 0;
+ gnutls_global_initialized = 0;
+
+ Qgnutls_log_level = intern_c_string ("gnutls-log-level");
+ staticpro (&Qgnutls_log_level);
Qgnutls_code = intern_c_string ("gnutls-code");
staticpro (&Qgnutls_code);
@@ -592,6 +859,9 @@ syms_of_gnutls (void)
Qgnutls_x509pki = intern_c_string ("gnutls-x509pki");
staticpro (&Qgnutls_x509pki);
+ Qgnutls_bootprop_hostname = intern_c_string (":hostname");
+ staticpro (&Qgnutls_bootprop_hostname);
+
Qgnutls_bootprop_priority = intern_c_string (":priority");
staticpro (&Qgnutls_bootprop_priority);
@@ -604,9 +874,21 @@ syms_of_gnutls (void)
Qgnutls_bootprop_callbacks = intern_c_string (":callbacks");
staticpro (&Qgnutls_bootprop_callbacks);
+ Qgnutls_bootprop_callbacks_verify = intern_c_string ("verify");
+ staticpro (&Qgnutls_bootprop_callbacks_verify);
+
Qgnutls_bootprop_loglevel = intern_c_string (":loglevel");
staticpro (&Qgnutls_bootprop_loglevel);
+ Qgnutls_bootprop_verify_flags = intern_c_string (":verify-flags");
+ staticpro (&Qgnutls_bootprop_verify_flags);
+
+ Qgnutls_bootprop_verify_hostname_error = intern_c_string (":verify-error");
+ staticpro (&Qgnutls_bootprop_verify_error);
+
+ Qgnutls_bootprop_verify_hostname_error = intern_c_string (":verify-hostname-error");
+ staticpro (&Qgnutls_bootprop_verify_hostname_error);
+
Qgnutls_e_interrupted = intern_c_string ("gnutls-e-interrupted");
staticpro (&Qgnutls_e_interrupted);
Fput (Qgnutls_e_interrupted, Qgnutls_code,
diff --git a/src/gnutls.h b/src/gnutls.h
index 5240d94c2ad..6c2e4c69523 100644
--- a/src/gnutls.h
+++ b/src/gnutls.h
@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
typedef enum
{
@@ -28,6 +29,7 @@ typedef enum
GNUTLS_STAGE_EMPTY = 0,
GNUTLS_STAGE_CRED_ALLOC,
GNUTLS_STAGE_FILES,
+ GNUTLS_STAGE_CALLBACKS,
GNUTLS_STAGE_INIT,
GNUTLS_STAGE_PRIORITY,
GNUTLS_STAGE_CRED_SET,
diff --git a/src/lisp.h b/src/lisp.h
index 4af12fb2f51..4b7973939ef 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2782,6 +2782,9 @@ extern Lisp_Object internal_with_output_to_temp_buffer
extern void float_to_string (char *, double);
extern void syms_of_print (void);
+/* Defined in doprnt.c */
+extern size_t doprnt (char *, size_t, const char *, const char *, va_list);
+
/* Defined in lread.c. */
extern Lisp_Object Qvariable_documentation, Qstandard_input;
extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
diff --git a/src/makefile.w32-in b/src/makefile.w32-in
index 62c40ca1f94..4ba314318db 100644
--- a/src/makefile.w32-in
+++ b/src/makefile.w32-in
@@ -105,6 +105,7 @@ OBJ2 = $(BLD)/sysdep.$(O) \
$(BLD)/floatfns.$(O) \
$(BLD)/frame.$(O) \
$(BLD)/gmalloc.$(O) \
+ $(BLD)/gnutls.$(O) \
$(BLD)/intervals.$(O) \
$(BLD)/composite.$(O) \
$(BLD)/ralloc.$(O) \
@@ -150,6 +151,7 @@ LIBS = $(TLIB0) \
$(OLE32) \
$(COMCTL32) \
$(UNISCRIBE) \
+ $(USER_LIBS) \
$(libc)
#
@@ -225,6 +227,7 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
obj = $(GLOBAL_SOURCES:.c=.o)
globals.h: gl-stamp
+ @cmd /c rem true
gl-stamp: ../lib-src/$(BLD)/make-docfile.exe $(GLOBAL_SOURCES)
- $(DEL) gl-tmp
@@ -329,7 +332,7 @@ cleanall: clean
##
## This works only with GNU Make.
-TAGS: $(OBJ0) $(OBJ1) $(OBJ2)
+TAGS: $(OBJ0) $(OBJ1) $(OBJ2) $(CURDIR)/m/intel386.h $(CURDIR)/s/ms-w32.h
$(MAKE) $(MFLAGS) TAGS-$(MAKETYPE)
TAGS-LISP: $(OBJ0) $(OBJ1) $(OBJ2)
@@ -343,7 +346,7 @@ TAGS-gmake:
$(patsubst $(BLD)%.$(O),$(CURDIR)%.c,$(OBJ1))
../lib-src/$(BLD)/etags.exe -a --regex=@../nt/emacs-src.tags \
$(patsubst $(BLD)%.$(O),$(CURDIR)%.c,$(OBJ2)) \
- $(CURDIR)/*.h
+ $(CURDIR)/*.h $(CURDIR)/m/intel386.h $(CURDIR)/s/ms-w32.h
TAGS-nmake:
echo This target is not supported with NMake
@@ -469,6 +472,7 @@ $(BLD)/callint.$(O) : \
$(EMACS_ROOT)/nt/inc/sys/time.h \
$(LISP_H) \
$(SRC)/buffer.h \
+ $(SRC)/character.h \
$(SRC)/coding.h \
$(SRC)/commands.h \
$(SRC)/composite.h \
@@ -948,6 +952,14 @@ $(BLD)/gmalloc.$(O) : \
$(EMACS_ROOT)/nt/inc/unistd.h \
$(SRC)/getpagesize.h
+$(BLD)/gnutls.$(O) : \
+ $(SRC)/gnutls.h \
+ $(SRC)/gnutls.c \
+ $(CONFIG_H) \
+ $(EMACS_ROOT)/nt/inc/sys/socket.h \
+ $(SRC)/lisp.h \
+ $(SRC)/process.h
+
$(BLD)/image.$(O) : \
$(SRC)/image.c \
$(CONFIG_H) \
diff --git a/src/msdos.c b/src/msdos.c
index e02e64b9ece..3dc586e42f5 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -842,7 +842,7 @@ IT_set_face (int face)
/* According to RBIL (INTERRUP.A, V-1000), 160 is the maximum possible
width of a DOS display in any known text mode. We multiply by 2 to
- accomodate the screen attribute byte. */
+ accommodate the screen attribute byte. */
#define MAX_SCREEN_BUF 160*2
extern unsigned char *encode_terminal_code (struct glyph *, int,
@@ -2812,7 +2812,7 @@ dos_keyread (void)
left), but I don't think it's worth the effort. */
/* These hold text of the current and the previous menu help messages. */
-static char *menu_help_message, *prev_menu_help_message;
+static const char *menu_help_message, *prev_menu_help_message;
/* Pane number and item number of the menu item which generated the
last menu help message. */
static int menu_help_paneno, menu_help_itemno;
@@ -2839,7 +2839,7 @@ IT_menu_make_room (XMenu *menu)
menu->text = (char **) xmalloc (count * sizeof (char *));
menu->submenu = (XMenu **) xmalloc (count * sizeof (XMenu *));
menu->panenumber = (int *) xmalloc (count * sizeof (int));
- menu->help_text = (char **) xmalloc (count * sizeof (char *));
+ menu->help_text = (const char **) xmalloc (count * sizeof (char *));
}
else if (menu->allocated == menu->count)
{
@@ -2851,7 +2851,7 @@ IT_menu_make_room (XMenu *menu)
menu->panenumber
= (int *) xrealloc (menu->panenumber, count * sizeof (int));
menu->help_text
- = (char **) xrealloc (menu->help_text, count * sizeof (char *));
+ = (const char **) xrealloc (menu->help_text, count * sizeof (char *));
}
}
@@ -3033,7 +3033,7 @@ XMenuAddPane (Display *foo, XMenu *menu, const char *txt, int enable)
int
XMenuAddSelection (Display *bar, XMenu *menu, int pane,
- int foo, char *txt, int enable, char *help_text)
+ int foo, char *txt, int enable, char const *help_text)
{
int len;
char *p;
@@ -3086,7 +3086,7 @@ struct IT_menu_state
int
XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
int x0, int y0, unsigned ButtonMask, char **txt,
- void (*help_callback)(char *, int, int))
+ void (*help_callback)(char const *, int, int))
{
struct IT_menu_state *state;
int statecount, x, y, i, b, screensize, leave, result, onepane;
diff --git a/src/msdos.h b/src/msdos.h
index 5051f2f3837..3048b5f7e35 100644
--- a/src/msdos.h
+++ b/src/msdos.h
@@ -101,16 +101,16 @@ typedef struct x_menu_struct
int allocated;
int panecount;
int width;
- char **help_text;
+ const char **help_text;
} XMenu;
XMenu *XMenuCreate (Display *, Window, char *);
-int XMenuAddPane (Display *, XMenu *, const char *, int);
-int XMenuAddSelection (Display *, XMenu *, int, int, char *, int, char *);
+int XMenuAddPane (Display *, XMenu *, char const *, int);
+int XMenuAddSelection (Display *, XMenu *, int, int, char *, int, char const *);
void XMenuLocate (Display *, XMenu *, int, int, int, int,
int *, int *, int *, int *);
int XMenuActivate (Display *, XMenu *, int *, int *, int, int, unsigned,
- char **, void (*callback)(char *, int, int));
+ char **, void (*callback)(char const *, int, int));
void XMenuDestroy (Display *, XMenu *);
#endif /* not HAVE_X_WINDOWS */
diff --git a/src/process.c b/src/process.c
index 89a5f3e0386..1544522ff55 100644
--- a/src/process.c
+++ b/src/process.c
@@ -4533,6 +4533,22 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
&Available,
(check_write ? &Writeok : (SELECT_TYPE *)0),
(SELECT_TYPE *)0, &timeout);
+
+#ifdef HAVE_GNUTLS
+ /* GnuTLS buffers data internally. In lowat mode it leaves
+ some data in the TCP buffers so that select works, but
+ with custom pull/push functions we need to check if some
+ data is available in the buffers manually. */
+ if (nfds == 0 &&
+ wait_proc && wait_proc->gnutls_p /* Check for valid process. */
+ /* Do we have pending data? */
+ && gnutls_record_check_pending (wait_proc->gnutls_state) > 0)
+ {
+ nfds = 1;
+ /* Set to Available. */
+ FD_SET (wait_proc->infd, &Available);
+ }
+#endif
}
xerrno = errno;
diff --git a/src/s/ms-w32.h b/src/s/ms-w32.h
index 8b189baea46..bf6cc66798c 100644
--- a/src/s/ms-w32.h
+++ b/src/s/ms-w32.h
@@ -204,6 +204,7 @@ struct sigaction {
#define dup2 sys_dup2
#define fopen sys_fopen
#define link sys_link
+#define localtime sys_localtime
#define mkdir sys_mkdir
#undef mktemp
#define mktemp sys_mktemp
diff --git a/src/syntax.c b/src/syntax.c
index 3bc9cdbd66d..cff6d50f510 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -19,7 +19,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
+
#include <ctype.h>
+#include <sys/types.h>
#include <setjmp.h>
#include "lisp.h"
#include "commands.h"
diff --git a/src/sysdep.c b/src/sysdep.c
index a57b8c0382d..ca7de4f54bb 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -304,7 +304,7 @@ wait_for_termination (int pid)
{
while (1)
{
-#if defined (BSD_SYSTEM) || defined (HPUX)
+#if (defined (BSD_SYSTEM) || defined (HPUX)) && !defined(__GNU__)
/* Note that kill returns -1 even if the process is just a zombie now.
But inevitably a SIGCHLD interrupt should be generated
and child_sig will do wait3 and make the process go away. */
diff --git a/src/term.c b/src/term.c
index cae83f4d269..28709138a17 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3121,7 +3121,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
terminal = create_terminal ();
#ifdef MSDOS
if (been_here > 0)
- maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
+ maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
name, "");
been_here = 1;
tty = &the_only_display_info;
@@ -3627,7 +3627,7 @@ vfatal (const char *str, va_list ap)
/* Auxiliary error-handling function for init_tty.
Delete TERMINAL, then call error or fatal with str1 or str2,
- respectively, according to MUST_SUCCEED. */
+ respectively, according to whether MUST_SUCCEED is zero or not. */
static void
maybe_fatal (int must_succeed, struct terminal *terminal,
diff --git a/src/textprop.c b/src/textprop.c
index 64265fd679c..aad090c5b41 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -233,7 +233,7 @@ interval_has_all_properties (Lisp_Object plist, INTERVAL i)
if (! EQ (Fcar (XCDR (tail1)), Fcar (XCDR (tail2))))
return 0;
- /* Property has same value on both lists; go to next one. */
+ /* Property has same value on both lists; go to next one. */
found = 1;
break;
}
@@ -1759,15 +1759,9 @@ text_property_stickiness (Lisp_Object prop, Lisp_Object pos, Lisp_Object buffer)
}
-/* I don't think this is the right interface to export; how often do you
- want to do something like this, other than when you're copying objects
- around?
+/* Copying properties between objects. */
- I think it would be better to have a pair of functions, one which
- returns the text properties of a region as a list of ranges and
- plists, and another which applies such a list to another object. */
-
-/* Add properties from SRC to SRC of SRC, starting at POS in DEST.
+/* Add properties from START to END of SRC, starting at POS in DEST.
SRC and DEST may each refer to strings or buffers.
Optional sixth argument PROP causes only that property to be copied.
Properties are copied to DEST as if by `add-text-properties'.
@@ -2307,6 +2301,4 @@ inherits it if NONSTICKINESS is nil. The `front-sticky' and
defsubr (&Sremove_list_of_text_properties);
defsubr (&Stext_property_any);
defsubr (&Stext_property_not_all);
-/* defsubr (&Serase_text_properties); */
-/* defsubr (&Scopy_text_properties); */
}
diff --git a/src/w32.c b/src/w32.c
index d715c39fa81..2fbb3b6cb4c 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -34,6 +34,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <mbstring.h> /* for _mbspbrk */
#include <math.h>
#include <setjmp.h>
+#include <time.h>
/* must include CRT headers *before* config.h */
@@ -62,6 +63,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#undef strerror
+#undef localtime
+
#include "lisp.h"
#include <pwd.h>
@@ -1942,6 +1945,12 @@ gettimeofday (struct timeval *tv, struct timezone *tz)
tv->tv_sec = tb.time;
tv->tv_usec = tb.millitm * 1000L;
+ /* Implementation note: _ftime sometimes doesn't update the dstflag
+ according to the new timezone when the system timezone is
+ changed. We could fix that by using GetSystemTime and
+ GetTimeZoneInformation, but that doesn't seem necessary, since
+ Emacs always calls gettimeofday with the 2nd argument NULL (see
+ EMACS_GET_TIME). */
if (tz)
{
tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
@@ -5678,6 +5687,19 @@ sys_write (int fd, const void * buffer, unsigned int count)
return nchars;
}
+/* The Windows CRT functions are "optimized for speed", so they don't
+ check for timezone and DST changes if they were last called less
+ than 1 minute ago (see http://support.microsoft.com/kb/821231). So
+ all Emacs features that repeatedly call time functions (e.g.,
+ display-time) are in real danger of missing timezone and DST
+ changes. Calling tzset before each localtime call fixes that. */
+struct tm *
+sys_localtime (const time_t *t)
+{
+ tzset ();
+ return localtime (t);
+}
+
static void
check_windows_init_file (void)
{
@@ -6102,5 +6124,72 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
p->childp = childp2;
}
-/* end of w32.c */
+#ifdef HAVE_GNUTLS
+
+ssize_t
+emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
+{
+ int n, sc, err;
+ SELECT_TYPE fdset;
+ EMACS_TIME timeout;
+ struct Lisp_Process *process = (struct Lisp_Process *)p;
+ int fd = process->infd;
+
+ for (;;)
+ {
+ n = sys_read(fd, (char*)buf, sz);
+
+ if (n >= 0)
+ return n;
+
+ err = errno;
+
+ if (err == EWOULDBLOCK)
+ {
+ /* Set a small timeout. */
+ EMACS_SET_SECS_USECS(timeout, 1, 0);
+ FD_ZERO (&fdset);
+ FD_SET ((int)fd, &fdset);
+
+ /* Use select with the timeout to poll the selector. */
+ sc = select (fd + 1, &fdset, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+ &timeout);
+
+ if (sc > 0)
+ continue; /* Try again. */
+
+ /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN.
+ Also accept select return 0 as an indicator to EAGAIN. */
+ if (sc == 0 || errno == EWOULDBLOCK)
+ err = EAGAIN;
+ else
+ err = errno; /* Other errors are just passed on. */
+ }
+ gnutls_transport_set_errno (process->gnutls_state, err);
+
+ return -1;
+ }
+}
+
+ssize_t
+emacs_gnutls_push (gnutls_transport_ptr_t p, const void* buf, size_t sz)
+{
+ struct Lisp_Process *process = (struct Lisp_Process *)p;
+ int fd = process->outfd;
+ ssize_t n = sys_write(fd, buf, sz);
+
+ /* 0 or more bytes written means everything went fine. */
+ if (n >= 0)
+ return n;
+
+ /* Negative bytes written means we got an error in errno.
+ Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
+ gnutls_transport_set_errno (process->gnutls_state,
+ errno == EWOULDBLOCK ? EAGAIN : errno);
+
+ return -1;
+}
+#endif /* HAVE_GNUTLS */
+
+/* end of w32.c */
diff --git a/src/w32.h b/src/w32.h
index 9279ddbe579..4086c4190e1 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -143,5 +143,17 @@ extern void syms_of_fontset (void);
extern int _sys_read_ahead (int fd);
extern int _sys_wait_accept (int fd);
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+
+/* GnuTLS pull (read from remote) interface. */
+extern ssize_t emacs_gnutls_pull (gnutls_transport_ptr_t p,
+ void* buf, size_t sz);
+
+/* GnuTLS push (write to remote) interface. */
+extern ssize_t emacs_gnutls_push (gnutls_transport_ptr_t p,
+ const void* buf, size_t sz);
+#endif /* HAVE_GNUTLS */
+
#endif /* EMACS_W32_H */
diff --git a/src/xdisp.c b/src/xdisp.c
index b44c27335a6..6d3c142f62a 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3855,7 +3855,7 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
}
-/* Set up IT from a single `display' specification PROP. OBJECT
+/* Set up IT from a single `display' property specification SPEC. OBJECT
is the object in which the `display' property was found. *POSITION
is the position at which it was found. DISPLAY_REPLACED_P non-zero
means that we previously saw a display specification which already
@@ -3865,7 +3865,7 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
OVERLAY is the overlay this `display' property came from,
or nil if it was a text property.
- If PROP is a `space' or `image' specification, and in some other
+ If SPEC is a `space' or `image' specification, and in some other
cases too, set *POSITION to the position where the `display'
property ends.
@@ -3875,7 +3875,7 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
static int
handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
Lisp_Object overlay, struct text_pos *position,
- int display_replaced_before_p)
+ int display_replaced_p)
{
Lisp_Object form;
Lisp_Object location, value;
@@ -4171,7 +4171,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
#endif /* not HAVE_WINDOW_SYSTEM */
|| (CONSP (value) && EQ (XCAR (value), Qspace)));
- if (valid_p && !display_replaced_before_p)
+ if (valid_p && !display_replaced_p)
{
/* Save current settings of IT so that we can restore them
when we are finished with the glyph property value. */
@@ -8373,22 +8373,10 @@ vmessage (const char *m, va_list ap)
{
if (m)
{
- char *buf = FRAME_MESSAGE_BUF (f);
- size_t bufsize = FRAME_MESSAGE_BUF_SIZE (f);
- int len;
+ size_t len;
- memset (buf, 0, bufsize);
- len = vsnprintf (buf, bufsize, m, ap);
-
- /* Do any truncation at a character boundary. */
- if (! (0 <= len && len < bufsize))
- {
- char *end = memchr (buf, 0, bufsize);
- for (len = end ? end - buf : bufsize;
- len && ! CHAR_HEAD_P (buf[len - 1]);
- len--)
- continue;
- }
+ len = doprnt (FRAME_MESSAGE_BUF (f),
+ FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, ap);
message2 (FRAME_MESSAGE_BUF (f), len, 0);
}
@@ -26997,6 +26985,7 @@ init_xdisp (void)
mini_w = XWINDOW (minibuf_window);
root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
+ echo_area_window = minibuf_window;
if (!noninteractive)
{
diff --git a/src/xfaces.c b/src/xfaces.c
index 9721df04cab..a26289e8a88 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -331,7 +331,7 @@ Lisp_Object Qexpanded;
static Lisp_Object Qultra_expanded;
static Lisp_Object Qreleased_button, Qpressed_button;
static Lisp_Object QCstyle, QCcolor, QCline_width;
-static Lisp_Object Qunspecified;
+Lisp_Object Qunspecified; /* used in dosfns.c */
static Lisp_Object Qignore_defface;
char unspecified_fg[] = "unspecified-fg", unspecified_bg[] = "unspecified-bg";