=== modified file 'doc/lispref/ChangeLog' --- doc/lispref/ChangeLog 2013-01-10 03:43:02 +0000 +++ doc/lispref/ChangeLog 2013-01-19 09:57:59 +0000 @@ -1,3 +1,9 @@ +2013-01-19 Paul Eggert + + Allow floating-point file offsets. + * files.texi (Reading from Files, Writing to Files): + Say that file offsets can be numbers, not just integers. + 2013-01-09 Glenn Morris * commands.texi (Interactive Codes): === modified file 'doc/lispref/files.texi' --- doc/lispref/files.texi 2013-01-04 02:42:08 +0000 +++ doc/lispref/files.texi 2013-01-19 09:57:59 +0000 @@ -533,9 +533,9 @@ file name and its last save file modtime. This feature is used by @code{find-file-noselect} and you probably should not use it yourself. -If @var{beg} and @var{end} are address@hidden, they should be integers -specifying the portion of the file to insert. In this case, @var{visit} -must be @code{nil}. For example, +If @var{beg} and @var{end} are address@hidden, they should be numbers +that are byte offsets specifying the portion of the file to insert. +In this case, @var{visit} must be @code{nil}. For example, @example (insert-file-contents filename nil 0 500) @@ -605,8 +605,8 @@ this case. If @var{append} is address@hidden, then the specified text is appended -to the existing file contents (if any). If @var{append} is an -integer, @code{write-region} seeks to that byte offset from the start +to the existing file contents (if any). If @var{append} is a +number, @code{write-region} seeks to that byte offset from the start of the file and writes the data from there. If @var{mustbenew} is address@hidden, then @code{write-region} asks === modified file 'src/ChangeLog' --- src/ChangeLog 2013-01-19 08:49:17 +0000 +++ src/ChangeLog 2013-01-19 09:57:59 +0000 @@ -1,3 +1,12 @@ +2013-01-19 Paul Eggert + + Allow floating-point file offsets. + Problem reported by Vitalie Spinu in + . + * fileio.c (emacs_lseek): Remove. + (file_offset): New function. + (Finsert_file_contents, Fwrite_region): Use it. + 2013-01-19 Chong Yidong * emacs.c (Fkill_emacs): Set waiting_for_input to 0 to avoid === modified file 'src/fileio.c' --- src/fileio.c 2013-01-19 04:44:34 +0000 +++ src/fileio.c 2013-01-19 09:57:59 +0000 @@ -3443,19 +3443,25 @@ return Qnil; } -/* Reposition FD to OFFSET, based on WHENCE. This acts like lseek - except that it also tests for OFFSET being out of lseek's range. */ +/* Return the file offset that VAL represents, checking for type + errors and overflow. */ static off_t -emacs_lseek (int fd, EMACS_INT offset, int whence) +file_offset (Lisp_Object val) { - /* Use "&" rather than "&&" to suppress a bogus GCC warning; see - . */ - if (! ((offset >= TYPE_MINIMUM (off_t)) & (offset <= TYPE_MAXIMUM (off_t)))) + if (RANGED_INTEGERP (0, val, TYPE_MAXIMUM (off_t))) + return XINT (val); + + if (FLOATP (val)) { - errno = EINVAL; - return -1; + double v = XFLOAT_DATA (val); + if (0 <= v + && (sizeof (off_t) < sizeof v + ? v <= TYPE_MAXIMUM (off_t) + : v < TYPE_MAXIMUM (off_t))) + return v; } - return lseek (fd, offset, whence); + + wrong_type_argument (intern ("file-offset"), val); } /* Return a special time value indicating the error number ERRNUM. */ @@ -3606,20 +3612,12 @@ } if (!NILP (beg)) - { - if (! RANGED_INTEGERP (0, beg, TYPE_MAXIMUM (off_t))) - wrong_type_argument (intern ("file-offset"), beg); - beg_offset = XFASTINT (beg); - } + beg_offset = file_offset (beg); else beg_offset = 0; if (!NILP (end)) - { - if (! RANGED_INTEGERP (0, end, TYPE_MAXIMUM (off_t))) - wrong_type_argument (intern ("file-offset"), end); - end_offset = XFASTINT (end); - } + end_offset = file_offset (end); else { if (not_regular) @@ -4714,7 +4712,7 @@ instead of any buffer contents; END is ignored. Optional fourth argument APPEND if non-nil means - append to existing file contents (if any). If it is an integer, + append to existing file contents (if any). If it is a number, seek to that offset in the file before writing. Optional fifth argument VISIT, if t or a string, means set the last-save-file-modtime of buffer to this file's modtime @@ -4743,6 +4741,7 @@ (Lisp_Object start, Lisp_Object end, Lisp_Object filename, Lisp_Object append, Lisp_Object visit, Lisp_Object lockname, Lisp_Object mustbenew) { int desc; + off_t offset; bool ok; int save_errno = 0; const char *fn; @@ -4864,13 +4863,14 @@ encoded_filename = ENCODE_FILE (filename); fn = SSDATA (encoded_filename); + offset = 0; desc = -1; if (!NILP (append)) -#ifdef DOS_NT - desc = emacs_open (fn, O_WRONLY | O_BINARY, 0); -#else /* not DOS_NT */ - desc = emacs_open (fn, O_WRONLY, 0); -#endif /* not DOS_NT */ + { + if (NUMBERP (append)) + offset = file_offset (append); + desc = emacs_open (fn, O_WRONLY | O_BINARY, 0); + } if (desc < 0 && (NILP (append) || errno == ENOENT)) #ifdef DOS_NT @@ -4897,14 +4897,9 @@ record_unwind_protect (close_file_unwind, make_number (desc)); - if (!NILP (append) && !NILP (Ffile_regular_p (filename))) + if (!NILP (append)) { - off_t ret; - - if (NUMBERP (append)) - ret = emacs_lseek (desc, XINT (append), SEEK_CUR); - else - ret = lseek (desc, 0, SEEK_END); + off_t ret = lseek (desc, offset, NUMBERP (append) ? SEEK_SET : SEEK_END); if (ret < 0) { #ifdef CLASH_DETECTION