#include <time.h>
#include <setjmp.h>
+#include <intprops.h>
+
#include "lisp.h"
#include "commands.h"
#include "character.h"
static Lisp_Object Qwidget_type;
static Lisp_Object Qcodeset, Qdays, Qmonths, Qpaper;
+static Lisp_Object Qmd5, Qsha1, Qsha224, Qsha256, Qsha384, Qsha512;
+
static int internal_equal (Lisp_Object , Lisp_Object, int, int);
#ifndef HAVE_UNISTD_H
uintmax_t lolen = 1;
if (! CONSP (list))
- return 0;
+ return make_number (0);
/* halftail is used to detect circular lists. */
for (tail = halftail = list; ; )
if (BOOL_VECTOR_P (arg))
{
Lisp_Object val;
- int size_in_chars
+ ptrdiff_t size_in_chars
= ((XBOOL_VECTOR (arg)->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
/ BOOL_VECTOR_BITS_PER_CHAR);
}
result_len += len;
- if (result_len < 0)
- error ("String overflow");
+ if (STRING_BYTES_BOUND < result_len)
+ string_overflow ();
}
if (! some_multibyte)
(Lisp_Object array, Lisp_Object item)
{
register EMACS_INT size, idx;
- int charval;
if (VECTORP (array))
{
else if (STRINGP (array))
{
register unsigned char *p = SDATA (array);
- CHECK_NUMBER (item);
- charval = XINT (item);
+ int charval;
+ CHECK_CHARACTER (item);
+ charval = XFASTINT (item);
size = SCHARS (array);
if (STRING_MULTIBYTE (array))
{
unsigned char str[MAX_MULTIBYTE_LENGTH];
int len = CHAR_STRING (charval, str);
EMACS_INT size_byte = SBYTES (array);
- unsigned char *p1 = p, *endp = p + size_byte;
- int i;
- if (size != size_byte)
- while (p1 < endp)
- {
- int this_len = BYTES_BY_CHAR_HEAD (*p1);
- if (len != this_len)
- error ("Attempt to change byte length of a string");
- p1 += this_len;
- }
- for (i = 0; i < size_byte; i++)
- *p++ = str[i % len];
+ if (INT_MULTIPLY_OVERFLOW (SCHARS (array), len)
+ || SCHARS (array) * len != size_byte)
+ error ("Attempt to change byte length of a string");
+ for (idx = 0; idx < size_byte; idx++)
+ *p++ = str[idx % len];
}
else
for (idx = 0; idx < size; idx++)
else if (BOOL_VECTOR_P (array))
{
register unsigned char *p = XBOOL_VECTOR (array)->data;
- int size_in_chars
- = ((XBOOL_VECTOR (array)->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
+ EMACS_INT size_in_chars;
+ size = XBOOL_VECTOR (array)->size;
+ size_in_chars
+ = ((size + BOOL_VECTOR_BITS_PER_CHAR - 1)
/ BOOL_VECTOR_BITS_PER_CHAR);
- charval = (! NILP (item) ? -1 : 0);
- for (idx = 0; idx < size_in_chars - 1; idx++)
- p[idx] = charval;
- if (idx < size_in_chars)
+ if (size_in_chars)
{
- /* Mask out bits beyond the vector size. */
- if (XBOOL_VECTOR (array)->size % BOOL_VECTOR_BITS_PER_CHAR)
- charval &= (1 << (XBOOL_VECTOR (array)->size % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
- p[idx] = charval;
+ memset (p, ! NILP (item) ? -1 : 0, size_in_chars);
+
+ /* Clear any extraneous bits in the last byte. */
+ p[size_in_chars - 1] &= (1 << (size % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
}
}
else
{
for (i = 0; i < leni; i++)
{
- int byte;
+ unsigned char byte;
byte = XBOOL_VECTOR (seq)->data[i / BOOL_VECTOR_BITS_PER_CHAR];
dummy = (byte & (1 << (i % BOOL_VECTOR_BITS_PER_CHAR))) ? Qt : Qnil;
dummy = call1 (fn, dummy);
while (loads-- > 0)
{
- Lisp_Object load = (NILP (use_floats) ?
- make_number ((int) (100.0 * load_ave[loads]))
+ Lisp_Object load = (NILP (use_floats)
+ ? make_number (100.0 * load_ave[loads])
: make_float (load_ave[loads]));
ret = Fcons (load, ret);
}
If FILENAME is omitted, the printname of FEATURE is used as the file name,
and `load' will try to load this name appended with the suffix `.elc' or
`.el', in that order. The name without appended suffix will not be used.
+If your system supports it, `.elc.gz' and `.el.gz' files will also be
+considered. See `get-load-suffixes' for the complete list of suffixes.
If the optional third argument NOERROR is non-nil,
then return nil if the file is not found instead of signaling an error.
Normally the return value is FEATURE.
\f
/************************************************************************
- MD5 and SHA1
+ MD5, SHA-1, and SHA-2
************************************************************************/
#include "md5.h"
#include "sha1.h"
+#include "sha256.h"
+#include "sha512.h"
-/* Convert a possibly-signed character to an unsigned character. This is
- a bit safer than casting to unsigned char, since it catches some type
- errors that the cast doesn't. */
-static inline unsigned char to_uchar (char ch) { return ch; }
-
-/* TYPE: 0 for md5, 1 for sha1. */
+/* ALGORITHM is a symbol: md5, sha1, sha224 and so on. */
static Lisp_Object
-crypto_hash_function (int type, Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror, Lisp_Object binary)
+secure_hash (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror, Lisp_Object binary)
{
int i;
EMACS_INT size;
register EMACS_INT b, e;
register struct buffer *bp;
EMACS_INT temp;
- Lisp_Object res=Qnil;
+ int digest_size;
+ void *(*hash_func) (const char *, size_t, void *);
+ Lisp_Object digest;
+
+ CHECK_SYMBOL (algorithm);
if (STRINGP (object))
{
object = code_convert_string (object, coding_system, Qnil, 1, 0, 0);
}
- switch (type)
+ if (EQ (algorithm, Qmd5))
{
- case 0: /* MD5 */
- {
- char digest[16];
- md5_buffer (SSDATA (object) + start_byte,
- SBYTES (object) - (size_byte - end_byte),
- digest);
+ digest_size = MD5_DIGEST_SIZE;
+ hash_func = md5_buffer;
+ }
+ else if (EQ (algorithm, Qsha1))
+ {
+ digest_size = SHA1_DIGEST_SIZE;
+ hash_func = sha1_buffer;
+ }
+ else if (EQ (algorithm, Qsha224))
+ {
+ digest_size = SHA224_DIGEST_SIZE;
+ hash_func = sha224_buffer;
+ }
+ else if (EQ (algorithm, Qsha256))
+ {
+ digest_size = SHA256_DIGEST_SIZE;
+ hash_func = sha256_buffer;
+ }
+ else if (EQ (algorithm, Qsha384))
+ {
+ digest_size = SHA384_DIGEST_SIZE;
+ hash_func = sha384_buffer;
+ }
+ else if (EQ (algorithm, Qsha512))
+ {
+ digest_size = SHA512_DIGEST_SIZE;
+ hash_func = sha512_buffer;
+ }
+ else
+ error ("Invalid algorithm arg: %s", SDATA (Fsymbol_name (algorithm)));
- if (NILP (binary))
- {
- char value[33];
- for (i = 0; i < 16; i++)
- sprintf (&value[2 * i], "%02x", to_uchar (digest[i]));
- res = make_string (value, 32);
- }
- else
- res = make_string (digest, 16);
- break;
- }
+ /* allocate 2 x digest_size so that it can be re-used to hold the
+ hexified value */
+ digest = make_uninit_string (digest_size * 2);
- case 1: /* SHA1 */
- {
- char digest[20];
- sha1_buffer (SSDATA (object) + start_byte,
- SBYTES (object) - (size_byte - end_byte),
- digest);
- if (NILP (binary))
- {
- char value[41];
- for (i = 0; i < 20; i++)
- sprintf (&value[2 * i], "%02x", to_uchar (digest[i]));
- res = make_string (value, 40);
- }
- else
- res = make_string (digest, 20);
- break;
- }
- }
+ hash_func (SSDATA (object) + start_byte,
+ SBYTES (object) - (size_byte - end_byte),
+ SSDATA (digest));
- return res;
+ if (NILP (binary))
+ {
+ unsigned char *p = SDATA (digest);
+ for (i = digest_size - 1; i >= 0; i--)
+ {
+ static char const hexdigit[16] = "0123456789abcdef";
+ int p_i = p[i];
+ p[2 * i] = hexdigit[p_i >> 4];
+ p[2 * i + 1] = hexdigit[p_i & 0xf];
+ }
+ return digest;
+ }
+ else
+ return make_unibyte_string (SSDATA (digest), digest_size);
}
DEFUN ("md5", Fmd5, Smd5, 1, 5, 0,
guesswork fails. Normally, an error is signaled in such case. */)
(Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp_Object coding_system, Lisp_Object noerror)
{
- return crypto_hash_function (0, object, start, end, coding_system, noerror, Qnil);
+ return secure_hash (Qmd5, object, start, end, coding_system, noerror, Qnil);
}
-DEFUN ("sha1", Fsha1, Ssha1, 1, 4, 0,
- doc: /* Return the SHA-1 (Secure Hash Algorithm) of an OBJECT.
-
-OBJECT is either a string or a buffer. Optional arguments START and
-END are character positions specifying which portion of OBJECT for
-computing the hash. If BINARY is non-nil, return a string in binary
-form. */)
- (Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp_Object binary)
+DEFUN ("secure-hash", Fsecure_hash, Ssecure_hash, 2, 5, 0,
+ doc: /* Return the secure hash of an OBJECT.
+ALGORITHM is a symbol: md5, sha1, sha224, sha256, sha384 or sha512.
+OBJECT is either a string or a buffer.
+Optional arguments START and END are character positions specifying
+which portion of OBJECT for computing the hash. If BINARY is non-nil,
+return a string in binary form. */)
+ (Lisp_Object algorithm, Lisp_Object object, Lisp_Object start, Lisp_Object end, Lisp_Object binary)
{
- return crypto_hash_function (1, object, start, end, Qnil, Qnil, binary);
+ return secure_hash (algorithm, object, start, end, Qnil, Qnil, binary);
}
-
\f
void
syms_of_fns (void)
{
+ DEFSYM (Qmd5, "md5");
+ DEFSYM (Qsha1, "sha1");
+ DEFSYM (Qsha224, "sha224");
+ DEFSYM (Qsha256, "sha256");
+ DEFSYM (Qsha384, "sha384");
+ DEFSYM (Qsha512, "sha512");
+
/* Hash table stuff. */
- Qhash_table_p = intern_c_string ("hash-table-p");
- staticpro (&Qhash_table_p);
- Qeq = intern_c_string ("eq");
- staticpro (&Qeq);
- Qeql = intern_c_string ("eql");
- staticpro (&Qeql);
- Qequal = intern_c_string ("equal");
- staticpro (&Qequal);
- QCtest = intern_c_string (":test");
- staticpro (&QCtest);
- QCsize = intern_c_string (":size");
- staticpro (&QCsize);
- QCrehash_size = intern_c_string (":rehash-size");
- staticpro (&QCrehash_size);
- QCrehash_threshold = intern_c_string (":rehash-threshold");
- staticpro (&QCrehash_threshold);
- QCweakness = intern_c_string (":weakness");
- staticpro (&QCweakness);
- Qkey = intern_c_string ("key");
- staticpro (&Qkey);
- Qvalue = intern_c_string ("value");
- staticpro (&Qvalue);
- Qhash_table_test = intern_c_string ("hash-table-test");
- staticpro (&Qhash_table_test);
- Qkey_or_value = intern_c_string ("key-or-value");
- staticpro (&Qkey_or_value);
- Qkey_and_value = intern_c_string ("key-and-value");
- staticpro (&Qkey_and_value);
+ DEFSYM (Qhash_table_p, "hash-table-p");
+ DEFSYM (Qeq, "eq");
+ DEFSYM (Qeql, "eql");
+ DEFSYM (Qequal, "equal");
+ DEFSYM (QCtest, ":test");
+ DEFSYM (QCsize, ":size");
+ DEFSYM (QCrehash_size, ":rehash-size");
+ DEFSYM (QCrehash_threshold, ":rehash-threshold");
+ DEFSYM (QCweakness, ":weakness");
+ DEFSYM (Qkey, "key");
+ DEFSYM (Qvalue, "value");
+ DEFSYM (Qhash_table_test, "hash-table-test");
+ DEFSYM (Qkey_or_value, "key-or-value");
+ DEFSYM (Qkey_and_value, "key-and-value");
defsubr (&Ssxhash);
defsubr (&Smake_hash_table);
defsubr (&Smaphash);
defsubr (&Sdefine_hash_table_test);
- Qstring_lessp = intern_c_string ("string-lessp");
- staticpro (&Qstring_lessp);
- Qprovide = intern_c_string ("provide");
- staticpro (&Qprovide);
- Qrequire = intern_c_string ("require");
- staticpro (&Qrequire);
- Qyes_or_no_p_history = intern_c_string ("yes-or-no-p-history");
- staticpro (&Qyes_or_no_p_history);
- Qcursor_in_echo_area = intern_c_string ("cursor-in-echo-area");
- staticpro (&Qcursor_in_echo_area);
- Qwidget_type = intern_c_string ("widget-type");
- staticpro (&Qwidget_type);
+ DEFSYM (Qstring_lessp, "string-lessp");
+ DEFSYM (Qprovide, "provide");
+ DEFSYM (Qrequire, "require");
+ DEFSYM (Qyes_or_no_p_history, "yes-or-no-p-history");
+ DEFSYM (Qcursor_in_echo_area, "cursor-in-echo-area");
+ DEFSYM (Qwidget_type, "widget-type");
staticpro (&string_char_byte_cache_string);
string_char_byte_cache_string = Qnil;
doc: /* A list of symbols which are the features of the executing Emacs.
Used by `featurep' and `require', and altered by `provide'. */);
Vfeatures = Fcons (intern_c_string ("emacs"), Qnil);
- Qsubfeatures = intern_c_string ("subfeatures");
- staticpro (&Qsubfeatures);
+ DEFSYM (Qsubfeatures, "subfeatures");
#ifdef HAVE_LANGINFO_CODESET
- Qcodeset = intern_c_string ("codeset");
- staticpro (&Qcodeset);
- Qdays = intern_c_string ("days");
- staticpro (&Qdays);
- Qmonths = intern_c_string ("months");
- staticpro (&Qmonths);
- Qpaper = intern_c_string ("paper");
- staticpro (&Qpaper);
+ DEFSYM (Qcodeset, "codeset");
+ DEFSYM (Qdays, "days");
+ DEFSYM (Qmonths, "months");
+ DEFSYM (Qpaper, "paper");
#endif /* HAVE_LANGINFO_CODESET */
DEFVAR_BOOL ("use-dialog-box", use_dialog_box,
defsubr (&Sbase64_encode_string);
defsubr (&Sbase64_decode_string);
defsubr (&Smd5);
- defsubr (&Ssha1);
+ defsubr (&Ssecure_hash);
defsubr (&Slocale_info);
}