#include "coding.h"
#include "frame.h"
#include "window.h"
+#include "blockinput.h"
#ifdef STDC_HEADERS
#include <float.h>
extern char **environ;
#endif
+#define TM_YEAR_BASE 1900
+
+/* Nonzero if TM_YEAR is a struct tm's tm_year value that causes
+ asctime to have well-defined behavior. */
+#ifndef TM_YEAR_IN_ASCTIME_RANGE
+# define TM_YEAR_IN_ASCTIME_RANGE(tm_year) \
+ (1000 - TM_YEAR_BASE <= (tm_year) && (tm_year) <= 9999 - TM_YEAR_BASE)
+#endif
+
extern size_t emacs_strftimeu P_ ((char *, size_t, const char *,
const struct tm *, int));
static int tm_diff P_ ((struct tm *, struct tm *));
if (!NILP (Vtransient_mark_mode)
&& NILP (Vmark_even_if_inactive)
&& NILP (current_buffer->mark_active))
- Fsignal (Qmark_inactive, Qnil);
+ xsignal0 (Qmark_inactive);
m = Fmarker_position (current_buffer->mark);
if (NILP (m))
}
/* Find the field surrounding POS in *BEG and *END. If POS is nil,
- the value of point is used instead. If BEG or END null,
+ the value of point is used instead. If BEG or END is null,
means don't store the beginning or end of the field.
BEG_LIMIT and END_LIMIT serve to limit the ranged of the returned
int orig_point = 0;
int fwd;
Lisp_Object prev_old, prev_new;
-
+
if (NILP (new_pos))
/* Use the current point, and afterwards, set it. */
{
prev_old = make_number (XFASTINT (old_pos) - 1);
prev_new = make_number (XFASTINT (new_pos) - 1);
-
+
if (NILP (Vinhibit_field_text_motion)
&& !EQ (new_pos, old_pos)
&& (!NILP (Fget_char_property (new_pos, Qfield, Qnil))
Lisp_Object n;
{
int orig, orig_byte, end;
+ int count = SPECPDL_INDEX ();
+ specbind (Qinhibit_point_motion_hooks, Qt);
if (NILP (n))
XSETFASTINT (n, 1);
SET_PT_BOTH (orig, orig_byte);
+ unbind_to (count, Qnil);
+
/* Return END constrained to the current input field. */
return Fconstrain_to_field (make_number (end), make_number (orig),
XINT (n) != 1 ? Qt : Qnil,
return Vuser_login_name;
CHECK_NUMBER (uid);
+ BLOCK_INPUT;
pw = (struct passwd *) getpwuid (XINT (uid));
+ UNBLOCK_INPUT;
return (pw ? build_string (pw->pw_name) : Qnil);
}
if (NILP (uid))
return Vuser_full_name;
else if (NUMBERP (uid))
- pw = (struct passwd *) getpwuid ((uid_t) XFLOATINT (uid));
+ {
+ BLOCK_INPUT;
+ pw = (struct passwd *) getpwuid ((uid_t) XFLOATINT (uid));
+ UNBLOCK_INPUT;
+ }
else if (STRINGP (uid))
- pw = (struct passwd *) getpwnam (SDATA (uid));
+ {
+ BLOCK_INPUT;
+ pw = (struct passwd *) getpwnam (SDATA (uid));
+ UNBLOCK_INPUT;
+ }
else
error ("Invalid UID specification");
}
DEFUN ("system-name", Fsystem_name, Ssystem_name, 0, 0, 0,
- doc: /* Return the name of the machine you are running on, as a string. */)
+ doc: /* Return the host name of the machine you are running on, as a string. */)
()
{
return Vsystem_name;
()
{
EMACS_TIME t;
- Lisp_Object result[3];
EMACS_GET_TIME (t);
- XSETINT (result[0], (EMACS_SECS (t) >> 16) & 0xffff);
- XSETINT (result[1], (EMACS_SECS (t) >> 0) & 0xffff);
- XSETINT (result[2], EMACS_USECS (t));
-
- return Flist (3, result);
+ return list3 (make_number ((EMACS_SECS (t) >> 16) & 0xffff),
+ make_number ((EMACS_SECS (t) >> 0) & 0xffff),
+ make_number (EMACS_USECS (t)));
}
DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
{
#ifdef HAVE_GETRUSAGE
struct rusage usage;
- Lisp_Object result[3];
int secs, usecs;
if (getrusage (RUSAGE_SELF, &usage) < 0)
/* This shouldn't happen. What action is appropriate? */
- Fsignal (Qerror, Qnil);
+ xsignal0 (Qerror);
/* Sum up user time and system time. */
secs = usage.ru_utime.tv_sec + usage.ru_stime.tv_sec;
secs++;
}
- XSETINT (result[0], (secs >> 16) & 0xffff);
- XSETINT (result[1], (secs >> 0) & 0xffff);
- XSETINT (result[2], usecs);
-
- return Flist (3, result);
+ return list3 (make_number ((secs >> 16) & 0xffff),
+ make_number ((secs >> 0) & 0xffff),
+ make_number (usecs));
#else
return Fcurrent_time ();
#endif
SBYTES (format_string),
tm, ut);
if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
- return code_convert_string_norecord (make_string (buf, result),
+ return code_convert_string_norecord (make_unibyte_string (buf, result),
Vlocale_coding_system, 0);
/* If buffer was too small, make it bigger and try again. */
XSETFASTINT (list_args[2], decoded_time->tm_hour);
XSETFASTINT (list_args[3], decoded_time->tm_mday);
XSETFASTINT (list_args[4], decoded_time->tm_mon + 1);
- XSETINT (list_args[5], decoded_time->tm_year + 1900);
+ /* On 64-bit machines an int is narrower than EMACS_INT, thus the
+ cast below avoids overflow in int arithmetics. */
+ XSETINT (list_args[5], TM_YEAR_BASE + (EMACS_INT) decoded_time->tm_year);
XSETFASTINT (list_args[6], decoded_time->tm_wday);
list_args[7] = (decoded_time->tm_isdst)? Qt : Qnil;
tm.tm_hour = XINT (args[2]);
tm.tm_mday = XINT (args[3]);
tm.tm_mon = XINT (args[4]) - 1;
- tm.tm_year = XINT (args[5]) - 1900;
+ tm.tm_year = XINT (args[5]) - TM_YEAR_BASE;
tm.tm_isdst = -1;
if (CONSP (zone))
DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
doc: /* Return the current time, as a human-readable string.
Programs can use this function to decode a time,
-since the number of columns in each field is fixed.
+since the number of columns in each field is fixed
+if the year is in the range 1000-9999.
The format is `Sun Sep 16 01:03:52 1973'.
However, see also the functions `decode-time' and `format-time-string'
which provide a much more powerful and general facility.
Lisp_Object specified_time;
{
time_t value;
- char buf[30];
+ struct tm *tm;
register char *tem;
if (! lisp_time_argument (specified_time, &value, NULL))
- value = -1;
- tem = (char *) ctime (&value);
+ error ("Invalid time specification");
- strncpy (buf, tem, 24);
- buf[24] = 0;
+ /* Convert to a string, checking for out-of-range time stamps.
+ Don't use 'ctime', as that might dump core if VALUE is out of
+ range. */
+ tm = localtime (&value);
+ if (! (tm && TM_YEAR_IN_ASCTIME_RANGE (tm->tm_year) && (tem = asctime (tm))))
+ error ("Specified time is not representable");
- return build_string (buf);
-}
+ /* Remove the trailing newline. */
+ tem[strlen (tem) - 1] = '\0';
-#define TM_YEAR_BASE 1900
+ return build_string (tem);
+}
/* Yield A - B, measured in seconds.
This function is copied from the GNU C Library. */
for (argnum = 0; argnum < nargs; argnum++)
{
val = args[argnum];
- retry:
if (INTEGERP (val))
{
unsigned char str[MAX_MULTIBYTE_LENGTH];
inherit);
}
else
- {
- val = wrong_type_argument (Qchar_or_string_p, val);
- goto retry;
- }
+ wrong_type_argument (Qchar_or_string_p, val);
}
}
Lisp_Object start, end, fromchar, tochar, noundo;
{
register int pos, pos_byte, stop, i, len, end_byte;
+ /* Keep track of the first change in the buffer:
+ if 0 we haven't found it yet.
+ if < 0 we've found it and we've run the before-change-function.
+ if > 0 we've actually performed it and the value is its position. */
int changed = 0;
unsigned char fromstr[MAX_MULTIBYTE_LENGTH], tostr[MAX_MULTIBYTE_LENGTH];
unsigned char *p;
int last_changed = 0;
int multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
+ restart:
+
validate_region (&start, &end);
CHECK_NUMBER (fromchar);
CHECK_NUMBER (tochar);
That's faster than getting rid of things,
and it prevents even the entry for a first change.
Also inhibit locking the file. */
- if (!NILP (noundo))
+ if (!changed && !NILP (noundo))
{
record_unwind_protect (subst_char_in_region_unwind,
current_buffer->undo_list);
&& (len == 2 || (p[2] == fromstr[2]
&& (len == 3 || p[3] == fromstr[3]))))))
{
- if (! changed)
+ if (changed < 0)
+ /* We've already seen this and run the before-change-function;
+ this time we only need to record the actual position. */
+ changed = pos;
+ else if (!changed)
{
- changed = pos;
- modify_region (current_buffer, changed, XINT (end));
+ changed = -1;
+ modify_region (current_buffer, pos, XINT (end), 0);
if (! NILP (noundo))
{
if (MODIFF - 1 == current_buffer->auto_save_modified)
current_buffer->auto_save_modified++;
}
+
+ /* The before-change-function may have moved the gap
+ or even modified the buffer so we should start over. */
+ goto restart;
}
/* Take care of the case where the new character
pos++;
}
- if (changed)
+ if (changed > 0)
{
signal_after_change (changed,
last_changed - changed, last_changed - changed);
pos = XINT (start);
pos_byte = CHAR_TO_BYTE (pos);
end_pos = XINT (end);
- modify_region (current_buffer, pos, XINT (end));
+ modify_region (current_buffer, pos, XINT (end), 0);
cnt = 0;
for (; pos < end_pos; )
static int message_length;
DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
- doc: /* Print a one-line message at the bottom of the screen.
+ doc: /* Display a message at the bottom of the screen.
The message also goes into the `*Messages*' buffer.
\(In keyboard macros, that's all it does.)
+Return the message.
The first argument is a format control string, and the rest are data
to be formatted under control of the string. See `format' for details.
+Note: Use (message "%s" VALUE) to print the value of expressions and
+variables to avoid accidentally interpreting `%' as format specifiers.
+
If the first argument is nil or the empty string, the function clears
any existing message; this lets the minibuffer contents show. See
also `current-message'.
this_format[format - this_format_start] = 0;
if (INTEGERP (args[n]))
- sprintf (p, this_format, XINT (args[n]));
+ {
+ if (format[-1] == 'd')
+ sprintf (p, this_format, XINT (args[n]));
+ /* Don't sign-extend for octal or hex printing. */
+ else
+ sprintf (p, this_format, XUINT (args[n]));
+ }
else
sprintf (p, this_format, XFLOAT_DATA (args[n]));
/* Likewise adjust the property end position. */
pos = XINT (XCAR (XCDR (item)));
- for (; bytepos < pos; bytepos++)
+ for (; position < pos; bytepos++)
{
if (! discarded[bytepos])
position++, translated++;
if (end1 == start2) /* adjacent regions */
{
- modify_region (current_buffer, start1, end2);
+ modify_region (current_buffer, start1, end2, 0);
record_change (start1, len1 + len2);
tmp_interval1 = copy_intervals (cur_intv, start1, len1);
{
USE_SAFE_ALLOCA;
- modify_region (current_buffer, start1, end1);
- modify_region (current_buffer, start2, end2);
+ modify_region (current_buffer, start1, end1, 0);
+ modify_region (current_buffer, start2, end2, 0);
record_change (start1, len1);
record_change (start2, len2);
tmp_interval1 = copy_intervals (cur_intv, start1, len1);
{
USE_SAFE_ALLOCA;
- modify_region (current_buffer, start1, end2);
+ modify_region (current_buffer, start1, end2, 0);
record_change (start1, (end2 - start1));
tmp_interval1 = copy_intervals (cur_intv, start1, len1);
tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
USE_SAFE_ALLOCA;
record_change (start1, (end2 - start1));
- modify_region (current_buffer, start1, end2);
+ modify_region (current_buffer, start1, end2, 0);
tmp_interval1 = copy_intervals (cur_intv, start1, len1);
tmp_interval_mid = copy_intervals (cur_intv, end1, len_mid);
Vbuffer_access_fontified_property = Qnil;
DEFVAR_LISP ("system-name", &Vsystem_name,
- doc: /* The name of the machine Emacs is running on. */);
+ doc: /* The host name of the machine Emacs is running on. */);
DEFVAR_LISP ("user-full-name", &Vuser_full_name,
doc: /* The full name of the user logged in. */);