From 3ad05a0dc46093dd6b8958747a0475b8baba954f Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Wed, 10 Feb 2016 12:18:30 +0100 Subject: Describe Makefile test targets in test/README * CONTRIBUTE: Move Makefile test targets to test/README. * Makefile.in: * test/README: Describe Makefile test targets. --- CONTRIBUTE | 22 ++-------------------- Makefile.in | 4 ++++ test/README | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/CONTRIBUTE b/CONTRIBUTE index 5a5cb5db5a5..d8e102dc7fb 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -257,26 +257,8 @@ If your test lasts longer than some few seconds, mark it in its To run tests on the entire Emacs tree, run "make check" from the top-level directory. Most tests are in the directory "test/automated". From the "test/automated" directory, run "make -" to run the tests for .el(c). See -"test/automated/Makefile" for more information. - -Tests which are tagged ":expensive-test" are enabled additionally, if -you run "make check-expensive" from the top-level directory. "make -" as mentioned above incorporates expensive tests for -.el(c). You can also define any ert selector on the command -line. So "make check SELECTOR=nil" is equivalent to "make -check-expensive". - -You could also use predefined selectors of the Makefile. "make - SELECTOR='$(SELECTOR_DEFAULT)'" runs all tests for -.el(c) except the tests tagged as expensive. - -Selectors can be defined with different methods, see (info "(ert)Test -Selectors") or -https://www.gnu.org/software/emacs/manual/html_node/ert/Test-Selectors.html -If your test file contains the tests "test-foo", "test2-foo" and -"test-foo-remote", and you want to run only the former two tests, you -could use a regexp: "make SELECTOR='\"foo$$\"'" . +" to run the tests for .el(c). See "test/README" +for more information. ** Understanding Emacs Internals. diff --git a/Makefile.in b/Makefile.in index 75fd15001a4..b212c914e56 100644 --- a/Makefile.in +++ b/Makefile.in @@ -57,6 +57,10 @@ # # make docs # Make Emacs documentation files from their sources; requires makeinfo. +# +# make check or make check-expensive +# Run Emacs test suite. check-expensive runs also tests which +# take more time to perform. SHELL = @SHELL@ diff --git a/test/README b/test/README index 244832decdc..d2aee9bf57b 100644 --- a/test/README +++ b/test/README @@ -1,4 +1,62 @@ +Copyright (C) 2008-2016 Free Software Foundation, Inc. +See the end of the file for license conditions. + This directory contains files intended to test various aspects of Emacs's functionality. Please help add tests! +Emacs uses ERT, Emacs Lisp Regression Testing, for testing. See (info +"(ert)") or https://www.gnu.org/software/emacs/manual/html_node/ert/ +for more information on writing and running tests. + +All ERT test files are supposed to run from subdirectory automated/. +The Makefile in that directory supports the following targets: + +* make check + Run all tests as defined in the directory. Expensive tests are + suppressed. The result of the tests for .el is stored in + .log. + +* make check-maybe + Like "make check", but run only the tests for files which have + unresolved prerequisites. + +* make check-expensive + Like "make check", but run also the tests marked as expensive. + +* make or make .log + Run all tests declared in .el. This includes expensive + tests. In the former case the output is shown on the terminal, in + the latter case the output is written to .log. + +ERT offers selectors, which make it possible to filter out which test +cases shall run. The make variable $(SELECTOR) gives you a simple +mean to use your own selectors. The ERT manual describes how +selectors are constructed, see (info "(ert)Test Selectors") or +https://www.gnu.org/software/emacs/manual/html_node/ert/Test-Selectors.html + +You could use predefined selectors of the Makefile. "make +SELECTOR='$(SELECTOR_DEFAULT)'" runs all tests for .el +except the tests tagged as expensive. + +If your test file contains the tests "test-foo", "test2-foo" and +"test-foo-remote", and you want to run only the former two tests, you +could use a selector regexp: "make SELECTOR='\"foo$$\"'". + + (Also, see etc/compilation.txt for compilation mode font lock tests.) + + +This file is part of GNU Emacs. + +GNU Emacs is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +GNU Emacs 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 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 . -- cgit v1.2.1 From 4ef153b55a543e67dec280accb1b2a3543089060 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 10 Feb 2016 20:30:12 +0200 Subject: Improve doc strings of 'forward/backward-word-strictly' * lisp/simple.el (backward-word): Refer to 'backward-word-strictly' in the doc string. Suggested by Glenn Morris . * lisp/subr.el (forward-word-strictly, backward-word-strictly): Mention 'subword-mode' in the doc strings. * src/syntax.c (Fforward_word): Refer to 'forward-word-strictly' in the doc string. (Bug#22560) --- lisp/simple.el | 8 +++++++- lisp/subr.el | 6 ++++-- src/syntax.c | 12 +++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lisp/simple.el b/lisp/simple.el index e39c864fc04..0b04b80cb67 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -6736,7 +6736,13 @@ current object." (defun backward-word (&optional arg) "Move backward until encountering the beginning of a word. With argument ARG, do this that many times. -If ARG is omitted or nil, move point backward one word." +If ARG is omitted or nil, move point backward one word. + +The word boundaries are normally determined by the buffer's syntax +table, but `find-word-boundary-function-table', such as set up +by `subword-mode', can change that. If a Lisp program needs to +move by words determined strictly by the syntax table, it should +use `backward-word-strictly' instead." (interactive "^p") (forward-word (- (or arg 1)))) diff --git a/lisp/subr.el b/lisp/subr.el index 311348150da..cf26fe384ba 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4137,7 +4137,8 @@ and the function returns nil. Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. This function is like `forward-word', but it is not affected -by `find-word-boundary-function-table'. It is also not interactive." +by `find-word-boundary-function-table' (as set up by +e.g. `subword-mode'). It is also not interactive." (let ((find-word-boundary-function-table (if (char-table-p word-move-empty-char-table) word-move-empty-char-table @@ -4150,7 +4151,8 @@ With argument ARG, do this that many times. If ARG is omitted or nil, move point backward one word. This function is like `forward-word', but it is not affected -by `find-word-boundary-function-table'. It is also not interactive." +by `find-word-boundary-function-table' (as set up by +e.g. `subword-mode'). It is also not interactive." (let ((find-word-boundary-function-table (if (char-table-p word-move-empty-char-table) word-move-empty-char-table diff --git a/src/syntax.c b/src/syntax.c index 8b5cc1df407..7e988547675 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -1536,9 +1536,15 @@ DEFUN ("forward-word", Fforward_word, Sforward_word, 0, 1, "^p", doc: /* Move point forward ARG words (backward if ARG is negative). If ARG is omitted or nil, move point forward one word. Normally returns t. -If an edge of the buffer or a field boundary is reached, point is left there -and the function returns nil. Field boundaries are not noticed if -`inhibit-field-text-motion' is non-nil. */) +If an edge of the buffer or a field boundary is reached, point is +left there and the function returns nil. Field boundaries are not +noticed if `inhibit-field-text-motion' is non-nil. + +The word boundaries are normally determined by the buffer's syntax +table, but `find-word-boundary-function-table', such as set up +by `subword-mode', can change that. If a Lisp program needs to +move by words determined strictly by the syntax table, it should +use `forward-word-strictly' instead. */) (Lisp_Object arg) { Lisp_Object tmp; -- cgit v1.2.1 From 02d925e9e55089fabfe03e5a911c391b9322978f Mon Sep 17 00:00:00 2001 From: Kevin Gallagher Date: Wed, 10 Feb 2016 20:40:28 +0200 Subject: Kevin Gallagher has new email address * lisp/emulation/edt.el: * lisp/emulation/edt-lk201.el: * lisp/emulation/edt-mapper.el: * lisp/emulation/edt-pc.el: * lisp/emulation/edt-vt100.el: * etc/edt-user.el: * doc/misc/edt.texi: Update Kevin Gallagher's email address. --- doc/misc/edt.texi | 5 +++-- etc/edt-user.el | 4 ++-- lisp/emulation/edt-lk201.el | 4 ++-- lisp/emulation/edt-mapper.el | 4 ++-- lisp/emulation/edt-pc.el | 4 ++-- lisp/emulation/edt-vt100.el | 4 ++-- lisp/emulation/edt.el | 7 ++++--- 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/doc/misc/edt.texi b/doc/misc/edt.texi index 4f3fdaeaa1f..2361313f262 100644 --- a/doc/misc/edt.texi +++ b/doc/misc/edt.texi @@ -30,7 +30,7 @@ modify this GNU manual.'' @titlepage @title EDT Emulation User's Manual @author Kevin Gallagher -@author @email{Kevin.Gallagher@@boeing.com} +@author @email{kevin.gal@verizon.net} @page @vskip 0pt plus 1filll @insertcopying @@ -106,7 +106,8 @@ how to customize it to your liking. @file{edt.texi}---This manual. @item -@file{edt-user.el}---An example customization file. +@file{edt-user.el}---An example customization file (located in the +Emacs distribution etc directory). @item @file{edt.el}---EDT emulation functions and default configuration. diff --git a/etc/edt-user.el b/etc/edt-user.el index 5541ce6b0d3..cf1acbcdb13 100644 --- a/etc/edt-user.el +++ b/etc/edt-user.el @@ -3,8 +3,8 @@ ;; Copyright (C) 1986, 1992-1993, 2000-2016 Free Software Foundation, ;; Inc. -;; Author: Kevin Gallagher -;; Maintainer: Kevin Gallagher +;; Author: Kevin Gallagher +;; Maintainer: Kevin Gallagher ;; Keywords: emulations ;; This file is part of GNU Emacs. diff --git a/lisp/emulation/edt-lk201.el b/lisp/emulation/edt-lk201.el index c30a84d72ae..bb8577c93c5 100644 --- a/lisp/emulation/edt-lk201.el +++ b/lisp/emulation/edt-lk201.el @@ -3,8 +3,8 @@ ;; Copyright (C) 1986, 1992-1993, 1995, 2001-2016 Free Software ;; Foundation, Inc. -;; Author: Kevin Gallagher -;; Maintainer: Kevin Gallagher +;; Author: Kevin Gallagher +;; Maintainer: Kevin Gallagher ;; Keywords: emulations ;; Package: edt diff --git a/lisp/emulation/edt-mapper.el b/lisp/emulation/edt-mapper.el index df32ac0cee1..0bba9e3eeb4 100644 --- a/lisp/emulation/edt-mapper.el +++ b/lisp/emulation/edt-mapper.el @@ -2,8 +2,8 @@ ;; Copyright (C) 1994-1995, 2000-2016 Free Software Foundation, Inc. -;; Author: Kevin Gallagher -;; Maintainer: Kevin Gallagher +;; Author: Kevin Gallagher +;; Maintainer: Kevin Gallagher ;; Keywords: emulations ;; Package: edt diff --git a/lisp/emulation/edt-pc.el b/lisp/emulation/edt-pc.el index 13b60fb3c3d..1f55f4a2369 100644 --- a/lisp/emulation/edt-pc.el +++ b/lisp/emulation/edt-pc.el @@ -3,8 +3,8 @@ ;; Copyright (C) 1986, 1994-1995, 2001-2016 Free Software Foundation, ;; Inc. -;; Author: Kevin Gallagher -;; Maintainer: Kevin Gallagher +;; Author: Kevin Gallagher +;; Maintainer: Kevin Gallagher ;; Keywords: emulations ;; Package: edt diff --git a/lisp/emulation/edt-vt100.el b/lisp/emulation/edt-vt100.el index 1f134f7937c..019283ed6ee 100644 --- a/lisp/emulation/edt-vt100.el +++ b/lisp/emulation/edt-vt100.el @@ -3,8 +3,8 @@ ;; Copyright (C) 1986, 1992-1993, 1995, 2002-2016 Free Software ;; Foundation, Inc. -;; Author: Kevin Gallagher -;; Maintainer: Kevin Gallagher +;; Author: Kevin Gallagher +;; Maintainer: Kevin Gallagher ;; Keywords: emulations ;; Package: edt diff --git a/lisp/emulation/edt.el b/lisp/emulation/edt.el index 1e55fd86c4a..6bda15bf98d 100644 --- a/lisp/emulation/edt.el +++ b/lisp/emulation/edt.el @@ -3,8 +3,8 @@ ;; Copyright (C) 1986, 1992-1995, 2000-2016 Free Software Foundation, ;; Inc. -;; Author: Kevin Gallagher -;; Maintainer: Kevin Gallagher +;; Author: Kevin Gallagher +;; Maintainer: Kevin Gallagher ;; Keywords: emulations ;; This file is part of GNU Emacs. @@ -59,7 +59,8 @@ ;; The EDT emulation consists of the following files: ;; ;; edt.texi - User manual -;; edt-user.el - Sample Customization File +;; edt-user.el - Sample Customization File (located in Emacs +;; distribution etc directory) ;; edt.el - EDT Emulation Functions and Default Configuration ;; edt-lk201.el - Built-in support for DEC LK-201 Keyboards ;; edt-vt100.el - Built-in support for DEC VT-100 (and above) terminals -- cgit v1.2.1 From 25ec995c064d4e658fe3f9af084f120ae21a021a Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 10 Feb 2016 10:14:50 -0800 Subject: Memory-management cleanup in make-docfile I compiled it with -fsanitize=address and fixed the leaks it detected. Also, I changed it to prefer signed to unsigned integer types, and to check for integer overflow. * lib-src/make-docfile.c: Include , , , . (memory_exhausted): New function. (xmalloc, xrealloc): Use it. (xmalloc, xrealloc, scan_file, struct rcsoc_state, write_c_args) (uncompiled, scan_lisp_file): Prefer signed integer types to unsigned. (xstrdup): Remove. All uses removed. (num_globals, num_globals_allocated, write_globals, scan_c_stream): Use ptrdiff_t, not int, for indexes that in theory could exceed INT_MAX. (add_global): Use const to pacify --enable-gcc-warnings. Make a copy here, rather than relying on strdup calls later. (add_global, write_globals, scan_c_stream): Avoid integer overflow when calculating sizes. (write_globals, scan_c_stream, scan_lisp_file): Avoid memory leak. (scan_c_stream): Check for add_global failure. --- lib-src/make-docfile.c | 132 ++++++++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 57 deletions(-) diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index 02b5e766ee2..4ab3729bad0 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -37,6 +37,8 @@ along with GNU Emacs. If not, see . */ #include #include +#include +#include #include #include /* config.h unconditionally includes this anyway */ @@ -48,6 +50,8 @@ along with GNU Emacs. If not, see . */ #endif /* WINDOWSNT */ #include +#include +#include #ifdef DOS_NT /* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this @@ -97,36 +101,31 @@ fatal (const char *s1, const char *s2) exit (EXIT_FAILURE); } -/* Like malloc but get fatal error if memory is exhausted. */ - -static void * -xmalloc (unsigned int size) +static _Noreturn void +memory_exhausted (void) { - void *result = (void *) malloc (size); - if (result == NULL) - fatal ("virtual memory exhausted", 0); - return result; + fatal ("virtual memory exhausted", 0); } -/* Like strdup, but get fatal error if memory is exhausted. */ +/* Like malloc but get fatal error if memory is exhausted. */ -static char * -xstrdup (char *s) +static void * +xmalloc (ptrdiff_t size) { - char *result = strdup (s); - if (! result) - fatal ("virtual memory exhausted", 0); + void *result = malloc (size); + if (result == NULL) + memory_exhausted (); return result; } /* Like realloc but get fatal error if memory is exhausted. */ static void * -xrealloc (void *arg, unsigned int size) +xrealloc (void *arg, ptrdiff_t size) { - void *result = (void *) realloc (arg, size); + void *result = realloc (arg, size); if (result == NULL) - fatal ("virtual memory exhausted", 0); + memory_exhausted (); return result; } @@ -223,8 +222,7 @@ put_filename (char *filename) static int scan_file (char *filename) { - - size_t len = strlen (filename); + ptrdiff_t len = strlen (filename); if (!generate_globals) put_filename (filename); @@ -250,7 +248,7 @@ static char input_buffer[128]; struct rcsoc_state { /* A count of spaces and newlines that have been read, but not output. */ - unsigned pending_spaces, pending_newlines; + intmax_t pending_spaces, pending_newlines; /* Where we're reading from. */ FILE *in_file; @@ -468,10 +466,10 @@ read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usa static void write_c_args (char *func, char *buf, int minargs, int maxargs) { - register char *p; + char *p; int in_ident = 0; char *ident_start IF_LINT (= NULL); - size_t ident_length = 0; + ptrdiff_t ident_length = 0; fputs ("(fn", stdout); @@ -575,34 +573,38 @@ enum { DEFUN_noreturn = 1, DEFUN_const = 2 }; /* All the variable names we saw while scanning C sources in `-g' mode. */ -int num_globals; -int num_globals_allocated; +ptrdiff_t num_globals; +ptrdiff_t num_globals_allocated; struct global *globals; static struct global * -add_global (enum global_type type, char *name, int value, char const *svalue) +add_global (enum global_type type, char const *name, int value, + char const *svalue) { /* Ignore the one non-symbol that can occur. */ if (strcmp (name, "...")) { - ++num_globals; - - if (num_globals_allocated == 0) - { - num_globals_allocated = 100; - globals = xmalloc (num_globals_allocated * sizeof (struct global)); - } - else if (num_globals == num_globals_allocated) + if (num_globals == num_globals_allocated) { - num_globals_allocated *= 2; - globals = xrealloc (globals, - num_globals_allocated * sizeof (struct global)); + ptrdiff_t num_globals_max = (min (PTRDIFF_MAX, SIZE_MAX) + / sizeof *globals); + if (num_globals_allocated == num_globals_max) + memory_exhausted (); + if (num_globals_allocated < num_globals_max / 2) + num_globals_allocated = 2 * num_globals_allocated + 1; + else + num_globals_allocated = num_globals_max; + globals = xrealloc (globals, num_globals_allocated * sizeof *globals); } + ++num_globals; + + ptrdiff_t namesize = strlen (name) + 1; + char *buf = xmalloc (namesize + (svalue ? strlen (svalue) + 1 : 0)); globals[num_globals - 1].type = type; - globals[num_globals - 1].name = name; + globals[num_globals - 1].name = strcpy (buf, name); if (svalue) - globals[num_globals - 1].v.svalue = svalue; + globals[num_globals - 1].v.svalue = strcpy (buf + namesize, svalue); else globals[num_globals - 1].v.value = value; globals[num_globals - 1].flags = 0; @@ -649,10 +651,10 @@ close_emacs_globals (int num_symbols) static void write_globals (void) { - int i, j; + ptrdiff_t i, j; bool seen_defun = false; - int symnum = 0; - int num_symbols = 0; + ptrdiff_t symnum = 0; + ptrdiff_t num_symbols = 0; qsort (globals, num_globals, sizeof (struct global), compare_globals); j = 0; @@ -665,6 +667,7 @@ write_globals (void) && globals[i].v.value != globals[i + 1].v.value) error ("function '%s' defined twice with differing signatures", globals[i].name); + free (globals[i].name); i++; } num_symbols += globals[i].type == SYMBOL; @@ -707,7 +710,7 @@ write_globals (void) globals[i].name, globals[i].name); } else if (globals[i].type == SYMBOL) - printf (("#define i%s %d\n" + printf (("#define i%s %td\n" "DEFINE_LISP_SYMBOL (%s)\n"), globals[i].name, symnum++, globals[i].name); else @@ -736,7 +739,7 @@ write_globals (void) puts ("#ifdef DEFINE_SYMBOLS"); puts ("static char const *const defsym_name[] = {"); - for (int i = 0; i < num_globals; i++) + for (ptrdiff_t i = 0; i < num_globals; i++) if (globals[i].type == SYMBOL) printf ("\t\"%s\",\n", globals[i].v.svalue); puts ("};"); @@ -745,9 +748,9 @@ write_globals (void) puts ("#define Qnil builtin_lisp_symbol (0)"); puts ("#if DEFINE_NON_NIL_Q_SYMBOL_MACROS"); num_symbols = 0; - for (int i = 0; i < num_globals; i++) + for (ptrdiff_t i = 0; i < num_globals; i++) if (globals[i].type == SYMBOL && num_symbols++ != 0) - printf ("# define %s builtin_lisp_symbol (%d)\n", + printf ("# define %s builtin_lisp_symbol (%td)\n", globals[i].name, num_symbols - 1); puts ("#endif"); } @@ -820,7 +823,8 @@ scan_c_stream (FILE *infile) int defvarperbufferflag = 0; int defvarflag = 0; enum global_type type = INVALID; - char *name IF_LINT (= 0); + static char *name; + static ptrdiff_t name_size; if (c != '\n' && c != '\r') { @@ -925,7 +929,7 @@ scan_c_stream (FILE *infile) if (generate_globals) { - int i = 0; + ptrdiff_t i = 0; char const *svalue = 0; /* Skip "," and whitespace. */ @@ -947,7 +951,16 @@ scan_c_stream (FILE *infile) || c == '\n' || c == '\r')); input_buffer[i] = '\0'; - name = xmalloc (i + 1); + if (name_size <= i) + { + free (name); + name_size = i + 1; + ptrdiff_t doubled; + if (! INT_MULTIPLY_WRAPV (name_size, 2, &doubled) + && doubled <= SIZE_MAX) + name_size = doubled; + name = xmalloc (name_size); + } memcpy (name, input_buffer, i + 1); if (type == SYMBOL) @@ -958,7 +971,7 @@ scan_c_stream (FILE *infile) if (c != '"') continue; c = read_c_string_or_comment (infile, -1, 0, 0); - svalue = xstrdup (input_buffer); + svalue = input_buffer; } if (!defunflag) @@ -1024,6 +1037,8 @@ scan_c_stream (FILE *infile) if (generate_globals) { struct global *g = add_global (FUNCTION, name, maxargs, 0); + if (!g) + continue; /* The following code tries to recognize function attributes specified after the docstring, e.g.: @@ -1278,7 +1293,7 @@ static int scan_lisp_file (const char *filename, const char *mode) { FILE *infile; - register int c; + int c; char *saved_string = 0; /* These are the only files that are loaded uncompiled, and must follow the conventions of the doc strings expected by this @@ -1286,7 +1301,7 @@ scan_lisp_file (const char *filename, const char *mode) byte compiler when it produces the .elc files. */ static struct { const char *fn; - size_t fl; + int fl; } const uncompiled[] = { DEF_ELISP_FILE (loaddefs.el), DEF_ELISP_FILE (loadup.el), @@ -1295,7 +1310,7 @@ scan_lisp_file (const char *filename, const char *mode) DEF_ELISP_FILE (eucjp-ms.el) }; int i, match; - size_t flen = strlen (filename); + int flen = strlen (filename); if (generate_globals) fatal ("scanning lisp file when -g specified", 0); @@ -1345,15 +1360,17 @@ scan_lisp_file (const char *filename, const char *mode) c = getc (infile); if (c == '@') { - size_t length = 0; - size_t i; + ptrdiff_t length = 0; + ptrdiff_t i; /* Read the length. */ while ((c = getc (infile), c >= '0' && c <= '9')) { - length *= 10; - length += c - '0'; + if (INT_MULTIPLY_WRAPV (length, 10, &length) + || INT_ADD_WRAPV (length, c - '0', &length) + || SIZE_MAX < length) + memory_exhausted (); } if (length <= 1) @@ -1369,7 +1386,7 @@ scan_lisp_file (const char *filename, const char *mode) /* Read in the contents. */ free (saved_string); - saved_string = (char *) xmalloc (length); + saved_string = xmalloc (length); for (i = 0; i < length; i++) saved_string[i] = getc (infile); /* The last character is a ^_. @@ -1606,6 +1623,7 @@ scan_lisp_file (const char *filename, const char *mode) else read_c_string_or_comment (infile, 1, 0, 0); } + free (saved_string); fclose (infile); return 0; } -- cgit v1.2.1 From 456c0a3137bf58ee61a8e442cff0ca5d808e8d32 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 10 Feb 2016 11:40:09 -0800 Subject: make-docfile cleanup for I/O, etc. * lib-src/make-docfile.c (progname, generate_globals, num_globals) (num_globals_allocated, globals): Now static. (generate_globals, struct rcsoc_state, read_c_string_or_comment): (write_c_args, scan_c_stream, search_lisp_doc_at_eol, scan_lisp_file): Use bool for boolean. (verror): New function. (fatal, error): Use it. API is now like printf. All callers changed. (main): Remove err_count local that was always 0. (main, scan_c_stream, scan_lisp_file): Check for I/O error. (scan_file, scan_c_file, scan_c_stream, scan_lisp_file): Return void, not 0. (put_char, scan_keyword_or_put_char, scan_c_file): Use char for byte. (scan_keyword_or_put_char): Check for missing ( and unexpected EOF. (close_emacs_globals): Use ptrdiff_t for index, not int. (scan_c_file, scan_lisp_file): Exit with failure if file cannot be opened, rather than diagnosing but exiting with status 0. (search_lisp_doc_at_eol): Don't worry about ungetc of EOF; it's portable now. --- lib-src/make-docfile.c | 200 +++++++++++++++++++++++++++---------------------- 1 file changed, 110 insertions(+), 90 deletions(-) diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index 4ab3729bad0..12222c3db3c 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -65,46 +65,58 @@ along with GNU Emacs. If not, see . */ #define IS_SLASH(c) ((c) == '/') #endif /* not DOS_NT */ -static int scan_file (char *filename); -static int scan_lisp_file (const char *filename, const char *mode); -static int scan_c_file (char *filename, const char *mode); -static int scan_c_stream (FILE *infile); +static void scan_file (char *filename); +static void scan_lisp_file (const char *filename, const char *mode); +static void scan_c_file (char *filename, const char *mode); +static void scan_c_stream (FILE *infile); static void start_globals (void); static void write_globals (void); #include /* Name this program was invoked with. */ -char *progname; +static char *progname; -/* Nonzero if this invocation is generating globals.h. */ -int generate_globals; +/* True if this invocation is generating globals.h. */ +static bool generate_globals; -/* Print error message. `s1' is printf control string, `s2' is arg for it. */ +/* Print error message. Args are like vprintf. */ -/* VARARGS1 */ -static void -error (const char *s1, const char *s2) +static void ATTRIBUTE_FORMAT_PRINTF (1, 0) +verror (char const *m, va_list ap) { fprintf (stderr, "%s: ", progname); - fprintf (stderr, s1, s2); + vfprintf (stderr, m, ap); fprintf (stderr, "\n"); } -/* Print error message and exit. */ +/* Print error message. Args are like printf. */ -/* VARARGS1 */ -static _Noreturn void -fatal (const char *s1, const char *s2) +static void ATTRIBUTE_FORMAT_PRINTF (1, 2) +error (char const *m, ...) +{ + va_list ap; + va_start (ap, m); + verror (m, ap); + va_end (ap); +} + +/* Print error message and exit. Args are like printf. */ + +static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (1, 2) +fatal (char const *m, ...) { - error (s1, s2); + va_list ap; + va_start (ap, m); + verror (m, ap); + va_end (ap); exit (EXIT_FAILURE); } static _Noreturn void memory_exhausted (void) { - fatal ("virtual memory exhausted", 0); + fatal ("virtual memory exhausted"); } /* Like malloc but get fatal error if memory is exhausted. */ @@ -134,7 +146,6 @@ int main (int argc, char **argv) { int i; - int err_count = 0; progname = argv[0]; @@ -169,7 +180,7 @@ main (int argc, char **argv) } if (argc > i && !strcmp (argv[i], "-g")) { - generate_globals = 1; + generate_globals = true; ++i; } @@ -191,14 +202,17 @@ main (int argc, char **argv) if (strcmp (argv[i], argv[j]) == 0) break; if (j == i) - err_count += scan_file (argv[i]); + scan_file (argv[i]); } } - if (err_count == 0 && generate_globals) + if (generate_globals) write_globals (); - return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS); + if (ferror (stdout) || fclose (stdout) != 0) + fatal ("write error"); + + return EXIT_SUCCESS; } /* Add a source file name boundary marker in the output file. */ @@ -217,9 +231,9 @@ put_filename (char *filename) } /* Read file FILENAME and output its doc strings to stdout. - Return 1 if file is not found, 0 if it is found. */ + Return true if file is found, false otherwise. */ -static int +static void scan_file (char *filename) { ptrdiff_t len = strlen (filename); @@ -227,11 +241,11 @@ scan_file (char *filename) if (!generate_globals) put_filename (filename); if (len > 4 && !strcmp (filename + len - 4, ".elc")) - return scan_lisp_file (filename, "rb"); + scan_lisp_file (filename, "rb"); else if (len > 3 && !strcmp (filename + len - 3, ".el")) - return scan_lisp_file (filename, "r"); + scan_lisp_file (filename, "r"); else - return scan_c_file (filename, "r"); + scan_c_file (filename, "r"); } static void @@ -265,16 +279,16 @@ struct rcsoc_state the input stream. */ const char *cur_keyword_ptr; /* Set to true if we saw an occurrence of KEYWORD. */ - int saw_keyword; + bool saw_keyword; }; /* Output CH to the file or buffer in STATE. Any pending newlines or spaces are output first. */ static void -put_char (int ch, struct rcsoc_state *state) +put_char (char ch, struct rcsoc_state *state) { - int out_ch; + char out_ch; do { if (state->pending_newlines > 0) @@ -305,7 +319,7 @@ put_char (int ch, struct rcsoc_state *state) keyword, but were in fact not. */ static void -scan_keyword_or_put_char (int ch, struct rcsoc_state *state) +scan_keyword_or_put_char (char ch, struct rcsoc_state *state) { if (state->keyword && *state->cur_keyword_ptr == ch @@ -317,7 +331,7 @@ scan_keyword_or_put_char (int ch, struct rcsoc_state *state) if (*++state->cur_keyword_ptr == '\0') /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */ { - state->saw_keyword = 1; + state->saw_keyword = true; /* Reset the scanning pointer. */ state->cur_keyword_ptr = state->keyword; @@ -328,22 +342,29 @@ scan_keyword_or_put_char (int ch, struct rcsoc_state *state) /* Skip any whitespace between the keyword and the usage string. */ + int c; do - ch = getc (state->in_file); - while (ch == ' ' || ch == '\n'); + c = getc (state->in_file); + while (c == ' ' || c == '\n'); /* Output the open-paren we just read. */ - put_char (ch, state); + if (c != '(') + fatal ("Missing '(' after keyword"); + put_char (c, state); /* Skip the function name and replace it with `fn'. */ do - ch = getc (state->in_file); - while (ch != ' ' && ch != ')'); + { + c = getc (state->in_file); + if (c == EOF) + fatal ("Unexpected EOF after keyword"); + } + while (c != ' ' && c != ')'); put_char ('f', state); put_char ('n', state); /* Put back the last character. */ - ungetc (ch, state->in_file); + ungetc (c, state->in_file); } } else @@ -367,18 +388,19 @@ scan_keyword_or_put_char (int ch, struct rcsoc_state *state) /* Skip a C string or C-style comment from INFILE, and return the - character that follows. COMMENT non-zero means skip a comment. If + byte that follows, or EOF. COMMENT means skip a comment. If PRINTFLAG is positive, output string contents to stdout. If it is negative, store contents in buf. Convert escape sequences \n and \t to newline and tab; discard \ followed by newline. - If SAW_USAGE is non-zero, then any occurrences of the string `usage:' + If SAW_USAGE is non-null, then any occurrences of the string "usage:" at the beginning of a line will be removed, and *SAW_USAGE set to true if any were encountered. */ static int -read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage) +read_c_string_or_comment (FILE *infile, int printflag, bool comment, + bool *saw_usage) { - register int c; + int c; struct rcsoc_state state; state.in_file = infile; @@ -388,7 +410,7 @@ read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usa state.pending_newlines = 0; state.keyword = (saw_usage ? "usage:" : 0); state.cur_keyword_ptr = state.keyword; - state.saw_keyword = 0; + state.saw_keyword = false; c = getc (infile); if (comment) @@ -467,7 +489,7 @@ static void write_c_args (char *func, char *buf, int minargs, int maxargs) { char *p; - int in_ident = 0; + bool in_ident = false; char *ident_start IF_LINT (= NULL); ptrdiff_t ident_length = 0; @@ -489,12 +511,12 @@ write_c_args (char *func, char *buf, int minargs, int maxargs) { if (!in_ident) { - in_ident = 1; + in_ident = true; ident_start = p; } else { - in_ident = 0; + in_ident = false; ident_length = p - ident_start; } } @@ -573,9 +595,9 @@ enum { DEFUN_noreturn = 1, DEFUN_const = 2 }; /* All the variable names we saw while scanning C sources in `-g' mode. */ -ptrdiff_t num_globals; -ptrdiff_t num_globals_allocated; -struct global *globals; +static ptrdiff_t num_globals; +static ptrdiff_t num_globals_allocated; +static struct global *globals; static struct global * add_global (enum global_type type, char const *name, int value, @@ -636,7 +658,7 @@ compare_globals (const void *a, const void *b) } static void -close_emacs_globals (int num_symbols) +close_emacs_globals (ptrdiff_t num_symbols) { printf (("};\n" "extern struct emacs_globals globals;\n" @@ -644,7 +666,7 @@ close_emacs_globals (int num_symbols) "#ifndef DEFINE_SYMBOLS\n" "extern\n" "#endif\n" - "struct Lisp_Symbol alignas (GCALIGNMENT) lispsym[%d];\n"), + "struct Lisp_Symbol alignas (GCALIGNMENT) lispsym[%td];\n"), num_symbols); } @@ -700,7 +722,7 @@ write_globals (void) } break; default: - fatal ("not a recognized DEFVAR_", 0); + fatal ("not a recognized DEFVAR_"); } if (type) @@ -761,11 +783,11 @@ write_globals (void) Looks for DEFUN constructs such as are defined in ../src/lisp.h. Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */ -static int +static void scan_c_file (char *filename, const char *mode) { FILE *infile; - int extension = filename[strlen (filename) - 1]; + char extension = filename[strlen (filename) - 1]; if (extension == 'o') filename[strlen (filename) - 1] = 'c'; @@ -781,16 +803,15 @@ scan_c_file (char *filename, const char *mode) filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */ } - /* No error if non-ex input file. */ if (infile == NULL) { perror (filename); - return 0; + exit (EXIT_FAILURE); } /* Reset extension to be able to detect duplicate files. */ filename[strlen (filename) - 1] = extension; - return scan_c_stream (infile); + scan_c_stream (infile); } /* Return 1 if next input from INFILE is equal to P, -1 if EOF, @@ -810,7 +831,7 @@ stream_match (FILE *infile, const char *p) return 1; } -static int +static void scan_c_stream (FILE *infile) { int commas, minargs, maxargs; @@ -818,10 +839,10 @@ scan_c_stream (FILE *infile) while (!feof (infile)) { - int doc_keyword = 0; - int defunflag = 0; - int defvarperbufferflag = 0; - int defvarflag = 0; + bool doc_keyword = false; + bool defunflag = false; + bool defvarperbufferflag = false; + bool defvarflag = false; enum global_type type = INVALID; static char *name; static ptrdiff_t name_size; @@ -870,7 +891,7 @@ scan_c_stream (FILE *infile) if (c != '_') continue; - defvarflag = 1; + defvarflag = true; c = getc (infile); defvarperbufferflag = (c == 'P'); @@ -924,7 +945,7 @@ scan_c_stream (FILE *infile) c = getc (infile); if (c != '"') continue; - c = read_c_string_or_comment (infile, -1, 0, 0); + c = read_c_string_or_comment (infile, -1, false, 0); } if (generate_globals) @@ -970,7 +991,7 @@ scan_c_stream (FILE *infile) while (c == ' ' || c == '\t' || c == '\n' || c == '\r'); if (c != '"') continue; - c = read_c_string_or_comment (infile, -1, 0, 0); + c = read_c_string_or_comment (infile, -1, false, 0); svalue = input_buffer; } @@ -1102,7 +1123,7 @@ scan_c_stream (FILE *infile) c = getc (infile); if (c == '"') - c = read_c_string_or_comment (infile, 0, 0, 0); + c = read_c_string_or_comment (infile, 0, false, 0); while (c != EOF && c != ',' && c != '/') c = getc (infile); @@ -1115,7 +1136,7 @@ scan_c_stream (FILE *infile) c = getc (infile); if (c == ':') { - doc_keyword = 1; + doc_keyword = true; c = getc (infile); while (c == ' ' || c == '\n' || c == '\r' || c == '\t') c = getc (infile); @@ -1128,8 +1149,8 @@ scan_c_stream (FILE *infile) ungetc (c, infile), c == '*'))) { - int comment = c != '"'; - int saw_usage; + bool comment = c != '"'; + bool saw_usage; printf ("\037%c%s\n", defvarflag ? 'V' : 'F', input_buffer); @@ -1183,8 +1204,8 @@ scan_c_stream (FILE *infile) } } eof: - fclose (infile); - return 0; + if (ferror (infile) || fclose (infile) != 0) + fatal ("read error"); } /* Read a file of Lisp code, compiled or interpreted. @@ -1260,7 +1281,7 @@ read_lisp_symbol (FILE *infile, char *buffer) skip_white (infile); } -static int +static bool search_lisp_doc_at_eol (FILE *infile) { int c = 0, c1 = 0, c2 = 0; @@ -1280,16 +1301,15 @@ search_lisp_doc_at_eol (FILE *infile) #ifdef DEBUG fprintf (stderr, "## non-docstring found\n"); #endif - if (c != EOF) - ungetc (c, infile); - return 0; + ungetc (c, infile); + return false; } - return 1; + return true; } #define DEF_ELISP_FILE(fn) { #fn, sizeof(#fn) - 1 } -static int +static void scan_lisp_file (const char *filename, const char *mode) { FILE *infile; @@ -1309,22 +1329,22 @@ scan_lisp_file (const char *filename, const char *mode) DEF_ELISP_FILE (cp51932.el), DEF_ELISP_FILE (eucjp-ms.el) }; - int i, match; + int i; int flen = strlen (filename); if (generate_globals) - fatal ("scanning lisp file when -g specified", 0); + fatal ("scanning lisp file when -g specified"); if (flen > 3 && !strcmp (filename + flen - 3, ".el")) { - for (i = 0, match = 0; i < sizeof (uncompiled) / sizeof (uncompiled[0]); - i++) + bool match = false; + for (i = 0; i < sizeof (uncompiled) / sizeof (uncompiled[0]); i++) { if (uncompiled[i].fl <= flen && !strcmp (filename + flen - uncompiled[i].fl, uncompiled[i].fn) && (flen == uncompiled[i].fl || IS_SLASH (filename[flen - uncompiled[i].fl - 1]))) { - match = 1; + match = true; break; } } @@ -1336,7 +1356,7 @@ scan_lisp_file (const char *filename, const char *mode) if (infile == NULL) { perror (filename); - return 0; /* No error. */ + exit (EXIT_FAILURE); } c = '\n'; @@ -1374,10 +1394,10 @@ scan_lisp_file (const char *filename, const char *mode) } if (length <= 1) - fatal ("invalid dynamic doc string length", ""); + fatal ("invalid dynamic doc string length"); if (c != ' ') - fatal ("space not found after dynamic doc string length", ""); + fatal ("space not found after dynamic doc string length"); /* The next character is a space that is counted in the length but not part of the doc string. @@ -1585,7 +1605,7 @@ scan_lisp_file (const char *filename, const char *mode) buffer, filename); continue; } - read_c_string_or_comment (infile, 0, 0, 0); + read_c_string_or_comment (infile, 0, false, 0); if (saved_string == 0) if (!search_lisp_doc_at_eol (infile)) @@ -1621,11 +1641,11 @@ scan_lisp_file (const char *filename, const char *mode) saved_string = 0; } else - read_c_string_or_comment (infile, 1, 0, 0); + read_c_string_or_comment (infile, 1, false, 0); } free (saved_string); - fclose (infile); - return 0; + if (ferror (infile) || fclose (infile) != 0) + fatal ("%s: read error", filename); } -- cgit v1.2.1 From eb4a18c7db2286bcb9d9ea8f392175a28a86772c Mon Sep 17 00:00:00 2001 From: Alan Third Date: Wed, 10 Feb 2016 18:27:50 -0800 Subject: Set locale when run from OS X GUI * src/emacs.c (main): Call ns_init_locale. * src/nsterm.m (ns_init_locale): Get locale from OS and set LANG. * src/nsterm.h: Include ns_init_locale. --- src/emacs.c | 5 +++++ src/nsterm.h | 2 ++ src/nsterm.m | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/src/emacs.c b/src/emacs.c index e3cfad0f7f8..ab5d777aa2e 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1310,6 +1310,11 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_ntproc (dumping); /* must precede init_editfns. */ #endif +#ifdef HAVE_NS + /* Initialise the locale from user defaults. */ + ns_init_locale(); +#endif + /* Initialize and GC-protect Vinitial_environment and Vprocess_environment before set_initial_environment fills them in. */ diff --git a/src/nsterm.h b/src/nsterm.h index 6ca584e6774..fa5399c7f90 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -1141,6 +1141,8 @@ extern void ns_retain_object (void *obj); extern void *ns_alloc_autorelease_pool (void); extern void ns_release_autorelease_pool (void *); extern const char *ns_get_defaults_value (const char *key); +extern void ns_init_locale (void); + /* in nsmenu */ extern void update_frame_tool_bar (struct frame *f); diff --git a/src/nsterm.m b/src/nsterm.m index f77aadba67c..43d1377f8a7 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -585,6 +585,27 @@ ns_load_path (void) } +void +ns_init_locale (void) +/* OS X doesn't set any environment variables for the locale when run + from the GUI. Get the locale from the OS and set LANG. */ +{ + NSLocale *locale = [NSLocale currentLocale]; + + NSTRACE ("ns_init_locale"); + + @try + { + /* Set LANG to locale, but not if LANG is already set. */ + setenv("LANG", [[locale localeIdentifier] UTF8String], 0); + } + @catch (NSException *e) + { + NSLog (@"Locale detection failed: %@: %@", [e name], [e reason]); + } +} + + void ns_release_object (void *obj) /* -------------------------------------------------------------------------- -- cgit v1.2.1 From c6f377cbae09a77d4f77e092d29bf611a3a37ff3 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 10 Feb 2016 18:35:26 -0800 Subject: Document OS X LANG default * doc/emacs/cmdargs.texi (General Variables): Document OS X Language and Region system preference. Suggested by Alan Third. --- doc/emacs/cmdargs.texi | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi index a1b0b098f22..a842cb84abd 100644 --- a/doc/emacs/cmdargs.texi +++ b/doc/emacs/cmdargs.texi @@ -550,10 +550,11 @@ variables is not set, the category defaults to the value of the @env{LANG} is not set. But if @env{LC_ALL} is specified, it overrides the settings of all the other locale environment variables. -On MS-Windows, if @env{LANG} is not already set in the environment -when Emacs starts, Emacs sets it based on the system-wide default -language, which you can set in the @samp{Regional Settings} Control Panel -on some versions of MS-Windows. +On MS-Windows and OS X, if @env{LANG} is not already set in the +environment, Emacs sets it based on the system-wide default. You can +set this in the ``Regional Settings'' Control Panel on some versions +of MS-Windows, and in the ``Language and Region'' System Preference on +OS X. The value of the @env{LC_CTYPE} category is matched against entries in @code{locale-language-names}, -- cgit v1.2.1 From afe7d1f72f78cfd8ce4b6fec6b0be49f49751fd2 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 11 Feb 2016 14:05:02 +1100 Subject: Revert "Document EXIF image rotation" This reverts commit 10b8ed27ec91ff52f93eb0297dcc3abb214931aa. This change does not work on Fedora, for instance. --- doc/lispref/display.texi | 4 +--- etc/NEWS | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 1ba91235759..323895927a9 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5205,9 +5205,7 @@ when the image does not have an associated file name, to provide a hint to ImageMagick to help it detect the image type. @item :rotation @var{angle} -Specifies a rotation angle in degrees. If no rotation is explicitly -specified, and the @acronym{EXIF} headers specify a rotation, the -rotation from the @acronym{EXIF} headers are used instead. +Specifies a rotation angle in degrees. @item :index @var{frame} @c Doesn't work: http://debbugs.gnu.org/7978 diff --git a/etc/NEWS b/etc/NEWS index c1338680541..70f9476e71e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -633,10 +633,6 @@ character-folds into STRING. text in the region. The search engine to use for this is specified by the customizable variable `eww-search-prefix'. -+++ -*** Images that have rotation specified in the EXIF headers are now -automatically rotated (if displayed as ImageMagick images). - +++ *** Query-replace history is enhanced. When query-replace reads the FROM string from the minibuffer, typing -- cgit v1.2.1 From f5d6b9bb5b307067547f0b26c74e9f538464bfc6 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 11 Feb 2016 14:05:24 +1100 Subject: Revert "Support integer image rotation and respect EXIF rotations" This reverts commit 0f600496050bf435f55dc81056e06fcd45992dc8. This change does not work on Fedora. --- src/image.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/image.c b/src/image.c index 45abfc7af76..144fe30a746 100644 --- a/src/image.c +++ b/src/image.c @@ -8546,16 +8546,6 @@ imagemagick_load_image (struct frame *f, struct image *img, return 0; } - /* If no :rotation is explicitly specified, apply the automatic - rotation from EXIF. */ - if (NILP (image_spec_value (img->spec, QCrotation, NULL))) - if (MagickAutoOrientImage (image_wand) == MagickFalse) - { - image_error ("Error applying automatic orientation in image `%s'", img->spec); - DestroyMagickWand (image_wand); - return 0; - } - if (ino < 0 || ino >= MagickGetNumberImages (image_wand)) { image_error ("Invalid image number `%s' in image `%s'", image, img->spec); @@ -8656,7 +8646,7 @@ imagemagick_load_image (struct frame *f, struct image *img, image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP (specified_bg). */ value = image_spec_value (img->spec, QCrotation, NULL); - if (FLOATP (value) || INTEGERP (value)) + if (FLOATP (value)) { rotation = extract_float (value); status = MagickRotateImage (image_wand, bg_wand, rotation); -- cgit v1.2.1