#endif
static void time_overflow (void) NO_RETURN;
+static Lisp_Object format_time_string (char const *, ptrdiff_t, Lisp_Object,
+ int, time_t *, struct tm **);
static int tm_diff (struct tm *, struct tm *);
static void update_buffer_properties (EMACS_INT, EMACS_INT);
/* If the user name claimed in the environment vars differs from
the real uid, use the claimed name to find the full name. */
tem = Fstring_equal (Vuser_login_name, Vuser_real_login_name);
- Vuser_full_name = Fuser_full_name (NILP (tem)? make_number (geteuid())
+ Vuser_full_name = Fuser_full_name (NILP (tem)? make_number (geteuid ())
: Vuser_login_name);
p = getenv ("NAME");
}
DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0,
- doc: /* Convert arg STRING to a character, the first character of that string.
-A multibyte character is handled correctly. */)
+ doc: /* Return the first character in STRING. */)
(register Lisp_Object string)
{
register Lisp_Object val;
%EX is a locale's alternative version of %X;
%OX is like %X, but uses the locale's number symbols.
-For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". */)
+For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".
+
+usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */)
(Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
{
- time_t value;
- int size;
- int usec;
- int ns;
+ time_t t;
struct tm *tm;
- int ut = ! NILP (universal);
CHECK_STRING (format_string);
+ format_string = code_convert_string_norecord (format_string,
+ Vlocale_coding_system, 1);
+ return format_time_string (SSDATA (format_string), SBYTES (format_string),
+ timeval, ! NILP (universal), &t, &tm);
+}
+
+static Lisp_Object
+format_time_string (char const *format, ptrdiff_t formatlen,
+ Lisp_Object timeval, int ut, time_t *tval, struct tm **tmp)
+{
+ ptrdiff_t size;
+ int usec;
+ int ns;
+ struct tm *tm;
- if (! (lisp_time_argument (timeval, &value, &usec)
+ if (! (lisp_time_argument (timeval, tval, &usec)
&& 0 <= usec && usec < 1000000))
error ("Invalid time specification");
ns = usec * 1000;
- format_string = code_convert_string_norecord (format_string,
- Vlocale_coding_system, 1);
-
/* This is probably enough. */
- size = SBYTES (format_string) * 6 + 50;
+ size = formatlen;
+ if (size <= (STRING_BYTES_BOUND - 50) / 6)
+ size = size * 6 + 50;
BLOCK_INPUT;
- tm = ut ? gmtime (&value) : localtime (&value);
+ tm = ut ? gmtime (tval) : localtime (tval);
UNBLOCK_INPUT;
if (! tm)
time_overflow ();
+ *tmp = tm;
synchronize_system_time_locale ();
while (1)
{
char *buf = (char *) alloca (size + 1);
- int result;
+ size_t result;
buf[0] = '\1';
BLOCK_INPUT;
- result = emacs_nmemftime (buf, size, SSDATA (format_string),
- SBYTES (format_string),
- tm, ut, ns);
+ result = emacs_nmemftime (buf, size, format, formatlen, tm, ut, ns);
UNBLOCK_INPUT;
if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
return code_convert_string_norecord (make_unibyte_string (buf, result),
/* If buffer was too small, make it bigger and try again. */
BLOCK_INPUT;
- result = emacs_nmemftime (NULL, (size_t) -1,
- SSDATA (format_string),
- SBYTES (format_string),
+ result = emacs_nmemftime (NULL, (size_t) -1, format, formatlen,
tm, ut, ns);
UNBLOCK_INPUT;
+ if (STRING_BYTES_BOUND <= result)
+ string_overflow ();
size = result + 1;
}
}
{
time_t value;
struct tm *t;
- struct tm gmt;
-
- if (!lisp_time_argument (specified_time, &value, NULL))
- t = NULL;
- else
- {
- BLOCK_INPUT;
- t = gmtime (&value);
- if (t)
- {
- gmt = *t;
- t = localtime (&value);
- }
- UNBLOCK_INPUT;
- }
+ struct tm localtm;
+ struct tm *localt;
+ Lisp_Object zone_offset, zone_name;
+
+ zone_offset = Qnil;
+ zone_name = format_time_string ("%Z", sizeof "%Z" - 1, specified_time,
+ 0, &value, &localt);
+ localtm = *localt;
+ BLOCK_INPUT;
+ t = gmtime (&value);
+ UNBLOCK_INPUT;
if (t)
{
- int offset = tm_diff (t, &gmt);
- char *s = 0;
- char buf[6];
-
-#ifdef HAVE_TM_ZONE
- if (t->tm_zone)
- s = (char *)t->tm_zone;
-#else /* not HAVE_TM_ZONE */
-#ifdef HAVE_TZNAME
- if (t->tm_isdst == 0 || t->tm_isdst == 1)
- s = tzname[t->tm_isdst];
-#endif
-#endif /* not HAVE_TM_ZONE */
-
- if (!s)
+ int offset = tm_diff (&localtm, t);
+ zone_offset = make_number (offset);
+ if (SCHARS (zone_name) == 0)
{
/* No local time zone name is available; use "+-NNNN" instead. */
- int am = (offset < 0 ? -offset : offset) / 60;
+ int m = offset / 60;
+ int am = offset < 0 ? - m : m;
+ char buf[sizeof "+00" + INT_STRLEN_BOUND (int)];
sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
- s = buf;
+ zone_name = build_string (buf);
}
-
- return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
}
- else
- return Fmake_list (make_number (2), Qnil);
+
+ return list2 (zone_offset, zone_name);
}
/* This holds the value of `environ' produced by the previous
DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
doc: /* Set the local time zone using TZ, a string specifying a time zone rule.
If TZ is nil, use implementation-defined default time zone information.
-If TZ is t, use Universal Time. */)
+If TZ is t, use Universal Time.
+
+Instead of calling this function, you typically want (setenv "TZ" TZ).
+That changes both the environment of the Emacs process and the
+variable `process-environment', whereas `set-time-zone-rule' affects
+only the former. */)
(Lisp_Object tz)
{
const char *tzstring;
}
set_time_zone_rule (tzstring);
- free (environbuf);
+ xfree (environbuf);
environbuf = environ;
return Qnil;
void
set_time_zone_rule (const char *tzstring)
{
- int envptrs;
+ ptrdiff_t envptrs;
char **from, **to, **newenv;
/* Make the ENVIRON vector longer with room for TZSTRING. */
}
DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
- doc: /* Delete the text between point and mark.
-
-When called from a program, expects two arguments,
-positions (integers or markers) specifying the stretch to be deleted. */)
+ doc: /* Delete the text between START and END.
+If called interactively, delete the region between point and mark.
+This command deletes buffer text without modifying the kill ring. */)
(Lisp_Object start, Lisp_Object end)
{
validate_region (&start, &end);
end = buildmark (ZV, ZV_BYTE);
/* END must move forward if text is inserted at its exact location. */
- XMARKER(end)->insertion_type = 1;
+ XMARKER (end)->insertion_type = 1;
return Fcons (beg, end);
}
static char *message_text;
/* Allocated length of that buffer. */
-static int message_length;
+static ptrdiff_t message_length;
DEFUN ("message", Fmessage, Smessage, 1, MANY, 0,
doc: /* Display a message at the bottom of the screen.
}
if (SBYTES (val) > message_length)
{
+ message_text = (char *) xrealloc (message_text, SBYTES (val));
message_length = SBYTES (val);
- message_text = (char *)xrealloc (message_text, message_length);
}
memcpy (message_text, SDATA (val), SBYTES (val));
message2 (message_text, SBYTES (val),
RETURN_UNGCPRO (string);
}
-/* pWIDE is a conversion for printing large decimal integers (possibly with a
- trailing "d" that is ignored). pWIDElen is its length. signed_wide and
- unsigned_wide are signed and unsigned types for printing them. Use widest
- integers if available so that more floating point values can be converted. */
-#ifdef PRIdMAX
-# define pWIDE PRIdMAX
-enum { pWIDElen = sizeof PRIdMAX - 2 }; /* Don't count trailing "d". */
-typedef intmax_t signed_wide;
-typedef uintmax_t unsigned_wide;
-#else
-# define pWIDE pI
-enum { pWIDElen = sizeof pI - 1 };
-typedef EMACS_INT signed_wide;
-typedef EMACS_UINT unsigned_wide;
-#endif
-
DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
doc: /* Format a string out of a format-string and arguments.
The first argument is a format control string.
printed representation. The padding, if any, normally goes on the
left, but it goes on the right if the - flag is present. The padding
character is normally a space, but it is 0 if the 0 flag is present.
-The - flag takes precedence over the 0 flag.
+The 0 flag is ignored if the - flag is present, or the format sequence
+is something other than %d, %e, %f, and %g.
For %e, %f, and %g sequences, the number after the "." in the
precision specifier says how many decimal places to show; if zero, the
: -1)),
/* Maximum number of bytes generated by any format, if
- precision is no more than DBL_USEFUL_PRECISION_MAX.
+ precision is no more than USEFUL_PRECISION_MAX.
On all practical hosts, %f is the worst case. */
SPRINTF_BUFSIZE =
- sizeof "-." + (DBL_MAX_10_EXP + 1) + USEFUL_PRECISION_MAX
+ sizeof "-." + (DBL_MAX_10_EXP + 1) + USEFUL_PRECISION_MAX,
+
+ /* Length of pM (that is, of pMd without the
+ trailing "d"). */
+ pMlen = sizeof pMd - 2
};
verify (0 < USEFUL_PRECISION_MAX);
/* Copy of conversion specification, modified somewhat.
At most three flags F can be specified at once. */
- char convspec[sizeof "%FFF.*d" + pWIDElen];
+ char convspec[sizeof "%FFF.*d" + pMlen];
/* Avoid undefined behavior in underlying sprintf. */
if (conversion == 'd' || conversion == 'i')
/* Create the copy of the conversion specification, with
any width and precision removed, with ".*" inserted,
- and with pWIDE inserted for integer formats. */
+ and with pM inserted for integer formats. */
{
char *f = convspec;
*f++ = '%';
|| conversion == 'o' || conversion == 'x'
|| conversion == 'X')
{
- memcpy (f, pWIDE, pWIDElen);
- f += pWIDElen;
+ memcpy (f, pMd, pMlen);
+ f += pMlen;
zero_flag &= ~ precision_given;
}
*f++ = conversion;
/* For float, maybe we should use "%1.0f"
instead so it also works for values outside
the integer range. */
- signed_wide x;
+ printmax_t x;
if (INTEGERP (args[n]))
x = XINT (args[n]);
else
double d = XFLOAT_DATA (args[n]);
if (d < 0)
{
- x = TYPE_MINIMUM (signed_wide);
+ x = TYPE_MINIMUM (printmax_t);
if (x < d)
x = d;
}
else
{
- x = TYPE_MAXIMUM (signed_wide);
+ x = TYPE_MAXIMUM (printmax_t);
if (d < x)
x = d;
}
else
{
/* Don't sign-extend for octal or hex printing. */
- unsigned_wide x;
+ uprintmax_t x;
if (INTEGERP (args[n]))
x = XUINT (args[n]);
else
x = 0;
else
{
- x = TYPE_MAXIMUM (unsigned_wide);
+ x = TYPE_MAXIMUM (uprintmax_t);
if (d < x)
x = d;
}
format++;
while (! CHAR_HEAD_P (*format));
- convbytes = format - format0;
- memset (&discarded[format0 + 1 - format_start], 2, convbytes - 1);
+ convbytes = format - src;
+ memset (&discarded[src + 1 - format_start], 2, convbytes - 1);
}
else
{
character. CONVBYTES says how much room is needed. Allocate
enough room (and then some) and do it again. */
{
- EMACS_INT used = p - buf;
+ ptrdiff_t used = p - buf;
if (max_bufsize - used < convbytes)
string_overflow ();
environbuf = 0;
initial_tz = 0;
- Qbuffer_access_fontify_functions
- = intern_c_string ("buffer-access-fontify-functions");
- staticpro (&Qbuffer_access_fontify_functions);
+ DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions");
DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
doc: /* Non-nil means text motion commands don't notice fields. */);
defsubr (&Sregion_beginning);
defsubr (&Sregion_end);
- staticpro (&Qfield);
- Qfield = intern_c_string ("field");
- staticpro (&Qboundary);
- Qboundary = intern_c_string ("boundary");
+ DEFSYM (Qfield, "field");
+ DEFSYM (Qboundary, "boundary");
defsubr (&Sfield_beginning);
defsubr (&Sfield_end);
defsubr (&Sfield_string);