for (EMACS_INT size = XFASTINT (length); 0 < size; size--)
{
val = Fcons (init, val);
- maybe_quit ();
+ rarely_quit (size);
}
return val;
{
Lisp_Object v2 = POP, v1 = TOP;
CHECK_NUMBER (v1);
- EMACS_INT n = XINT (v1);
- while (--n >= 0 && CONSP (v2))
- v2 = XCDR (v2);
+ for (EMACS_INT n = XINT (v1); 0 < n && CONSP (v2); n--)
+ {
+ v2 = XCDR (v2);
+ rarely_quit (n);
+ }
TOP = CAR (v2);
NEXT;
}
/* Exchange args and then do nth. */
Lisp_Object v2 = POP, v1 = TOP;
CHECK_NUMBER (v2);
- EMACS_INT n = XINT (v2);
- while (--n >= 0 && CONSP (v1))
- v1 = XCDR (v1);
+ for (EMACS_INT n = XINT (v2); 0 < n && CONSP (v1); n--)
+ {
+ v1 = XCDR (v1);
+ rarely_quit (n);
+ }
TOP = CAR (v1);
}
else
{
kill (-synch_process_pid, SIGINT);
message1 ("Waiting for process to die...(type C-g again to kill it instantly)");
- maybe_quit ();
wait_for_termination (synch_process_pid, 0, 1);
synch_process_pid = 0;
message1 ("Waiting for process to die...done");
process_coding.src_multibyte = 0;
}
- maybe_quit ();
-
if (0 <= fd0)
{
enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 };
nread = carryover;
while (nread < bufsize - 1024)
{
- int this_read = emacs_read (fd0, buf + nread,
- bufsize - nread);
+ int this_read = emacs_read_quit (fd0, buf + nread,
+ bufsize - nread);
if (this_read < 0)
goto give_up;
we should have already detected a coding system. */
display_on_the_fly = true;
}
-
- maybe_quit ();
}
give_up: ;
If we read the same block last time, maybe skip this? */
if (space_left > 1024 * 8)
space_left = 1024 * 8;
- nread = emacs_read (fd, p, space_left);
+ nread = emacs_read_quit (fd, p, space_left);
if (nread < 0)
report_file_error ("Read error on documentation file", file);
p[nread] = 0;
Vdoc_file_name = filename;
filled = 0;
pos = 0;
- while (1)
+ while (true)
{
- register char *end;
if (filled < 512)
- filled += emacs_read (fd, &buf[filled], sizeof buf - 1 - filled);
+ filled += emacs_read_quit (fd, &buf[filled], sizeof buf - 1 - filled);
if (!filled)
break;
buf[filled] = 0;
- end = buf + (filled < 512 ? filled : filled - 128);
+ char *end = buf + (filled < 512 ? filled : filled - 128);
p = memchr (buf, '\037', end - buf);
/* p points to ^_Ffunctionname\n or ^_Vvarname\n or ^_Sfilename\n. */
if (p)
return make_number (c1 < c2 ? -1 - chars : chars + 1);
chars++;
+ rarely_quit (chars);
}
/* The strings match as far as they go.
quit ();
}
+/* Check quit-flag and quit if it is non-nil. Typing C-g does not
+ directly cause a quit; it only sets Vquit_flag. So the program
+ needs to call maybe_quit at times when it is safe to quit. Every
+ loop that might run for a long time or might not exit ought to call
+ maybe_quit at least once, at a safe place. Unless that is
+ impossible, of course. But it is very desirable to avoid creating
+ loops where maybe_quit is impossible.
+
+ If quit-flag is set to `kill-emacs' the SIGINT handler has received
+ a request to exit Emacs when it is safe to do.
+
+ When not quitting, process any pending signals. */
+
void
maybe_quit (void)
{
{
char buf[MAX_ALLOCA];
ptrdiff_t n;
- for (newsize = 0; 0 < (n = emacs_read (ifd, buf, sizeof buf));
+ for (newsize = 0; 0 < (n = emacs_read_quit (ifd, buf, sizeof buf));
newsize += n)
- if (emacs_write_sig (ofd, buf, n) != n)
+ if (emacs_write_quit (ofd, buf, n) != n)
report_file_error ("Write error", newname);
if (n < 0)
report_file_error ("Read error", file);
static Lisp_Object
read_non_regular (Lisp_Object state)
{
- int nbytes;
-
- maybe_quit ();
- nbytes = emacs_read (XSAVE_INTEGER (state, 0),
- ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE
- + XSAVE_INTEGER (state, 1)),
- XSAVE_INTEGER (state, 2));
+ int nbytes = emacs_read_quit (XSAVE_INTEGER (state, 0),
+ ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE
+ + XSAVE_INTEGER (state, 1)),
+ XSAVE_INTEGER (state, 2));
/* Fast recycle this object for the likely next call. */
free_misc (state);
return make_number (nbytes);
int nread;
if (st.st_size <= (1024 * 4))
- nread = emacs_read (fd, read_buf, 1024 * 4);
+ nread = emacs_read_quit (fd, read_buf, 1024 * 4);
else
{
- nread = emacs_read (fd, read_buf, 1024);
+ nread = emacs_read_quit (fd, read_buf, 1024);
if (nread == 1024)
{
int ntail;
if (lseek (fd, - (1024 * 3), SEEK_END) < 0)
report_file_error ("Setting file position",
orig_filename);
- ntail = emacs_read (fd, read_buf + nread, 1024 * 3);
+ ntail = emacs_read_quit (fd, read_buf + nread, 1024 * 3);
nread = ntail < 0 ? ntail : nread + ntail;
}
}
report_file_error ("Setting file position", orig_filename);
}
- maybe_quit ();
/* Count how many chars at the start of the file
match the text at the beginning of the buffer. */
- while (1)
+ while (true)
{
- int nread, bufpos;
-
- nread = emacs_read (fd, read_buf, sizeof read_buf);
+ int nread = emacs_read_quit (fd, read_buf, sizeof read_buf);
if (nread < 0)
report_file_error ("Read error", orig_filename);
else if (nread == 0)
break;
}
- bufpos = 0;
+ int bufpos = 0;
while (bufpos < nread && same_at_start < ZV_BYTE
&& FETCH_BYTE (same_at_start) == read_buf[bufpos])
same_at_start++, bufpos++;
del_range_1 (same_at_start, same_at_end, 0, 0);
goto handled;
}
- maybe_quit ();
+
/* Count how many chars at the end of the file
match the text at the end of the buffer. But, if we have
already found that decoding is necessary, don't waste time. */
total_read = nread = 0;
while (total_read < trial)
{
- nread = emacs_read (fd, read_buf + total_read, trial - total_read);
+ nread = emacs_read_quit (fd, read_buf + total_read,
+ trial - total_read);
if (nread < 0)
report_file_error ("Read error", orig_filename);
else if (nread == 0)
inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
unprocessed = 0; /* Bytes not processed in previous loop. */
- while (1)
+ while (true)
{
/* Read at most READ_BUF_SIZE bytes at a time, to allow
quitting while reading a huge file. */
- /* Allow quitting out of the actual I/O. */
- maybe_quit ();
- this = emacs_read (fd, read_buf + unprocessed,
- READ_BUF_SIZE - unprocessed);
-
+ this = emacs_read_quit (fd, read_buf + unprocessed,
+ READ_BUF_SIZE - unprocessed);
if (this <= 0)
break;
/* Allow quitting out of the actual I/O. We don't make text
part of the buffer until all the reading is done, so a C-g
here doesn't do any harm. */
- maybe_quit ();
- this = emacs_read (fd,
- ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE
- + inserted),
- trytry);
+ this = emacs_read_quit (fd,
+ ((char *) BEG_ADDR + PT_BYTE - BEG_BYTE
+ + inserted),
+ trytry);
}
if (this <= 0)
: (STRINGP (coding->dst_object)
? SSDATA (coding->dst_object)
: (char *) BYTE_POS_ADDR (coding->dst_pos_byte)));
- coding->produced -= emacs_write_sig (desc, buf, coding->produced);
+ coding->produced -= emacs_write_quit (desc, buf, coding->produced);
if (coding->raw_destination)
{
fcntl (fd, F_SETFD, FD_CLOEXEC);
lock_info_len = strlen (lock_info_str);
err = 0;
- /* Use 'write', not 'emacs_write', as garbage collection
- might signal an error, which would leak FD. */
- if (write (fd, lock_info_str, lock_info_len) != lock_info_len
+ if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
|| fchmod (fd, S_IRUSR | S_IRGRP | S_IROTH) != 0)
err = errno;
/* There is no need to call fsync here, as the contents of
int fd = emacs_open (lfname, O_RDONLY | O_NOFOLLOW, 0);
if (0 <= fd)
{
- /* Use read, not emacs_read, since FD isn't unwind-protected. */
- ptrdiff_t read_bytes = read (fd, lfinfo, MAX_LFINFO + 1);
+ ptrdiff_t read_bytes = emacs_read (fd, lfinfo, MAX_LFINFO + 1);
int read_errno = errno;
if (emacs_close (fd) != 0)
return -1;
return make_number (val);
}
\f
-/* Heuristic on how many iterations of a tight loop can be safely done
- before it's time to do a quit. This must be a power of 2. It
- is nice but not necessary for it to equal USHRT_MAX + 1. */
-enum { QUIT_COUNT_HEURISTIC = 1 << 16 };
-
-/* Process a quit, but do it only rarely, for efficiency. "Rarely"
- means once per QUIT_COUNT_HEURISTIC or per USHRT_MAX + 1 times,
- whichever is smaller. Use *QUIT_COUNT to count this. */
-
-static void
-rarely_quit (unsigned short int *quit_count)
-{
- if (! (++*quit_count & (QUIT_COUNT_HEURISTIC - 1)))
- maybe_quit ();
-}
-
/* Random data-structure functions. */
DEFUN ("length", Flength, Slength, 1, 1, 0,
(Lisp_Object n, Lisp_Object list)
{
CHECK_NUMBER (n);
- EMACS_INT num = XINT (n);
Lisp_Object tail = list;
- for (EMACS_INT i = 0; i < num; i++)
+ for (EMACS_INT num = XINT (n); 0 < num; num--)
{
if (! CONSP (tail))
{
return Qnil;
}
tail = XCDR (tail);
+ rarely_quit (num);
}
return tail;
}
{
if (! NILP (Fequal (elt, XCAR (tail))))
return tail;
- rarely_quit (&quit_count);
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
The value is actually the tail of LIST whose car is ELT. */)
(Lisp_Object elt, Lisp_Object list)
{
+ unsigned short int quit_count = 0;
Lisp_Object tail;
for (tail = list; CONSP (tail); tail = XCDR (tail))
{
if (EQ (XCAR (tail), elt))
return tail;
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
if (!FLOATP (elt))
return Fmemq (elt, list);
+ unsigned short int quit_count = 0;
Lisp_Object tail;
for (tail = list; CONSP (tail); tail = XCDR (tail))
{
Lisp_Object tem = XCAR (tail);
if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil))
return tail;
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
Elements of LIST that are not conses are ignored. */)
(Lisp_Object key, Lisp_Object list)
{
+ unsigned short int quit_count = 0;
Lisp_Object tail;
for (tail = list; CONSP (tail); tail = XCDR (tail))
{
if (CONSP (XCAR (tail)) && EQ (XCAR (XCAR (tail)), key))
return XCAR (tail);
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
if (CONSP (car)
&& (EQ (XCAR (car), key) || !NILP (Fequal (XCAR (car), key))))
return car;
- rarely_quit (&quit_count);
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
The value is actually the first element of LIST whose cdr is KEY. */)
(Lisp_Object key, Lisp_Object list)
{
+ unsigned short int quit_count = 0;
Lisp_Object tail;
for (tail = list; CONSP (tail); tail = XCDR (tail))
{
if (CONSP (XCAR (tail)) && EQ (XCDR (XCAR (tail)), key))
return XCAR (tail);
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
if (CONSP (car)
&& (EQ (XCDR (car), key) || !NILP (Fequal (XCDR (car), key))))
return car;
- rarely_quit (&quit_count);
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, list);
return Qnil;
}
else
prev = tail;
- rarely_quit (&quit_count);
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, seq);
}
for (prev = Qnil, tail = seq; CONSP (tail); tail = next)
{
- rarely_quit (&quit_count);
next = XCDR (tail);
Fsetcdr (tail, prev);
prev = tail;
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, seq);
seq = prev;
unsigned short int quit_count = 0;
for (new = Qnil; CONSP (seq); seq = XCDR (seq))
{
- rarely_quit (&quit_count);
new = Fcons (XCAR (seq), new);
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (seq, seq);
}
The PLIST is modified by side effects. */)
(Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
{
+ unsigned short int quit_count = 0;
Lisp_Object prev = Qnil;
for (Lisp_Object tail = plist; CONSP (tail) && CONSP (XCDR (tail));
tail = XCDR (XCDR (tail)))
}
prev = tail;
+ incr_rarely_quit (&quit_count);
}
Lisp_Object newcell
= Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev))));
{
if (! NILP (Fequal (prop, XCAR (tail))))
return XCAR (XCDR (tail));
- rarely_quit (&quit_count);
+ incr_rarely_quit (&quit_count);
}
CHECK_LIST_END (tail, prop);
}
prev = tail;
- rarely_quit (&quit_count);
+ incr_rarely_quit (&quit_count);
}
Lisp_Object newcell = list2 (prop, val);
if (NILP (prev))
unsigned short int quit_count = 0;
tail_recurse:
- rarely_quit (&quit_count);
+ incr_rarely_quit (&quit_count);
if (EQ (o1, o2))
return 1;
if (XTYPE (o1) != XTYPE (o2))
{
tail = tem;
tem = XCDR (tail);
+ incr_rarely_quit (&quit_count);
}
while (CONSP (tem));
- rarely_quit (&quit_count);
-
tem = args[argnum + 1];
Fsetcdr (tail, tem);
if (NILP (tem))
The value is actually the tail of PLIST whose car is PROP. */)
(Lisp_Object plist, Lisp_Object prop)
{
+ unsigned short int quit_count = 0;
while (CONSP (plist) && !EQ (XCAR (plist), prop))
{
plist = XCDR (plist);
plist = CDR (plist);
+ incr_rarely_quit (&quit_count);
}
return plist;
}
continuation_glyph_width = 0; /* In the fringe. */
#endif
- maybe_quit ();
-
/* It's just impossible to be too paranoid here. */
eassert (from == BYTE_TO_CHAR (frombyte) && frombyte == CHAR_TO_BYTE (from));
cmp_it.id = -1;
composition_compute_stop_pos (&cmp_it, pos, pos_byte, to, Qnil);
- while (1)
+ unsigned short int quit_count = 0;
+
+ while (true)
{
+ incr_rarely_quit (&quit_count);
+
while (pos == next_boundary)
{
ptrdiff_t pos_here = pos;
pos = newpos;
pos_byte = CHAR_TO_BYTE (pos);
}
+
+ incr_rarely_quit (&quit_count);
}
/* Handle right margin. */
pos = find_before_next_newline (pos, to, 1, &pos_byte);
if (pos < to)
INC_BOTH (pos, pos_byte);
+ incr_rarely_quit (&quit_count);
}
while (pos < to
&& indented_beyond_p (pos, pos_byte,
/* Now read; for one reason or another, this will not block.
NREAD is set to the number of chars read. */
- do
- {
- nread = emacs_read (fileno (tty->input), (char *) cbuf, n_to_read);
- /* POSIX infers that processes which are not in the session leader's
- process group won't get SIGHUPs at logout time. BSDI adheres to
- this part standard and returns -1 from read (0) with errno==EIO
- when the control tty is taken away.
- Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
- if (nread == -1 && errno == EIO)
- return -2; /* Close this terminal. */
-#if defined (AIX) && defined (_BSD)
- /* The kernel sometimes fails to deliver SIGHUP for ptys.
- This looks incorrect, but it isn't, because _BSD causes
- O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
- and that causes a value other than 0 when there is no input. */
- if (nread == 0)
- return -2; /* Close this terminal. */
-#endif
- }
- while (
- /* We used to retry the read if it was interrupted.
- But this does the wrong thing when O_NONBLOCK causes
- an EAGAIN error. Does anybody know of a situation
- where a retry is actually needed? */
-#if 0
- nread < 0 && (errno == EAGAIN || errno == EFAULT
-#ifdef EBADSLT
- || errno == EBADSLT
-#endif
- )
-#else
- 0
+ nread = emacs_read (fileno (tty->input), (char *) cbuf, n_to_read);
+ /* POSIX infers that processes which are not in the session leader's
+ process group won't get SIGHUPs at logout time. BSDI adheres to
+ this part standard and returns -1 from read (0) with errno==EIO
+ when the control tty is taken away.
+ Jeffrey Honig <jch@bsdi.com> says this is generally safe. */
+ if (nread == -1 && errno == EIO)
+ return -2; /* Close this terminal. */
+#if defined AIX && defined _BSD
+ /* The kernel sometimes fails to deliver SIGHUP for ptys.
+ This looks incorrect, but it isn't, because _BSD causes
+ O_NDELAY to be defined in fcntl.h as O_NONBLOCK,
+ and that causes a value other than 0 when there is no input. */
+ if (nread == 0)
+ return -2; /* Close this terminal. */
#endif
- );
#ifndef USABLE_FIONREAD
#if defined (USG) || defined (CYGWIN)
extern Lisp_Object memory_signal_data;
-/* Check quit-flag and quit if it is non-nil. Typing C-g does not
- directly cause a quit; it only sets Vquit_flag. So the program
- needs to call maybe_quit at times when it is safe to quit. Every
- loop that might run for a long time or might not exit ought to call
- maybe_quit at least once, at a safe place. Unless that is
- impossible, of course. But it is very desirable to avoid creating
- loops where maybe_quit is impossible.
-
- If quit-flag is set to `kill-emacs' the SIGINT handler has received
- a request to exit Emacs when it is safe to do.
-
- When not quitting, process any pending signals. */
-
extern void maybe_quit (void);
/* True if ought to quit now. */
#define QUITP (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
+
+/* Heuristic on how many iterations of a tight loop can be safely done
+ before it's time to do a quit. This must be a power of 2. It
+ is nice but not necessary for it to equal USHRT_MAX + 1. */
+
+enum { QUIT_COUNT_HEURISTIC = 1 << 16 };
+
+/* Process a quit rarely, based on a counter COUNT, for efficiency.
+ "Rarely" means once per QUIT_COUNT_HEURISTIC or per USHRT_MAX + 1
+ times, whichever is smaller (somewhat arbitrary, but often faster). */
+
+INLINE void
+rarely_quit (unsigned short int count)
+{
+ if (! (count & (QUIT_COUNT_HEURISTIC - 1)))
+ maybe_quit ();
+}
+
+/* Increment *QUIT_COUNT and rarely quit. */
+
+INLINE void
+incr_rarely_quit (unsigned short int *quit_count)
+{
+ rarely_quit (++*quit_count);
+}
\f
extern Lisp_Object Vascii_downcase_table;
extern Lisp_Object Vascii_canon_table;
extern int emacs_pipe (int[2]);
extern int emacs_close (int);
extern ptrdiff_t emacs_read (int, void *, ptrdiff_t);
+extern ptrdiff_t emacs_read_quit (int, void *, ptrdiff_t);
extern ptrdiff_t emacs_write (int, void const *, ptrdiff_t);
extern ptrdiff_t emacs_write_sig (int, void const *, ptrdiff_t);
+extern ptrdiff_t emacs_write_quit (int, void const *, ptrdiff_t);
extern void emacs_perror (char const *);
extern void unlock_all_files (void);
/* Read the first few bytes from the file, and look for a line
specifying the byte compiler version used. */
- nbytes = emacs_read (fd, buf, sizeof buf);
+ nbytes = emacs_read_quit (fd, buf, sizeof buf);
if (nbytes > 0)
{
/* Skip to the next newline, skipping over the initial `ELC'
*bytepos = lim_byte + next;
return BYTE_TO_CHAR (lim_byte + next);
}
+ if (allow_quit)
+ maybe_quit ();
}
start_byte = lim_byte;
*bytepos = ceiling_byte + prev + 1;
return BYTE_TO_CHAR (ceiling_byte + prev + 1);
}
+ if (allow_quit)
+ maybe_quit ();
}
start_byte = ceiling_byte;
return (n);
}
n++;
+ maybe_quit ();
}
while (n > 0)
{
return (0 - n);
}
n--;
+ maybe_quit ();
}
#ifdef REL_ALLOC
r_alloc_inhibit_buffer_relocation (0);
*bytepos = lim_byte + next;
return BYTE_TO_CHAR (lim_byte + next);
}
+ if (allow_quit)
+ maybe_quit ();
}
start_byte = lim_byte;
find_defun_start (ptrdiff_t pos, ptrdiff_t pos_byte)
{
ptrdiff_t opoint = PT, opoint_byte = PT_BYTE;
+ unsigned short int quit_count = 0;
/* Use previous finding, if it's valid and applies to this inquiry. */
if (current_buffer == find_start_buffer
SETUP_BUFFER_SYNTAX_TABLE ();
while (PT > BEGV)
{
- int c;
-
/* Open-paren at start of line means we may have found our
defun-start. */
- c = FETCH_CHAR_AS_MULTIBYTE (PT_BYTE);
+ int c = FETCH_CHAR_AS_MULTIBYTE (PT_BYTE);
if (SYNTAX (c) == Sopen)
{
SETUP_SYNTAX_TABLE (PT + 1, -1); /* Try again... */
}
/* Move to beg of previous line. */
scan_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -2, 1);
+ incr_rarely_quit (&quit_count);
}
/* Record what we found, for the next try. */
ptrdiff_t nesting = 1; /* Current comment nesting. */
int c;
int syntax = 0;
+ unsigned short int quit_count = 0;
/* FIXME: A }} comment-ender style leads to incorrect behavior
in the case of {{ c }}} because we ignore the last two chars which are
that determines quote parity to the comment-end. */
while (from != stop)
{
+ incr_rarely_quit (&quit_count);
+
ptrdiff_t temp_byte;
int prev_syntax;
bool com2start, com2end, comstart;
defun_start_byte = CHAR_TO_BYTE (defun_start);
}
}
- } while (defun_start < comment_end);
+ incr_rarely_quit (&quit_count);
+ }
+ while (defun_start < comment_end);
from_byte = CHAR_TO_BYTE (from);
UPDATE_SYNTAX_TABLE_FORWARD (from - 1);
COUNT negative means scan backward and stop at word beginning. */
ptrdiff_t
-scan_words (register ptrdiff_t from, register EMACS_INT count)
+scan_words (ptrdiff_t from, EMACS_INT count)
{
- register ptrdiff_t beg = BEGV;
- register ptrdiff_t end = ZV;
- register ptrdiff_t from_byte = CHAR_TO_BYTE (from);
- register enum syntaxcode code;
+ ptrdiff_t beg = BEGV;
+ ptrdiff_t end = ZV;
+ ptrdiff_t from_byte = CHAR_TO_BYTE (from);
+ enum syntaxcode code;
int ch0, ch1;
Lisp_Object func, pos;
- maybe_quit ();
-
SETUP_SYNTAX_TABLE (from, count);
while (count > 0)
{
- while (1)
+ while (true)
{
if (from == end)
return 0;
break;
if (code == Sword)
break;
+ rarely_quit (from);
}
/* Now CH0 is a character which begins a word and FROM is the
position of the next character. */
break;
INC_BOTH (from, from_byte);
ch0 = ch1;
+ rarely_quit (from);
}
}
count--;
}
while (count < 0)
{
- while (1)
+ while (true)
{
if (from == beg)
return 0;
break;
if (code == Sword)
break;
+ rarely_quit (from);
}
/* Now CH1 is a character which ends a word and FROM is the
position of it. */
break;
}
ch1 = ch0;
+ rarely_quit (from);
}
}
count++;
}
fwd_ok:
p += nbytes, pos++, pos_byte += nbytes;
+ rarely_quit (pos);
}
else
- while (1)
+ while (true)
{
if (p >= stop)
{
break;
fwd_unibyte_ok:
p++, pos++, pos_byte++;
+ rarely_quit (pos);
}
}
else
{
if (multibyte)
- while (1)
+ while (true)
{
- unsigned char *prev_p;
-
if (p <= stop)
{
if (p <= endp)
p = GPT_ADDR;
stop = endp;
}
- prev_p = p;
- while (--p >= stop && ! CHAR_HEAD_P (*p));
+ unsigned char *prev_p = p;
+ do
+ p--;
+ while (stop <= p && ! CHAR_HEAD_P (*p));
+
c = STRING_CHAR (p);
if (! NILP (iso_classes) && in_classes (c, iso_classes))
}
back_ok:
pos--, pos_byte -= prev_p - p;
+ rarely_quit (pos);
}
else
- while (1)
+ while (true)
{
if (p <= stop)
{
break;
back_unibyte_ok:
p--, pos--, pos_byte--;
+ rarely_quit (pos);
}
}
if (! fastmap[SYNTAX (c)])
goto done;
p += nbytes, pos++, pos_byte += nbytes;
+ rarely_quit (pos);
}
while (!parse_sexp_lookup_properties
|| pos < gl_state.e_property);
if (multibyte)
{
- while (1)
+ while (true)
{
- unsigned char *prev_p;
-
if (p <= stop)
{
if (p <= endp)
stop = endp;
}
UPDATE_SYNTAX_TABLE_BACKWARD (pos - 1);
- prev_p = p;
- while (--p >= stop && ! CHAR_HEAD_P (*p));
+
+ unsigned char *prev_p = p;
+ do
+ p--;
+ while (stop <= p && ! CHAR_HEAD_P (*p));
+
c = STRING_CHAR (p);
if (! fastmap[SYNTAX (c)])
break;
pos--, pos_byte -= prev_p - p;
+ rarely_quit (pos);
}
}
else
{
- while (1)
+ while (true)
{
if (p <= stop)
{
if (! fastmap[SYNTAX (p[-1])])
break;
p--, pos--, pos_byte--;
+ rarely_quit (pos);
}
}
}
ptrdiff_t *charpos_ptr, ptrdiff_t *bytepos_ptr,
EMACS_INT *incomment_ptr, int *last_syntax_ptr)
{
- register int c, c1;
- register enum syntaxcode code;
- register int syntax, other_syntax;
+ unsigned short int quit_count = 0;
+ int c, c1;
+ enum syntaxcode code;
+ int syntax, other_syntax;
if (nesting <= 0) nesting = -1;
UPDATE_SYNTAX_TABLE_FORWARD (from);
nesting++;
}
+
+ incr_rarely_quit (&quit_count);
}
*charpos_ptr = from;
*bytepos_ptr = from_byte;
ptrdiff_t out_charpos, out_bytepos;
EMACS_INT dummy;
int dummy2;
+ unsigned short int quit_count = 0;
CHECK_NUMBER (count);
count1 = XINT (count);
stop = count1 > 0 ? ZV : BEGV;
- maybe_quit ();
-
from = PT;
from_byte = PT_BYTE;
INC_BOTH (from, from_byte);
UPDATE_SYNTAX_TABLE_FORWARD (from);
}
+ incr_rarely_quit (&quit_count);
}
while (code == Swhitespace || (code == Sendcomment && c == '\n'));
while (count1 < 0)
{
- while (1)
+ while (true)
{
- bool quoted;
- int syntax;
-
if (from <= stop)
{
SET_PT_BOTH (BEGV, BEGV_BYTE);
DEC_BOTH (from, from_byte);
/* char_quoted does UPDATE_SYNTAX_TABLE_BACKWARD (from). */
- quoted = char_quoted (from, from_byte);
+ bool quoted = char_quoted (from, from_byte);
c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
- syntax = SYNTAX_WITH_FLAGS (c);
+ int syntax = SYNTAX_WITH_FLAGS (c);
code = SYNTAX (c);
comstyle = 0;
comnested = SYNTAX_FLAGS_COMMENT_NESTED (syntax);
}
else if (from == stop)
break;
+ incr_rarely_quit (&quit_count);
}
if (fence_found == 0)
{
SET_PT_BOTH (from, from_byte);
return Qnil;
}
+
+ incr_rarely_quit (&quit_count);
}
count1++;
EMACS_INT dummy;
int dummy2;
bool multibyte_symbol_p = sexpflag && multibyte_syntax_as_symbol;
+ unsigned short int quit_count = 0;
if (depth > 0) min_depth = 0;
{
while (from < stop)
{
+ incr_rarely_quit (&quit_count);
bool comstart_first, prefix;
int syntax, other_syntax;
UPDATE_SYNTAX_TABLE_FORWARD (from);
goto done;
}
INC_BOTH (from, from_byte);
+ incr_rarely_quit (&quit_count);
}
goto done;
if (c_code == Scharquote || c_code == Sescape)
INC_BOTH (from, from_byte);
INC_BOTH (from, from_byte);
+ incr_rarely_quit (&quit_count);
}
INC_BOTH (from, from_byte);
if (!depth && sexpflag) goto done;
{
while (from > stop)
{
- int syntax;
+ incr_rarely_quit (&quit_count);
DEC_BOTH (from, from_byte);
UPDATE_SYNTAX_TABLE_BACKWARD (from);
c = FETCH_CHAR_AS_MULTIBYTE (from_byte);
- syntax= SYNTAX_WITH_FLAGS (c);
+ int syntax = SYNTAX_WITH_FLAGS (c);
code = syntax_multibyte (c, multibyte_symbol_p);
if (depth == min_depth)
last_good = from;
default: goto done2;
}
DEC_BOTH (from, from_byte);
+ incr_rarely_quit (&quit_count);
}
goto done2;
if (syntax_multibyte (c, multibyte_symbol_p) == code)
break;
}
+ incr_rarely_quit (&quit_count);
}
if (code == Sstring_fence && !depth && sexpflag) goto done2;
break;
case Sstring:
stringterm = FETCH_CHAR_AS_MULTIBYTE (from_byte);
- while (1)
+ while (true)
{
if (from == stop)
goto lose;
== Sstring))
break;
}
+ incr_rarely_quit (&quit_count);
}
if (!depth && sexpflag) goto done2;
break;
if (pos <= beg)
break;
DEC_BOTH (pos, pos_byte);
+ rarely_quit (pos);
}
SET_PT_BOTH (opoint, opoint_byte);
bool found;
ptrdiff_t out_bytepos, out_charpos;
int temp;
+ unsigned short int quit_count = 0;
prev_from = from;
prev_from_byte = from_byte;
while (from < end)
{
+ incr_rarely_quit (&quit_count);
INC_FROM;
if ((from < end)
goto symdone;
}
INC_FROM;
+ incr_rarely_quit (&quit_count);
}
symdone:
curlevel->prev = curlevel->last;
break;
}
INC_FROM;
+ incr_rarely_quit (&quit_count);
}
}
string_end:
so that another thread running glib won't find them. */
eassert (child > 0);
- while ((pid = waitpid (child, status, options)) < 0)
+ while (true)
{
+ /* Note: the MS-Windows emulation of waitpid calls maybe_quit
+ internally. */
+ if (interruptible)
+ maybe_quit ();
+
+ pid = waitpid (child, status, options);
+ if (0 <= pid)
+ break;
+
/* Check that CHILD is a child process that has not been reaped,
and that STATUS and OPTIONS are valid. Otherwise abort,
as continuing after this internal error could cause Emacs to
become confused and kill innocent-victim processes. */
if (errno != EINTR)
emacs_abort ();
-
- /* Note: the MS-Windows emulation of waitpid calls maybe_quit
- internally. */
- if (interruptible)
- maybe_quit ();
}
/* If successful and status is requested, tell wait_reading_process_output
#define MAX_RW_COUNT (INT_MAX >> 18 << 18)
#endif
-/* Read from FILEDESC to a buffer BUF with size NBYTE, retrying if interrupted.
+/* Read from FD to a buffer BUF with size NBYTE.
+ If interrupted, either quit or retry the read.
+ Process any quits and pending signals immediately if INTERRUPTIBLE.
Return the number of bytes read, which might be less than NBYTE.
- On error, set errno and return -1. */
-ptrdiff_t
-emacs_read (int fildes, void *buf, ptrdiff_t nbyte)
+ On error, set errno to a value other than EINTR, and return -1. */
+static ptrdiff_t
+emacs_nointr_read (int fd, void *buf, ptrdiff_t nbyte, bool interruptible)
{
- ssize_t rtnval;
+ ssize_t result;
/* There is no need to check against MAX_RW_COUNT, since no caller ever
passes a size that large to emacs_read. */
+ do
+ {
+ if (interruptible)
+ maybe_quit ();
+ result = read (fd, buf, nbyte);
+ }
+ while (result < 0 && errno == EINTR);
- while ((rtnval = read (fildes, buf, nbyte)) == -1
- && (errno == EINTR))
- maybe_quit ();
- return (rtnval);
+ return result;
}
-/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if interrupted
- or if a partial write occurs. If interrupted, process pending
- signals if PROCESS SIGNALS. Return the number of bytes written, setting
- errno if this is less than NBYTE. */
+/* Read from FD to a buffer BUF with size NBYTE.
+ If interrupted, retry the read. Return the number of bytes read,
+ which might be less than NBYTE. On error, set errno to a value
+ other than EINTR, and return -1. */
+ptrdiff_t
+emacs_read (int fd, void *buf, ptrdiff_t nbyte)
+{
+ return emacs_nointr_read (fd, buf, nbyte, false);
+}
+
+/* Like emacs_read, but also process quits and pending signals. */
+ptrdiff_t
+emacs_read_quit (int fd, void *buf, ptrdiff_t nbyte)
+{
+ return emacs_nointr_read (fd, buf, nbyte, true);
+}
+
+/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if
+ interrupted or if a partial write occurs. Process any quits
+ immediately if INTERRUPTIBLE is positive, and process any pending
+ signals immediately if INTERRUPTIBLE is nonzero. Return the number
+ of bytes written; if this is less than NBYTE, set errno to a value
+ other than EINTR. */
static ptrdiff_t
-emacs_full_write (int fildes, char const *buf, ptrdiff_t nbyte,
- bool process_signals)
+emacs_full_write (int fd, char const *buf, ptrdiff_t nbyte,
+ int interruptible)
{
ptrdiff_t bytes_written = 0;
while (nbyte > 0)
{
- ssize_t n = write (fildes, buf, min (nbyte, MAX_RW_COUNT));
+ ssize_t n = write (fd, buf, min (nbyte, MAX_RW_COUNT));
if (n < 0)
{
- if (errno == EINTR)
+ if (errno != EINTR)
+ break;
+
+ if (interruptible)
{
- /* I originally used maybe_quit but that might cause files to
- be truncated if you hit C-g in the middle of it. --Stef */
- if (process_signals && pending_signals)
+ if (0 < interruptible)
+ maybe_quit ();
+ if (pending_signals)
process_pending_signals ();
- continue;
}
- else
- break;
}
-
- buf += n;
- nbyte -= n;
- bytes_written += n;
+ else
+ {
+ buf += n;
+ nbyte -= n;
+ bytes_written += n;
+ }
}
return bytes_written;
}
-/* Write to FILEDES from a buffer BUF with size NBYTE, retrying if
- interrupted or if a partial write occurs. Return the number of
- bytes written, setting errno if this is less than NBYTE. */
+/* Write to FD from a buffer BUF with size NBYTE, retrying if
+ interrupted or if a partial write occurs. Do not process quits or
+ pending signals. Return the number of bytes written, setting errno
+ if this is less than NBYTE. */
+ptrdiff_t
+emacs_write (int fd, void const *buf, ptrdiff_t nbyte)
+{
+ return emacs_full_write (fd, buf, nbyte, 0);
+}
+
+/* Like emacs_write, but also process pending signals. */
ptrdiff_t
-emacs_write (int fildes, void const *buf, ptrdiff_t nbyte)
+emacs_write_sig (int fd, void const *buf, ptrdiff_t nbyte)
{
- return emacs_full_write (fildes, buf, nbyte, 0);
+ return emacs_full_write (fd, buf, nbyte, -1);
}
-/* Like emacs_write, but also process pending signals if interrupted. */
+/* Like emacs_write, but also process quits and pending signals. */
ptrdiff_t
-emacs_write_sig (int fildes, void const *buf, ptrdiff_t nbyte)
+emacs_write_quit (int fd, void const *buf, ptrdiff_t nbyte)
{
- return emacs_full_write (fildes, buf, nbyte, 1);
+ return emacs_full_write (fd, buf, nbyte, 1);
}
/* Write a diagnostic to standard error that contains MESSAGE and a
string derived from errno. Preserve errno. Do not buffer stderr.
- Do not process pending signals if interrupted. */
+ Do not process quits or pending signals if interrupted. */
void
emacs_perror (char const *message)
{
else
{
record_unwind_protect_int (close_file_unwind, fd);
- nread = emacs_read (fd, procbuf, sizeof procbuf - 1);
+ nread = emacs_read_quit (fd, procbuf, sizeof procbuf - 1);
}
if (0 < nread)
{
/* Leave room even if every byte needs escaping below. */
readsize = (cmdline_size >> 1) - nread;
- nread_incr = emacs_read (fd, cmdline + nread, readsize);
+ nread_incr = emacs_read_quit (fd, cmdline + nread, readsize);
nread += max (0, nread_incr);
}
while (nread_incr == readsize);
else
{
record_unwind_protect_int (close_file_unwind, fd);
- nread = emacs_read (fd, &pinfo, sizeof pinfo);
+ nread = emacs_read_quit (fd, &pinfo, sizeof pinfo);
}
if (nread == sizeof pinfo)