Make numerous improvements

- Python static hello world now 1.8mb
- Python static fully loaded now 10mb
- Python HTTPS client now uses MbedTLS
- Python REPL now completes import stmts
- Increase stack size for Python for now
- Begin synthesizing posixpath and ntpath
- Restore Python \N{UNICODE NAME} support
- Restore Python NFKD symbol normalization
- Add optimized code path for Intel SHA-NI
- Get more Python unit tests passing faster
- Get Python help() pagination working on NT
- Python hashlib now supports MbedTLS PBKDF2
- Make memcpy/memmove/memcmp/bcmp/etc. faster
- Add Mersenne Twister and Vigna to LIBC_RAND
- Provide privileged __printf() for error code
- Fix zipos opendir() so that it reports ENOTDIR
- Add basic chmod() implementation for Windows NT
- Add Cosmo's best functions to Python cosmo module
- Pin function trace indent depth to that of caller
- Show memory diagram on invalid access in MODE=dbg
- Differentiate stack overflow on crash in MODE=dbg
- Add stb_truetype and tools for analyzing font files
- Upgrade to UNICODE 13 and reduce its binary footprint
- COMPILE.COM now logs resource usage of build commands
- Start implementing basic poll() support on bare metal
- Set getauxval(AT_EXECFN) to GetModuleFileName() on NT
- Add descriptions to strerror() in non-TINY build modes
- Add COUNTBRANCH() macro to help with micro-optimizations
- Make error / backtrace / asan / memory code more unbreakable
- Add fast perfect C implementation of μ-Law and a-Law audio codecs
- Make strtol() functions consistent with other libc implementations
- Improve Linenoise implementation (see also github.com/jart/bestline)
- COMPILE.COM now suppresses stdout/stderr of successful build commands
This commit is contained in:
Justine Tunney 2021-09-27 22:58:51 -07:00
parent fa7b4f5bd1
commit 39bf41f4eb
806 changed files with 77494 additions and 63859 deletions

View file

@ -2448,3 +2448,8 @@ PyInit__collections(void)
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__collections = {
"_collections",
PyInit__collections,
};

View file

@ -28,6 +28,7 @@
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libc/fmt/fmt.h"
#include "libc/log/libfatal.internal.h"
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/boolobject.h"
#include "third_party/python/Include/complexobject.h"
@ -103,13 +104,10 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
#define CONFIG_64
#if !defined(MPD_VERSION_HEX) || MPD_VERSION_HEX < 0x02040100
#error "libmpdec version >= 2.4.1 required"
#endif
/*
* Type sizes with assertions in mpdecimal.h and pyport.h:
* sizeof(size_t) == sizeof(Py_ssize_t)
@ -346,8 +344,9 @@ runtime_error_ptr(const char *mesg)
return runtime_error_ptr("internal error in " funcname)
static void
dec_traphandler(mpd_context_t *ctx UNUSED) /* GCOV_NOT_REACHED */
{ /* GCOV_NOT_REACHED */
dec_traphandler(mpd_context_t *ctx)
{
(void)ctx;
return; /* GCOV_NOT_REACHED */
}
@ -355,14 +354,12 @@ static PyObject *
flags_as_exception(uint32_t flags)
{
DecCondMap *cm;
for (cm = signal_map; cm->name != NULL; cm++) {
if (flags&cm->flag) {
return cm->ex;
}
}
INTERNAL_ERROR_PTR("flags_as_exception"); /* GCOV_NOT_REACHED */
INTERNAL_ERROR_PTR("flags_as_exception");
}
Py_LOCAL_INLINE(uint32_t)
@ -606,22 +603,26 @@ getround(PyObject *v)
a context, it cannot be deleted. */
static int
signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED)
signaldict_init(PyObject *self, PyObject *args, PyObject *kwds)
{
(void)args;
(void)kwds;
SdFlagAddr(self) = NULL;
return 0;
}
static Py_ssize_t
signaldict_len(PyObject *self UNUSED)
signaldict_len(PyObject *self)
{
(void)self;
return SIGNAL_MAP_LEN;
}
static PyObject *SignalTuple;
static PyObject *
signaldict_iter(PyObject *self UNUSED)
signaldict_iter(PyObject *self)
{
(void)self;
return PyTuple_Type.tp_iter(SignalTuple);
}
@ -724,8 +725,9 @@ signaldict_richcompare(PyObject *v, PyObject *w, int op)
}
static PyObject *
signaldict_copy(PyObject *self, PyObject *args UNUSED)
signaldict_copy(PyObject *self, PyObject *args)
{
(void)args;
return flags_as_dict(SdFlags(self));
}
@ -792,15 +794,17 @@ static PyTypeObject PyDecSignalDictMixin_Type =
#define Dec_CONTEXT_GET_SSIZE(mem) \
static PyObject * \
context_get##mem(PyObject *self, void *closure UNUSED) \
context_get##mem(PyObject *self, void *closure) \
{ \
(void)closure; \
return PyLong_FromSsize_t(mpd_get##mem(CTX(self))); \
}
#define Dec_CONTEXT_GET_ULONG(mem) \
static PyObject * \
context_get##mem(PyObject *self, void *closure UNUSED) \
context_get##mem(PyObject *self, void *closure) \
{ \
(void)closure; \
return PyLong_FromUnsignedLong(mpd_get##mem(CTX(self))); \
}
@ -815,7 +819,7 @@ Dec_CONTEXT_GET_ULONG(status)
#endif
static PyObject *
context_getround(PyObject *self, void *closure UNUSED)
context_getround(PyObject *self, void *closure)
{
int i = mpd_getround(CTX(self));
@ -824,33 +828,33 @@ context_getround(PyObject *self, void *closure UNUSED)
}
static PyObject *
context_getcapitals(PyObject *self, void *closure UNUSED)
context_getcapitals(PyObject *self, void *closure)
{
return PyLong_FromLong(CtxCaps(self));
}
#ifdef EXTRA_FUNCTIONALITY
static PyObject *
context_getallcr(PyObject *self, void *closure UNUSED)
context_getallcr(PyObject *self, void *closure)
{
return PyLong_FromLong(mpd_getcr(CTX(self)));
}
#endif
static PyObject *
context_getetiny(PyObject *self, PyObject *dummy UNUSED)
context_getetiny(PyObject *self, PyObject *dummy)
{
return PyLong_FromSsize_t(mpd_etiny(CTX(self)));
}
static PyObject *
context_getetop(PyObject *self, PyObject *dummy UNUSED)
context_getetop(PyObject *self, PyObject *dummy)
{
return PyLong_FromSsize_t(mpd_etop(CTX(self)));
}
static int
context_setprec(PyObject *self, PyObject *value, void *closure UNUSED)
context_setprec(PyObject *self, PyObject *value, void *closure)
{
mpd_context_t *ctx;
mpd_ssize_t x;
@ -870,7 +874,7 @@ context_setprec(PyObject *self, PyObject *value, void *closure UNUSED)
}
static int
context_setemin(PyObject *self, PyObject *value, void *closure UNUSED)
context_setemin(PyObject *self, PyObject *value, void *closure)
{
mpd_context_t *ctx;
mpd_ssize_t x;
@ -890,7 +894,7 @@ context_setemin(PyObject *self, PyObject *value, void *closure UNUSED)
}
static int
context_setemax(PyObject *self, PyObject *value, void *closure UNUSED)
context_setemax(PyObject *self, PyObject *value, void *closure)
{
mpd_context_t *ctx;
mpd_ssize_t x;
@ -972,7 +976,7 @@ context_unsafe_setemax(PyObject *self, PyObject *value)
#endif
static int
context_setround(PyObject *self, PyObject *value, void *closure UNUSED)
context_setround(PyObject *self, PyObject *value, void *closure)
{
mpd_context_t *ctx;
int x;
@ -991,7 +995,7 @@ context_setround(PyObject *self, PyObject *value, void *closure UNUSED)
}
static int
context_setcapitals(PyObject *self, PyObject *value, void *closure UNUSED)
context_setcapitals(PyObject *self, PyObject *value, void *closure)
{
mpd_ssize_t x;
@ -1011,7 +1015,7 @@ context_setcapitals(PyObject *self, PyObject *value, void *closure UNUSED)
#ifdef EXTRA_FUNCTIONALITY
static int
context_settraps(PyObject *self, PyObject *value, void *closure UNUSED)
context_settraps(PyObject *self, PyObject *value, void *closure)
{
mpd_context_t *ctx;
uint32_t flags;
@ -1075,7 +1079,7 @@ context_settraps_dict(PyObject *self, PyObject *value)
#ifdef EXTRA_FUNCTIONALITY
static int
context_setstatus(PyObject *self, PyObject *value, void *closure UNUSED)
context_setstatus(PyObject *self, PyObject *value, void *closure)
{
mpd_context_t *ctx;
uint32_t flags;
@ -1138,7 +1142,7 @@ context_setstatus_dict(PyObject *self, PyObject *value)
}
static int
context_setclamp(PyObject *self, PyObject *value, void *closure UNUSED)
context_setclamp(PyObject *self, PyObject *value, void *closure)
{
mpd_context_t *ctx;
mpd_ssize_t x;
@ -1159,7 +1163,7 @@ context_setclamp(PyObject *self, PyObject *value, void *closure UNUSED)
#ifdef EXTRA_FUNCTIONALITY
static int
context_setallcr(PyObject *self, PyObject *value, void *closure UNUSED)
context_setallcr(PyObject *self, PyObject *value, void *closure)
{
mpd_context_t *ctx;
mpd_ssize_t x;
@ -1222,14 +1226,14 @@ context_setattr(PyObject *self, PyObject *name, PyObject *value)
}
static PyObject *
context_clear_traps(PyObject *self, PyObject *dummy UNUSED)
context_clear_traps(PyObject *self, PyObject *dummy)
{
CTX(self)->traps = 0;
Py_RETURN_NONE;
}
static PyObject *
context_clear_flags(PyObject *self, PyObject *dummy UNUSED)
context_clear_flags(PyObject *self, PyObject *dummy)
{
CTX(self)->status = 0;
Py_RETURN_NONE;
@ -1245,7 +1249,7 @@ static mpd_context_t dflt_ctx = {
};
static PyObject *
context_new(PyTypeObject *type, PyObject *args UNUSED, PyObject *kwds UNUSED)
context_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyDecContextObject *self = NULL;
mpd_context_t *ctx;
@ -1445,7 +1449,7 @@ init_extended_context(PyObject *v)
#ifdef EXTRA_FUNCTIONALITY
/* Factory function for creating IEEE interchange format contexts */
static PyObject *
ieee_context(PyObject *dummy UNUSED, PyObject *v)
ieee_context(PyObject *dummy, PyObject *v)
{
PyObject *context;
mpd_ssize_t bits;
@ -1480,7 +1484,7 @@ error:
#endif
static PyObject *
context_copy(PyObject *self, PyObject *args UNUSED)
context_copy(PyObject *self, PyObject *args)
{
PyObject *copy;
@ -1497,7 +1501,7 @@ context_copy(PyObject *self, PyObject *args UNUSED)
}
static PyObject *
context_reduce(PyObject *self, PyObject *args UNUSED)
context_reduce(PyObject *self, PyObject *args)
{
PyObject *flags;
PyObject *traps;
@ -1601,7 +1605,7 @@ current_context(void)
/* Return a new reference to the current context */
static PyObject *
PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
PyDec_GetCurrentContext(PyObject *self, PyObject *args)
{
PyObject *context;
@ -1613,7 +1617,7 @@ PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
/* Set the module context to a new context, decrement old reference */
static PyObject *
PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
PyDec_SetCurrentContext(PyObject *self, PyObject *v)
{
CONTEXT_CHECK(v);
@ -1728,7 +1732,7 @@ current_context(void)
/* Return a new reference to the current context */
static PyObject *
PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
PyDec_GetCurrentContext(PyObject *self, PyObject *args)
{
PyObject *context;
@ -1743,7 +1747,7 @@ PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
/* Set the thread local context to a new context, decrement old reference */
static PyObject *
PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
PyDec_SetCurrentContext(PyObject *self, PyObject *v)
{
PyObject *dict;
@ -1786,7 +1790,7 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
* owns one reference to the global (outer) context and one
* to the local (inner) context. */
static PyObject *
ctxmanager_new(PyTypeObject *type UNUSED, PyObject *args, PyObject *kwds)
ctxmanager_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"ctx", NULL};
PyDecContextManagerObject *self;
@ -1833,7 +1837,7 @@ ctxmanager_dealloc(PyDecContextManagerObject *self)
}
static PyObject *
ctxmanager_set_local(PyDecContextManagerObject *self, PyObject *args UNUSED)
ctxmanager_set_local(PyDecContextManagerObject *self, PyObject *args)
{
PyObject *ret;
@ -1849,7 +1853,7 @@ ctxmanager_set_local(PyDecContextManagerObject *self, PyObject *args UNUSED)
static PyObject *
ctxmanager_restore_global(PyDecContextManagerObject *self,
PyObject *args UNUSED)
PyObject *args)
{
PyObject *ret;
@ -1970,21 +1974,17 @@ numeric_as_ascii(const PyObject *u, int strip_ws, int ignore_underscores)
char *res, *cp;
Py_ssize_t j, len;
int d;
if (PyUnicode_READY(u) == -1) {
return NULL;
}
kind = PyUnicode_KIND(u);
data = PyUnicode_DATA(u);
len = PyUnicode_GET_LENGTH(u);
cp = res = PyMem_Malloc(len+1);
if (res == NULL) {
PyErr_NoMemory();
return NULL;
}
j = 0;
if (strip_ws) {
while (len > 0 && is_space(kind, data, len-1)) {
@ -1994,7 +1994,6 @@ numeric_as_ascii(const PyObject *u, int strip_ws, int ignore_underscores)
j++;
}
}
for (; j < len; j++) {
ch = PyUnicode_READ(kind, data, j);
if (ignore_underscores && ch == '_') {
@ -2028,12 +2027,10 @@ PyDecType_FromCString(PyTypeObject *type, const char *s,
{
PyObject *dec;
uint32_t status = 0;
dec = PyDecType_New(type);
if (dec == NULL) {
return NULL;
}
mpd_qset_string(MPD(dec), s, CTX(context), &status);
if (dec_addstatus(context, status)) {
Py_DECREF(dec);
@ -2052,14 +2049,11 @@ PyDecType_FromCStringExact(PyTypeObject *type, const char *s,
PyObject *dec;
uint32_t status = 0;
mpd_context_t maxctx;
dec = PyDecType_New(type);
if (dec == NULL) {
return NULL;
}
mpd_maxcontext(&maxctx);
mpd_qset_string(MPD(dec), s, &maxctx, &status);
if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
/* we want exact results */
@ -2070,7 +2064,6 @@ PyDecType_FromCStringExact(PyTypeObject *type, const char *s,
Py_DECREF(dec);
return NULL;
}
return dec;
}
@ -2081,12 +2074,10 @@ PyDecType_FromUnicode(PyTypeObject *type, const PyObject *u,
{
PyObject *dec;
char *s;
s = numeric_as_ascii(u, 0, 0);
if (s == NULL) {
return NULL;
}
dec = PyDecType_FromCString(type, s, context);
PyMem_Free(s);
return dec;
@ -2101,12 +2092,10 @@ PyDecType_FromUnicodeExactWS(PyTypeObject *type, const PyObject *u,
{
PyObject *dec;
char *s;
s = numeric_as_ascii(u, 1, 1);
if (s == NULL) {
return NULL;
}
dec = PyDecType_FromCStringExact(type, s, context);
PyMem_Free(s);
return dec;
@ -2116,18 +2105,8 @@ PyDecType_FromUnicodeExactWS(PyTypeObject *type, const PyObject *u,
Py_LOCAL_INLINE(void)
_dec_settriple(PyObject *dec, uint8_t sign, uint32_t v, mpd_ssize_t exp)
{
#ifdef CONFIG_64
MPD(dec)->data[0] = v;
MPD(dec)->len = 1;
#else
uint32_t q, r;
q = v / MPD_RADIX;
r = v - q * MPD_RADIX;
MPD(dec)->data[1] = q;
MPD(dec)->data[0] = r;
MPD(dec)->len = q ? 2 : 1;
#endif
mpd_set_flags(MPD(dec), sign);
MPD(dec)->exp = exp;
mpd_setdigits(MPD(dec));
@ -3475,7 +3454,7 @@ dec_as_long(PyObject *dec, PyObject *context, int round)
/* Convert a Decimal to its exact integer ratio representation. */
static PyObject *
dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
dec_as_integer_ratio(PyObject *self, PyObject *args)
{
PyObject *numerator = NULL;
PyObject *denominator = NULL;
@ -3737,7 +3716,7 @@ PyDec_Round(PyObject *dec, PyObject *args)
static PyTypeObject *DecimalTuple = NULL;
/* Return the DecimalTuple representation of a PyDecObject. */
static PyObject *
PyDec_AsTuple(PyObject *dec, PyObject *dummy UNUSED)
PyDec_AsTuple(PyObject *dec, PyObject *dummy)
{
PyObject *result = NULL;
PyObject *sign = NULL;
@ -3890,7 +3869,7 @@ nm_##MPDFUNC(PyObject *self, PyObject *other) \
/* Boolean function without a context arg. */
#define Dec_BoolFunc(MPDFUNC) \
static PyObject * \
dec_##MPDFUNC(PyObject *self, PyObject *dummy UNUSED) \
dec_##MPDFUNC(PyObject *self, PyObject *dummy) \
{ \
return MPDFUNC(MPD(self)) ? incr_true() : incr_false(); \
}
@ -4209,7 +4188,7 @@ Dec_BoolFuncVA(mpd_issubnormal)
/* Unary functions, no context arg */
static PyObject *
dec_mpd_adjexp(PyObject *self, PyObject *dummy UNUSED)
dec_mpd_adjexp(PyObject *self, PyObject *dummy)
{
mpd_ssize_t retval;
@ -4224,21 +4203,21 @@ dec_mpd_adjexp(PyObject *self, PyObject *dummy UNUSED)
}
static PyObject *
dec_canonical(PyObject *self, PyObject *dummy UNUSED)
dec_canonical(PyObject *self, PyObject *dummy)
{
Py_INCREF(self);
return self;
}
static PyObject *
dec_conjugate(PyObject *self, PyObject *dummy UNUSED)
dec_conjugate(PyObject *self, PyObject *dummy)
{
Py_INCREF(self);
return self;
}
static PyObject *
dec_mpd_radix(PyObject *self UNUSED, PyObject *dummy UNUSED)
dec_mpd_radix(PyObject *self, PyObject *dummy)
{
PyObject *result;
@ -4252,7 +4231,7 @@ dec_mpd_radix(PyObject *self UNUSED, PyObject *dummy UNUSED)
}
static PyObject *
dec_mpd_qcopy_abs(PyObject *self, PyObject *dummy UNUSED)
dec_mpd_qcopy_abs(PyObject *self, PyObject *dummy)
{
PyObject *result;
uint32_t status = 0;
@ -4272,7 +4251,7 @@ dec_mpd_qcopy_abs(PyObject *self, PyObject *dummy UNUSED)
}
static PyObject *
dec_mpd_qcopy_negate(PyObject *self, PyObject *dummy UNUSED)
dec_mpd_qcopy_negate(PyObject *self, PyObject *dummy)
{
PyObject *result;
uint32_t status = 0;
@ -4518,7 +4497,7 @@ dec_richcompare(PyObject *v, PyObject *w, int op)
/* __ceil__ */
static PyObject *
dec_ceil(PyObject *self, PyObject *dummy UNUSED)
dec_ceil(PyObject *self, PyObject *dummy)
{
PyObject *context;
@ -4528,7 +4507,7 @@ dec_ceil(PyObject *self, PyObject *dummy UNUSED)
/* __complex__ */
static PyObject *
dec_complex(PyObject *self, PyObject *dummy UNUSED)
dec_complex(PyObject *self, PyObject *dummy)
{
PyObject *f;
double x;
@ -4549,7 +4528,7 @@ dec_complex(PyObject *self, PyObject *dummy UNUSED)
/* __copy__ and __deepcopy__ */
static PyObject *
dec_copy(PyObject *self, PyObject *dummy UNUSED)
dec_copy(PyObject *self, PyObject *dummy)
{
Py_INCREF(self);
return self;
@ -4557,10 +4536,9 @@ dec_copy(PyObject *self, PyObject *dummy UNUSED)
/* __floor__ */
static PyObject *
dec_floor(PyObject *self, PyObject *dummy UNUSED)
dec_floor(PyObject *self, PyObject *dummy)
{
PyObject *context;
CURRENT_CONTEXT(context);
return dec_as_long(self, context, MPD_ROUND_FLOOR);
}
@ -4569,7 +4547,6 @@ dec_floor(PyObject *self, PyObject *dummy UNUSED)
static Py_hash_t
_dec_hash(PyDecObject *v)
{
#if defined(CONFIG_64) && _PyHASH_BITS == 61
/* 2**61 - 1 */
mpd_uint_t p_data[1] = {2305843009213693951ULL};
mpd_t p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 19, 1, 1, p_data};
@ -4577,17 +4554,6 @@ _dec_hash(PyDecObject *v)
mpd_uint_t inv10_p_data[1] = {2075258708292324556ULL};
mpd_t inv10_p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA,
0, 19, 1, 1, inv10_p_data};
#elif defined(CONFIG_32) && _PyHASH_BITS == 31
/* 2**31 - 1 */
mpd_uint_t p_data[2] = {147483647UL, 2};
mpd_t p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 10, 2, 2, p_data};
/* Inverse of 10 modulo p */
mpd_uint_t inv10_p_data[2] = {503238553UL, 1};
mpd_t inv10_p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA,
0, 10, 2, 2, inv10_p_data};
#else
#error "No valid combination of CONFIG_64, CONFIG_32 and _PyHASH_BITS"
#endif
const Py_hash_t py_hash_inf = 314159;
const Py_hash_t py_hash_nan = 0;
mpd_uint_t ten_data[1] = {10};
@ -4700,7 +4666,7 @@ dec_hash(PyDecObject *self)
/* __reduce__ */
static PyObject *
dec_reduce(PyObject *self, PyObject *dummy UNUSED)
dec_reduce(PyObject *self, PyObject *dummy)
{
PyObject *result, *str;
@ -4717,7 +4683,7 @@ dec_reduce(PyObject *self, PyObject *dummy UNUSED)
/* __sizeof__ */
static PyObject *
dec_sizeof(PyObject *v, PyObject *dummy UNUSED)
dec_sizeof(PyObject *v, PyObject *dummy)
{
Py_ssize_t res;
@ -4730,7 +4696,7 @@ dec_sizeof(PyObject *v, PyObject *dummy UNUSED)
/* __trunc__ */
static PyObject *
dec_trunc(PyObject *self, PyObject *dummy UNUSED)
dec_trunc(PyObject *self, PyObject *dummy)
{
PyObject *context;
@ -4740,14 +4706,14 @@ dec_trunc(PyObject *self, PyObject *dummy UNUSED)
/* real and imag */
static PyObject *
dec_real(PyObject *self, void *closure UNUSED)
dec_real(PyObject *self, void *closure)
{
Py_INCREF(self);
return self;
}
static PyObject *
dec_imag(PyObject *self UNUSED, void *closure UNUSED)
dec_imag(PyObject *self, void *closure)
{
PyObject *result;
@ -5105,7 +5071,6 @@ ctx_##MPDFUNC(PyObject *context, PyObject *args) \
return result; \
}
/* Unary arithmetic functions */
DecCtx_UnaryFunc(mpd_qabs)
DecCtx_UnaryFunc(mpd_qexp)
@ -5145,13 +5110,10 @@ ctx_mpd_qdivmod(PyObject *context, PyObject *args)
PyObject *q, *r;
uint32_t status = 0;
PyObject *ret;
if (!PyArg_ParseTuple(args, "OO", &v, &w)) {
return NULL;
}
CONVERT_BINOP_RAISE(&a, &b, v, w, context);
q = dec_alloc();
if (q == NULL) {
Py_DECREF(a);
@ -5165,7 +5127,6 @@ ctx_mpd_qdivmod(PyObject *context, PyObject *args)
Py_DECREF(q);
return NULL;
}
mpd_qdivmod(MPD(q), MPD(r), MPD(a), MPD(b), CTX(context), &status);
Py_DECREF(a);
Py_DECREF(b);
@ -5174,7 +5135,6 @@ ctx_mpd_qdivmod(PyObject *context, PyObject *args)
Py_DECREF(q);
return NULL;
}
ret = Py_BuildValue("(OO)", q, r);
Py_DECREF(r);
Py_DECREF(q);
@ -5190,14 +5150,11 @@ ctx_mpd_qpow(PyObject *context, PyObject *args, PyObject *kwds)
PyObject *a, *b, *c = NULL;
PyObject *result;
uint32_t status = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist,
&base, &exp, &mod)) {
return NULL;
}
CONVERT_BINOP_RAISE(&a, &b, base, exp, context);
if (mod != Py_None) {
if (!convert_op(TYPE_ERR, &c, mod, context)) {
Py_DECREF(a);
@ -5205,7 +5162,6 @@ ctx_mpd_qpow(PyObject *context, PyObject *args, PyObject *kwds)
return c;
}
}
result = dec_alloc();
if (result == NULL) {
Py_DECREF(a);
@ -5213,7 +5169,6 @@ ctx_mpd_qpow(PyObject *context, PyObject *args, PyObject *kwds)
Py_XDECREF(c);
return NULL;
}
if (c == NULL) {
mpd_qpow(MPD(result), MPD(a), MPD(b),
CTX(context), &status);
@ -5229,7 +5184,6 @@ ctx_mpd_qpow(PyObject *context, PyObject *args, PyObject *kwds)
Py_DECREF(result);
return NULL;
}
return result;
}
@ -5255,14 +5209,13 @@ DecCtx_BoolFunc_NO_CTX(mpd_issnan)
DecCtx_BoolFunc_NO_CTX(mpd_iszero)
static PyObject *
ctx_iscanonical(PyObject *context UNUSED, PyObject *v)
ctx_iscanonical(PyObject *context, PyObject *v)
{
if (!PyDec_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"argument must be a Decimal");
return NULL;
}
return mpd_iscanonical(MPD(v)) ? incr_true() : incr_false();
}
@ -5271,23 +5224,20 @@ static PyObject *
PyDecContext_Apply(PyObject *context, PyObject *v)
{
PyObject *result, *a;
CONVERT_OP_RAISE(&a, v, context);
result = dec_apply(a, context);
Py_DECREF(a);
return result;
}
static PyObject *
ctx_canonical(PyObject *context UNUSED, PyObject *v)
ctx_canonical(PyObject *context, PyObject *v)
{
if (!PyDec_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"argument must be a Decimal");
return NULL;
}
Py_INCREF(v);
return v;
}
@ -5297,22 +5247,18 @@ ctx_mpd_qcopy_abs(PyObject *context, PyObject *v)
{
PyObject *result, *a;
uint32_t status = 0;
CONVERT_OP_RAISE(&a, v, context);
result = dec_alloc();
if (result == NULL) {
Py_DECREF(a);
return NULL;
}
mpd_qcopy_abs(MPD(result), MPD(a), &status);
Py_DECREF(a);
if (dec_addstatus(context, status)) {
Py_DECREF(result);
return NULL;
}
return result;
}
@ -5320,7 +5266,6 @@ static PyObject *
ctx_copy_decimal(PyObject *context, PyObject *v)
{
PyObject *result;
CONVERT_OP_RAISE(&result, v, context);
return result;
}
@ -5330,22 +5275,18 @@ ctx_mpd_qcopy_negate(PyObject *context, PyObject *v)
{
PyObject *result, *a;
uint32_t status = 0;
CONVERT_OP_RAISE(&a, v, context);
result = dec_alloc();
if (result == NULL) {
Py_DECREF(a);
return NULL;
}
mpd_qcopy_negate(MPD(result), MPD(a), &status);
Py_DECREF(a);
if (dec_addstatus(context, status)) {
Py_DECREF(result);
return NULL;
}
return result;
}
@ -5357,12 +5298,9 @@ ctx_mpd_class(PyObject *context, PyObject *v)
{
PyObject *a;
const char *cp;
CONVERT_OP_RAISE(&a, v, context);
cp = mpd_class(MPD(a), CTX(context));
Py_DECREF(a);
return PyUnicode_FromString(cp);
}
@ -5373,19 +5311,15 @@ ctx_mpd_to_sci(PyObject *context, PyObject *v)
PyObject *a;
mpd_ssize_t size;
char *s;
CONVERT_OP_RAISE(&a, v, context);
size = mpd_to_sci_size(&s, MPD(a), CtxCaps(context));
Py_DECREF(a);
if (size < 0) {
PyErr_NoMemory();
return NULL;
}
result = unicode_fromascii(s, size);
mpd_free(s);
return result;
}
@ -5396,19 +5330,15 @@ ctx_mpd_to_eng(PyObject *context, PyObject *v)
PyObject *a;
mpd_ssize_t size;
char *s;
CONVERT_OP_RAISE(&a, v, context);
size = mpd_to_eng_size(&s, MPD(a), CtxCaps(context));
Py_DECREF(a);
if (size < 0) {
PyErr_NoMemory();
return NULL;
}
result = unicode_fromascii(s, size);
mpd_free(s);
return result;
}
@ -5566,13 +5496,6 @@ static PyMethodDef context_methods [] =
{ "clear_flags", context_clear_flags, METH_NOARGS, doc_ctx_clear_flags },
{ "clear_traps", context_clear_traps, METH_NOARGS, doc_ctx_clear_traps },
#ifdef CONFIG_32
/* Unsafe set functions with relaxed range checks */
{ "_unsafe_setprec", context_unsafe_setprec, METH_O, NULL },
{ "_unsafe_setemin", context_unsafe_setemin, METH_O, NULL },
{ "_unsafe_setemax", context_unsafe_setemax, METH_O, NULL },
#endif
/* Miscellaneous */
{ "__copy__", (PyCFunction)context_copy, METH_NOARGS, NULL },
{ "__reduce__", context_reduce, METH_NOARGS, NULL },

View file

@ -42,7 +42,6 @@ asm(".include \"libc/disclaimer.inc\"");
/* Calculations in base MPD_RADIX */
/*********************************************************************/
/*
* Knuth, TAOCP, Volume 2, 4.3.1:
* w := sum of u (len m) and v (len n)
@ -56,9 +55,7 @@ _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
mpd_uint_t s;
mpd_uint_t carry = 0;
mpd_size_t i;
assert(n > 0 && m >= n);
/* add n members of u and v */
for (i = 0; i < n; i++) {
s = u[i] + (v[i] + carry);
@ -75,7 +72,6 @@ _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
for (; i < m; i++) {
w[i] = u[i];
}
return carry;
}
@ -89,9 +85,7 @@ _mpd_baseaddto(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
mpd_uint_t s;
mpd_uint_t carry = 0;
mpd_size_t i;
if (n == 0) return;
/* add n members of u to w */
for (i = 0; i < n; i++) {
s = w[i] + (u[i] + carry);
@ -116,21 +110,17 @@ _mpd_shortadd(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v)
mpd_uint_t s;
mpd_uint_t carry;
mpd_size_t i;
assert(m > 0);
/* add v to w */
s = w[0] + v;
carry = (s < v) | (s >= MPD_RADIX);
w[0] = carry ? s-MPD_RADIX : s;
/* if there is a carry, propagate it */
for (i = 1; carry && i < m; i++) {
s = w[i] + carry;
carry = (s == MPD_RADIX);
w[i] = carry ? 0 : s;
}
return carry;
}
@ -141,16 +131,13 @@ _mpd_baseincr(mpd_uint_t *u, mpd_size_t n)
mpd_uint_t s;
mpd_uint_t carry = 1;
mpd_size_t i;
assert(n > 0);
/* if there is a carry, propagate it */
for (i = 0; carry && i < n; i++) {
s = u[i] + carry;
carry = (s == MPD_RADIX);
u[i] = carry ? 0 : s;
}
return carry;
}
@ -166,9 +153,7 @@ _mpd_basesub(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
mpd_uint_t d;
mpd_uint_t borrow = 0;
mpd_size_t i;
assert(m > 0 && n > 0);
/* subtract n members of v from u */
for (i = 0; i < n; i++) {
d = u[i] - (v[i] + borrow);
@ -197,9 +182,7 @@ _mpd_basesubfrom(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n)
mpd_uint_t d;
mpd_uint_t borrow = 0;
mpd_size_t i;
if (n == 0) return;
/* subtract n members of u from w */
for (i = 0; i < n; i++) {
d = w[i] - (u[i] + borrow);
@ -221,15 +204,11 @@ _mpd_shortmul(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
mpd_uint_t hi, lo;
mpd_uint_t carry = 0;
mpd_size_t i;
assert(n > 0);
for (i=0; i < n; i++) {
_mpd_mul_words(&hi, &lo, u[i], v);
lo = carry + lo;
if (lo < carry) hi++;
_mpd_div_words_r(&carry, &w[i], hi, lo);
}
w[i] = carry;
@ -247,19 +226,15 @@ _mpd_basemul(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
mpd_uint_t hi, lo;
mpd_uint_t carry;
mpd_size_t i, j;
assert(m > 0 && n > 0);
for (j=0; j < n; j++) {
carry = 0;
for (i=0; i < m; i++) {
_mpd_mul_words(&hi, &lo, u[i], v[j]);
lo = w[i+j] + lo;
if (lo < w[i+j]) hi++;
lo = carry + lo;
if (lo < carry) hi++;
_mpd_div_words_r(&carry, &w[i+j], hi, lo);
}
w[j+m] = carry;
@ -276,18 +251,13 @@ _mpd_shortdiv(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
mpd_uint_t hi, lo;
mpd_uint_t rem = 0;
mpd_size_t i;
assert(n > 0);
for (i=n-1; i != MPD_SIZE_MAX; i--) {
_mpd_mul_words(&hi, &lo, rem, MPD_RADIX);
lo = u[i] + lo;
if (lo < u[i]) hi++;
_mpd_div_words(&w[i], &rem, hi, lo, v);
}
return rem;
}
@ -315,13 +285,10 @@ _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
mpd_uint_t carry;
mpd_size_t i, j, m;
int retval = 0;
assert(n > 1 && nplusm >= n);
m = sub_size_t(nplusm, n);
/* D1: normalize */
d = MPD_RADIX / (vconst[n-1] + 1);
if (nplusm >= MPD_MINALLOC_MAX) {
if ((u = mpd_alloc(nplusm+1, sizeof *u)) == NULL) {
return -1;
@ -333,17 +300,13 @@ _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
return -1;
}
}
_mpd_shortmul(u, uconst, nplusm, d);
_mpd_shortmul(v, vconst, n, d);
/* D2: loop */
for (j=m; j != MPD_SIZE_MAX; j--) {
/* D3: calculate qhat and rhat */
rhat = _mpd_shortdiv(w2, u+j+n-1, 2, v[n-1]);
qhat = w2[1] * MPD_RADIX + w2[0];
while (1) {
if (qhat < MPD_RADIX) {
_mpd_singlemul(w2, qhat, v[n-2]);
@ -362,14 +325,10 @@ _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
/* D4: multiply and subtract */
carry = 0;
for (i=0; i <= n; i++) {
_mpd_mul_words(&hi, &lo, qhat, v[i]);
lo = carry + lo;
if (lo < carry) hi++;
_mpd_div_words_r(&hi, &lo, hi, lo);
x = u[i+j] - lo;
carry = (u[i+j] < x);
u[i+j] = carry ? x+MPD_RADIX : x;
@ -383,7 +342,6 @@ _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
(void)_mpd_baseadd(u+j, u+j, v, n+1, n);
}
}
/* D8: unnormalize */
if (r != NULL) {
_mpd_shortdiv(r, u, n, d);
@ -393,11 +351,9 @@ _mpd_basedivmod(mpd_uint_t *q, mpd_uint_t *r,
else {
retval = !_mpd_isallzero(u, n);
}
if (u != ustatic) mpd_free(u);
if (v != vstatic) mpd_free(v);
return retval;
if (u != ustatic) mpd_free(u);
if (v != vstatic) mpd_free(v);
return retval;
}
/*
@ -428,23 +384,13 @@ void
_mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n, mpd_size_t m,
mpd_size_t shift)
{
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
/* spurious uninitialized warnings */
mpd_uint_t l=l, lprev=lprev, h=h;
#else
mpd_uint_t l, lprev, h;
#endif
mpd_uint_t l=l, lprev=lprev, h=h; /* b/c warnings */
mpd_uint_t q, r;
mpd_uint_t ph;
assert(m > 0 && n >= m);
_mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
if (r != 0) {
ph = mpd_pow10[r];
--m; --n;
_mpd_divmod_pow10(&h, &lprev, src[m--], MPD_RDIGITS-r);
if (h != 0) { /* r + msdigits > rdigits <==> h != 0 */
@ -464,7 +410,6 @@ _mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n, mpd_size_t m,
dest[m+q] = src[m];
}
}
mpd_uint_zero(dest, q);
}
@ -497,29 +442,19 @@ mpd_uint_t
_mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
mpd_size_t shift)
{
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
/* spurious uninitialized warnings */
mpd_uint_t l=l, h=h, hprev=hprev; /* low, high, previous high */
#else
mpd_uint_t l, h, hprev; /* low, high, previous high */
#endif
mpd_uint_t rnd, rest; /* rounding digit, rest */
mpd_uint_t q, r;
mpd_size_t i, j;
mpd_uint_t ph;
assert(slen > 0);
_mpd_div_word(&q, &r, (mpd_uint_t)shift, MPD_RDIGITS);
rnd = rest = 0;
if (r != 0) {
ph = mpd_pow10[MPD_RDIGITS-r];
_mpd_divmod_pow10(&hprev, &rest, src[q], r);
_mpd_divmod_pow10(&rnd, &rest, rest, r-1);
if (rest == 0 && q > 0) {
rest = !_mpd_isallzero(src, q);
}
@ -544,14 +479,12 @@ _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
dest[j] = src[q+j];
}
}
/* 0-4 ==> rnd+rest < 0.5 */
/* 5 ==> rnd+rest == 0.5 */
/* 6-9 ==> rnd+rest > 0.5 */
return (rnd == 0 || rnd == 5) ? rnd + !!rest : rnd;
}
/*********************************************************************/
/* Calculations in base b */
/*********************************************************************/
@ -566,21 +499,17 @@ _mpd_shortadd_b(mpd_uint_t *w, mpd_size_t m, mpd_uint_t v, mpd_uint_t b)
mpd_uint_t s;
mpd_uint_t carry;
mpd_size_t i;
assert(m > 0);
/* add v to w */
s = w[0] + v;
carry = (s < v) | (s >= b);
w[0] = carry ? s-b : s;
/* if there is a carry, propagate it */
for (i = 1; carry && i < m; i++) {
s = w[i] + carry;
carry = (s == b);
w[i] = carry ? 0 : s;
}
return carry;
}
@ -591,18 +520,13 @@ _mpd_shortmul_c(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n, mpd_uint_t v)
mpd_uint_t hi, lo;
mpd_uint_t carry = 0;
mpd_size_t i;
assert(n > 0);
for (i=0; i < n; i++) {
_mpd_mul_words(&hi, &lo, u[i], v);
lo = carry + lo;
if (lo < carry) hi++;
_mpd_div_words_r(&carry, &w[i], hi, lo);
}
return carry;
}
@ -614,18 +538,13 @@ _mpd_shortmul_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
mpd_uint_t hi, lo;
mpd_uint_t carry = 0;
mpd_size_t i;
assert(n > 0);
for (i=0; i < n; i++) {
_mpd_mul_words(&hi, &lo, u[i], v);
lo = carry + lo;
if (lo < carry) hi++;
_mpd_div_words(&carry, &w[i], hi, lo, b);
}
return carry;
}
@ -640,17 +559,12 @@ _mpd_shortdiv_b(mpd_uint_t *w, const mpd_uint_t *u, mpd_size_t n,
mpd_uint_t hi, lo;
mpd_uint_t rem = 0;
mpd_size_t i;
assert(n > 0);
for (i=n-1; i != MPD_SIZE_MAX; i--) {
_mpd_mul_words(&hi, &lo, rem, b);
lo = u[i] + lo;
if (lo < u[i]) hi++;
_mpd_div_words(&w[i], &rem, hi, lo, v);
}
return rem;
}

View file

@ -5,7 +5,6 @@
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
mpd_uint_t _mpd_baseadd(mpd_uint_t *w, const mpd_uint_t *u, const mpd_uint_t *v,
mpd_size_t m, mpd_size_t n);
@ -36,7 +35,6 @@ void _mpd_baseshiftl(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t n,
mpd_uint_t _mpd_baseshiftr(mpd_uint_t *dest, mpd_uint_t *src, mpd_size_t slen,
mpd_size_t shift);
#ifdef CONFIG_64
extern const mpd_uint_t mprime_rdx;
/*
@ -66,12 +64,10 @@ _mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
{
mpd_uint_t n_adj, h, l, t;
mpd_uint_t n1_neg;
/* n1_neg = if lo >= 2**63 then MPD_UINT_MAX else 0 */
n1_neg = (lo & (1ULL<<63)) ? MPD_UINT_MAX : 0;
/* n_adj = if lo >= 2**63 then lo+MPD_RADIX else lo */
n_adj = lo + (n1_neg & MPD_RADIX);
/* (h, l) = if lo >= 2**63 then m'*(hi+1) else m'*hi */
_mpd_mul_words(&h, &l, mprime_rdx, hi-n1_neg);
l = l + n_adj;
@ -80,10 +76,8 @@ _mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
/* At this point t == qest, with q == qest or q == qest+1:
* 1) 0 <= 2**64*hi + lo - qest*MPD_RADIX < 2*MPD_RADIX
*/
/* t = 2**64-1 - qest = 2**64 - (qest+1) */
t = MPD_UINT_MAX - t;
/* (h, l) = 2**64*MPD_RADIX - (qest+1)*MPD_RADIX */
_mpd_mul_words(&h, &l, t, MPD_RADIX);
l = l + lo;
@ -100,25 +94,15 @@ _mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
* b) q := h - t == qest
* c) r := l + MPD_RADIX = r
*/
*q = (h - t);
*r = l + (MPD_RADIX & h);
}
#else
static inline void
_mpd_div_words_r(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo)
{
_mpd_div_words(q, r, hi, lo, MPD_RADIX);
}
#endif
/* Multiply two single base MPD_RADIX words, store result in array w[2]. */
static inline void
_mpd_singlemul(mpd_uint_t w[2], mpd_uint_t u, mpd_uint_t v)
{
mpd_uint_t hi, lo;
_mpd_mul_words(&hi, &lo, u, v);
_mpd_div_words_r(&w[1], &w[0], hi, lo);
}
@ -128,21 +112,17 @@ static inline void
_mpd_mul_2_le2(mpd_uint_t w[4], mpd_uint_t u[2], mpd_uint_t v[2], mpd_ssize_t m)
{
mpd_uint_t hi, lo;
_mpd_mul_words(&hi, &lo, u[0], v[0]);
_mpd_div_words_r(&w[1], &w[0], hi, lo);
_mpd_mul_words(&hi, &lo, u[1], v[0]);
lo = w[1] + lo;
if (lo < w[1]) hi++;
_mpd_div_words_r(&w[2], &w[1], hi, lo);
if (m == 1) return;
_mpd_mul_words(&hi, &lo, u[0], v[1]);
lo = w[1] + lo;
if (lo < w[1]) hi++;
_mpd_div_words_r(&w[3], &w[1], hi, lo);
_mpd_mul_words(&hi, &lo, u[1], v[1]);
lo = w[2] + lo;
if (lo < w[2]) hi++;
@ -151,7 +131,6 @@ _mpd_mul_2_le2(mpd_uint_t w[4], mpd_uint_t u[2], mpd_uint_t v[2], mpd_ssize_t m)
_mpd_div_words_r(&w[3], &w[2], hi, lo);
}
/*
* Test if all words from data[len-1] to data[0] are zero. If len is 0, nothing
* is tested and the coefficient is regarded as "all zero".
@ -178,6 +157,5 @@ _mpd_isallnine(const mpd_uint_t *data, mpd_ssize_t len)
return 1;
}
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
#endif /* BASEARITH_H */

View file

@ -3,41 +3,35 @@
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
/* clang-format off */
/* Check if n is a power of 2. */
/*
* Check if 𝑛 is a power of 2.
*/
static inline int
ispower2(mpd_size_t n)
{
return n != 0 && (n & (n-1)) == 0;
}
#if defined(ANSI)
#error oh no
/*
* Return the most significant bit position of n from 0 to 31 (63).
* Assumptions: n != 0.
* Returns most significant bit position of 𝑛.
* Assumptions: 𝑛 0
*/
static inline int
mpd_bsr(mpd_size_t n)
{
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
return __builtin_clzll(n) ^ (sizeof(long long) * CHAR_BIT - 1);
#else
int pos = 0;
mpd_size_t tmp;
#ifdef CONFIG_64
tmp = n >> 32;
if (tmp != 0) { n = tmp; pos += 32; }
#endif
tmp = n >> 16;
if (tmp != 0) { n = tmp; pos += 16; }
tmp = n >> 8;
if (tmp != 0) { n = tmp; pos += 8; }
tmp = n >> 4;
if (tmp != 0) { n = tmp; pos += 4; }
tmp = n >> 2;
if (tmp != 0) { n = tmp; pos += 2; }
tmp = n >> 1;
if (tmp != 0) { n = tmp; pos += 1; }
tmp = n >> 32; if (tmp != 0) { n = tmp; pos += 32; }
tmp = n >> 16; if (tmp != 0) { n = tmp; pos += 16; }
tmp = n >> 8; if (tmp != 0) { n = tmp; pos += 8; }
tmp = n >> 4; if (tmp != 0) { n = tmp; pos += 4; }
tmp = n >> 2; if (tmp != 0) { n = tmp; pos += 2; }
tmp = n >> 1; if (tmp != 0) { n = tmp; pos += 1; }
return pos + (int)n - 1;
#endif
}
/*
@ -47,9 +41,10 @@ mpd_bsr(mpd_size_t n)
static inline int
mpd_bsf(mpd_size_t n)
{
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
return __builtin_ctzll(n);
#else
int pos;
#ifdef CONFIG_64
pos = 63;
if (n & 0x00000000FFFFFFFFULL) { pos -= 32; } else { n >>= 32; }
if (n & 0x000000000000FFFFULL) { pos -= 16; } else { n >>= 16; }
@ -57,104 +52,8 @@ mpd_bsf(mpd_size_t n)
if (n & 0x000000000000000FULL) { pos -= 4; } else { n >>= 4; }
if (n & 0x0000000000000003ULL) { pos -= 2; } else { n >>= 2; }
if (n & 0x0000000000000001ULL) { pos -= 1; }
#else
pos = 31;
if (n & 0x000000000000FFFFUL) { pos -= 16; } else { n >>= 16; }
if (n & 0x00000000000000FFUL) { pos -= 8; } else { n >>= 8; }
if (n & 0x000000000000000FUL) { pos -= 4; } else { n >>= 4; }
if (n & 0x0000000000000003UL) { pos -= 2; } else { n >>= 2; }
if (n & 0x0000000000000001UL) { pos -= 1; }
#endif
return pos;
}
/* END ANSI */
#elif defined(ASM)
/*
* Bit scan reverse. Assumptions: a != 0.
*/
static inline int
mpd_bsr(mpd_size_t a)
{
mpd_size_t retval;
__asm__ (
#ifdef CONFIG_64
"bsrq %1, %0\n\t"
#else
"bsr %1, %0\n\t"
#endif
:"=r" (retval)
:"r" (a)
:"cc"
);
return (int)retval;
}
/*
* Bit scan forward. Assumptions: a != 0.
*/
static inline int
mpd_bsf(mpd_size_t a)
{
mpd_size_t retval;
__asm__ (
#ifdef CONFIG_64
"bsfq %1, %0\n\t"
#else
"bsf %1, %0\n\t"
#endif
:"=r" (retval)
:"r" (a)
:"cc"
);
return (int)retval;
}
/* END ASM */
#elif defined(MASM)
#include <intrin.h>
/*
* Bit scan reverse. Assumptions: a != 0.
*/
static inline int __cdecl
mpd_bsr(mpd_size_t a)
{
unsigned long retval;
#ifdef CONFIG_64
_BitScanReverse64(&retval, a);
#else
_BitScanReverse(&retval, a);
#endif
return (int)retval;
}
/*
* Bit scan forward. Assumptions: a != 0.
*/
static inline int __cdecl
mpd_bsf(mpd_size_t a)
{
unsigned long retval;
#ifdef CONFIG_64
_BitScanForward64(&retval, a);
#else
_BitScanForward(&retval, a);
#endif
return (int)retval;
}
/* END MASM (_MSC_VER) */
#else
#error "missing preprocessor definitions"
#endif /* BSR/BSF */
#endif /* BITS_H */

View file

@ -36,86 +36,45 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
#if defined(CONFIG_64)
/* number-theory.c */
const mpd_uint_t mpd_moduli[3] = {
18446744069414584321ULL, 18446744056529682433ULL, 18446742974197923841ULL
};
const mpd_uint_t mpd_roots[3] = {7ULL, 10ULL, 19ULL};
/* number-theory.c */
const mpd_uint_t mpd_moduli[3] = {
18446744069414584321ULL, 18446744056529682433ULL, 18446742974197923841ULL
};
const mpd_uint_t mpd_roots[3] = {7ULL, 10ULL, 19ULL};
/* crt.c */
const mpd_uint_t INV_P1_MOD_P2 = 18446744055098026669ULL;
const mpd_uint_t INV_P1P2_MOD_P3 = 287064143708160ULL;
const mpd_uint_t LH_P1P2 = 18446744052234715137ULL; /* (P1*P2) % 2^64 */
const mpd_uint_t UH_P1P2 = 18446744052234715141ULL; /* (P1*P2) / 2^64 */
/* crt.c */
const mpd_uint_t INV_P1_MOD_P2 = 18446744055098026669ULL;
const mpd_uint_t INV_P1P2_MOD_P3 = 287064143708160ULL;
const mpd_uint_t LH_P1P2 = 18446744052234715137ULL; /* (P1*P2) % 2^64 */
const mpd_uint_t UH_P1P2 = 18446744052234715141ULL; /* (P1*P2) / 2^64 */
/* transpose.c */
const mpd_size_t mpd_bits[64] = {
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608,
16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,
2147483648ULL, 4294967296ULL, 8589934592ULL, 17179869184ULL, 34359738368ULL,
68719476736ULL, 137438953472ULL, 274877906944ULL, 549755813888ULL,
1099511627776ULL, 2199023255552ULL, 4398046511104, 8796093022208ULL,
17592186044416ULL, 35184372088832ULL, 70368744177664ULL, 140737488355328ULL,
281474976710656ULL, 562949953421312ULL, 1125899906842624ULL,
2251799813685248ULL, 4503599627370496ULL, 9007199254740992ULL,
18014398509481984ULL, 36028797018963968ULL, 72057594037927936ULL,
144115188075855872ULL, 288230376151711744ULL, 576460752303423488ULL,
1152921504606846976ULL, 2305843009213693952ULL, 4611686018427387904ULL,
9223372036854775808ULL
};
/* transpose.c */
const mpd_size_t mpd_bits[64] = {
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608,
16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,
2147483648ULL, 4294967296ULL, 8589934592ULL, 17179869184ULL, 34359738368ULL,
68719476736ULL, 137438953472ULL, 274877906944ULL, 549755813888ULL,
1099511627776ULL, 2199023255552ULL, 4398046511104, 8796093022208ULL,
17592186044416ULL, 35184372088832ULL, 70368744177664ULL, 140737488355328ULL,
281474976710656ULL, 562949953421312ULL, 1125899906842624ULL,
2251799813685248ULL, 4503599627370496ULL, 9007199254740992ULL,
18014398509481984ULL, 36028797018963968ULL, 72057594037927936ULL,
144115188075855872ULL, 288230376151711744ULL, 576460752303423488ULL,
1152921504606846976ULL, 2305843009213693952ULL, 4611686018427387904ULL,
9223372036854775808ULL
};
/* mpdecimal.c */
const mpd_uint_t mpd_pow10[MPD_RDIGITS+1] = {
1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,
10000000000ULL,100000000000ULL,1000000000000ULL,10000000000000ULL,
100000000000000ULL,1000000000000000ULL,10000000000000000ULL,
100000000000000000ULL,1000000000000000000ULL,10000000000000000000ULL
};
/* mpdecimal.c */
const mpd_uint_t mpd_pow10[MPD_RDIGITS+1] = {
1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,
10000000000ULL,100000000000ULL,1000000000000ULL,10000000000000ULL,
100000000000000ULL,1000000000000000ULL,10000000000000000ULL,
100000000000000000ULL,1000000000000000000ULL,10000000000000000000ULL
};
/* magic number for constant division by MPD_RADIX */
const mpd_uint_t mprime_rdx = 15581492618384294730ULL;
#elif defined(CONFIG_32)
/* number-theory.c */
const mpd_uint_t mpd_moduli[3] = {2113929217UL, 2013265921UL, 1811939329UL};
const mpd_uint_t mpd_roots[3] = {5UL, 31UL, 13UL};
/* PentiumPro modular multiplication: These constants have to be loaded as
* 80 bit long doubles, which are not supported by certain compilers. */
const uint32_t mpd_invmoduli[3][3] = {
{4293885170U, 2181570688U, 16352U}, /* ((long double) 1 / 2113929217UL) */
{1698898177U, 2290649223U, 16352U}, /* ((long double) 1 / 2013265921UL) */
{2716021846U, 2545165803U, 16352U} /* ((long double) 1 / 1811939329UL) */
};
const float MPD_TWO63 = 9223372036854775808.0; /* 2^63 */
/* crt.c */
const mpd_uint_t INV_P1_MOD_P2 = 2013265901UL;
const mpd_uint_t INV_P1P2_MOD_P3 = 54UL;
const mpd_uint_t LH_P1P2 = 4127195137UL; /* (P1*P2) % 2^32 */
const mpd_uint_t UH_P1P2 = 990904320UL; /* (P1*P2) / 2^32 */
/* transpose.c */
const mpd_size_t mpd_bits[32] = {
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384,
32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608,
16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824,
2147483648UL
};
/* mpdecimal.c */
const mpd_uint_t mpd_pow10[MPD_RDIGITS+1] = {
1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000
};
#else
#error "CONFIG_64 or CONFIG_32 must be defined."
#endif
/* magic number for constant division by MPD_RADIX */
const mpd_uint_t mprime_rdx = 15581492618384294730ULL;
const char *mpd_round_string[MPD_ROUND_GUARD] = {
"ROUND_UP", /* round away from 0 */

View file

@ -3,35 +3,12 @@
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
/* choice of optimized functions */
#if defined(CONFIG_64)
/* x64 */
#define MULMOD(a, b) x64_mulmod(a, b, umod)
#define MULMOD2C(a0, a1, w) x64_mulmod2c(a0, a1, w, umod)
#define MULMOD2(a0, b0, a1, b1) x64_mulmod2(a0, b0, a1, b1, umod)
#define POWMOD(base, exp) x64_powmod(base, exp, umod)
#define SETMODULUS(modnum) std_setmodulus(modnum, &umod)
#define SIZE3_NTT(x0, x1, x2, w3table) std_size3_ntt(x0, x1, x2, w3table, umod)
#elif defined(PPRO)
/* PentiumPro (or later) gcc inline asm */
#define MULMOD(a, b) ppro_mulmod(a, b, &dmod, dinvmod)
#define MULMOD2C(a0, a1, w) ppro_mulmod2c(a0, a1, w, &dmod, dinvmod)
#define MULMOD2(a0, b0, a1, b1) ppro_mulmod2(a0, b0, a1, b1, &dmod, dinvmod)
#define POWMOD(base, exp) ppro_powmod(base, exp, &dmod, dinvmod)
#define SETMODULUS(modnum) ppro_setmodulus(modnum, &umod, &dmod, dinvmod)
#define SIZE3_NTT(x0, x1, x2, w3table) ppro_size3_ntt(x0, x1, x2, w3table, umod, &dmod, dinvmod)
#else
/* ANSI C99 */
#define MULMOD(a, b) std_mulmod(a, b, umod)
#define MULMOD2C(a0, a1, w) std_mulmod2c(a0, a1, w, umod)
#define MULMOD2(a0, b0, a1, b1) std_mulmod2(a0, b0, a1, b1, umod)
#define POWMOD(base, exp) std_powmod(base, exp, umod)
#define SETMODULUS(modnum) std_setmodulus(modnum, &umod)
#define SIZE3_NTT(x0, x1, x2, w3table) std_size3_ntt(x0, x1, x2, w3table, umod)
#endif
#define MULMOD(a, b) x64_mulmod(a, b, umod)
#define MULMOD2C(a0, a1, w) x64_mulmod2c(a0, a1, w, umod)
#define MULMOD2(a0, b0, a1, b1) x64_mulmod2(a0, b0, a1, b1, umod)
#define POWMOD(base, exp) x64_powmod(base, exp, umod)
#define SETMODULUS(modnum) std_setmodulus(modnum, &umod)
#define SIZE3_NTT(x0, x1, x2, w3table) std_size3_ntt(x0, x1, x2, w3table, umod)
/* PentiumPro (or later) gcc inline asm */
extern const float MPD_TWO63;
@ -49,11 +26,4 @@ extern const mpd_uint_t INV_P1P2_MOD_P3;
extern const mpd_uint_t LH_P1P2;
extern const mpd_uint_t UH_P1P2;
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
#endif /* CONSTANTS_H */

View file

@ -38,14 +38,14 @@ Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
void
mpd_dflt_traphandler(mpd_context_t *ctx UNUSED)
mpd_dflt_traphandler(mpd_context_t *ctx)
{
(void)ctx;
raise(SIGFPE);
}
void (* mpd_traphandler)(mpd_context_t *) = mpd_dflt_traphandler;
/* Set guaranteed minimum number of coefficient words. The function may
be used once at program start. Setting MPD_MINALLOC to out-of-bounds
values is a catastrophic error, so in that case the function exits rather
@ -54,7 +54,6 @@ void
mpd_setminalloc(mpd_ssize_t n)
{
static int minalloc_is_set = 0;
if (minalloc_is_set) {
mpd_err_warn("mpd_setminalloc: ignoring request to set "
"MPD_MINALLOC a second time\n");
@ -71,18 +70,14 @@ void
mpd_init(mpd_context_t *ctx, mpd_ssize_t prec)
{
mpd_ssize_t ideal_minalloc;
mpd_defaultcontext(ctx);
if (!mpd_qsetprec(ctx, prec)) {
mpd_addstatus_raise(ctx, MPD_Invalid_context);
return;
}
ideal_minalloc = 2 * ((prec+MPD_RDIGITS-1) / MPD_RDIGITS);
if (ideal_minalloc < MPD_MINALLOC_MIN) ideal_minalloc = MPD_MINALLOC_MIN;
if (ideal_minalloc > MPD_MINALLOC_MAX) ideal_minalloc = MPD_MINALLOC_MAX;
mpd_setminalloc(ideal_minalloc);
}
@ -134,7 +129,6 @@ mpd_ieee_context(mpd_context_t *ctx, int bits)
if (bits <= 0 || bits > MPD_IEEE_CONTEXT_MAX_BITS || bits % 32) {
return -1;
}
ctx->prec = 9 * (bits/32) - 2;
ctx->emax = 3 * ((mpd_ssize_t)1<<(bits/16+3));
ctx->emin = 1 - ctx->emax;
@ -144,7 +138,6 @@ mpd_ieee_context(mpd_context_t *ctx, int bits)
ctx->newtrap=0;
ctx->clamp=1;
ctx->allcr=1;
return 0;
}
@ -196,7 +189,6 @@ mpd_getcr(const mpd_context_t *ctx)
return ctx->allcr;
}
int
mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec)
{
@ -277,7 +269,6 @@ mpd_qsetcr(mpd_context_t *ctx, int c)
return 1;
}
void
mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags)
{

View file

@ -44,8 +44,8 @@ Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
/* Bignum: Fast convolution using the Number Theoretic Transform. Used for
the multiplication of very large coefficients. */
/* Bignum: Fast convolution using the Number Theoretic Transform.
Used for the multiplication of very large coefficients. */
/* Convolute the data in c1 and c2. Result is in c1. */
@ -54,17 +54,10 @@ fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum)
{
int (*fnt)(mpd_uint_t *, mpd_size_t, int);
int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_uint_t n_inv, umod;
mpd_size_t i;
SETMODULUS(modnum);
n_inv = POWMOD(n, (umod-2));
if (ispower2(n)) {
if (n > SIX_STEP_THRESHOLD) {
fnt = six_step_fnt;
@ -79,7 +72,6 @@ fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum)
fnt = four_step_fnt;
inv_fnt = inv_four_step_fnt;
}
if (!fnt(c1, n, modnum)) {
return 0;
}
@ -95,7 +87,6 @@ fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum)
c1[i] = x0;
c1[i+1] = x1;
}
if (!inv_fnt(c1, n, modnum)) {
return 0;
}
@ -111,7 +102,6 @@ fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum)
c1[i+2] = x2;
c1[i+3] = x3;
}
return 1;
}
@ -121,17 +111,10 @@ fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum)
{
int (*fnt)(mpd_uint_t *, mpd_size_t, int);
int (*inv_fnt)(mpd_uint_t *, mpd_size_t, int);
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_uint_t n_inv, umod;
mpd_size_t i;
SETMODULUS(modnum);
n_inv = POWMOD(n, (umod-2));
if (ispower2(n)) {
if (n > SIX_STEP_THRESHOLD) {
fnt = six_step_fnt;
@ -146,7 +129,6 @@ fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum)
fnt = four_step_fnt;
inv_fnt = inv_four_step_fnt;
}
if (!fnt(c1, n, modnum)) {
return 0;
}
@ -157,7 +139,6 @@ fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum)
c1[i] = x0;
c1[i+1] = x1;
}
if (!inv_fnt(c1, n, modnum)) {
return 0;
}
@ -173,6 +154,5 @@ fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum)
c1[i+2] = x2;
c1[i+3] = x3;
}
return 1;
}

View file

@ -1,16 +1,10 @@
#ifndef CONVOLUTE_H
#define CONVOLUTE_H
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
#define SIX_STEP_THRESHOLD 4096
int fnt_convolute(mpd_uint_t *c1, mpd_uint_t *c2, mpd_size_t n, int modnum);
int fnt_autoconvolute(mpd_uint_t *c1, mpd_size_t n, int modnum);
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
int fnt_convolute(mpd_uint_t *, mpd_uint_t *, mpd_size_t, int);
int fnt_autoconvolute(mpd_uint_t *, mpd_size_t, int);
#endif

View file

@ -38,23 +38,18 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
/* Bignum: Chinese Remainder Theorem, extends the maximum transform length. */
/* Multiply P1P2 by v, store result in w. */
static inline void
_crt_mulP1P2_3(mpd_uint_t w[3], mpd_uint_t v)
{
mpd_uint_t hi1, hi2, lo;
_mpd_mul_words(&hi1, &lo, LH_P1P2, v);
w[0] = lo;
_mpd_mul_words(&hi2, &lo, UH_P1P2, v);
lo = hi1 + lo;
if (lo < hi1) hi2++;
w[1] = lo;
w[2] = hi2;
}
@ -65,15 +60,12 @@ _crt_add3(mpd_uint_t w[3], mpd_uint_t v[3])
{
mpd_uint_t carry;
mpd_uint_t s;
s = w[0] + v[0];
carry = (s < w[0]);
w[0] = s;
s = w[1] + (v[1] + carry);
carry = (s < w[1]);
w[1] = s;
w[2] = w[2] + (v[2] + carry);
}
@ -83,21 +75,17 @@ _crt_div3(mpd_uint_t *w, const mpd_uint_t *u, mpd_uint_t v)
{
mpd_uint_t r1 = u[2];
mpd_uint_t r2;
if (r1 < v) {
w[2] = 0;
}
else {
_mpd_div_word(&w[2], &r1, u[2], v); /* GCOV_NOT_REACHED */
}
_mpd_div_words(&w[1], &r2, r1, u[1], v);
_mpd_div_words(&w[0], &r1, r2, u[0], v);
return r1;
}
/*
* Chinese Remainder Theorem:
* Algorithm from Joerg Arndt, "Matters Computational",
@ -138,45 +126,32 @@ crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t rsize)
{
mpd_uint_t p1 = mpd_moduli[P1];
mpd_uint_t umod;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_uint_t a1, a2, a3;
mpd_uint_t s;
mpd_uint_t z[3], t[3];
mpd_uint_t carry[3] = {0,0,0};
mpd_uint_t hi, lo;
mpd_size_t i;
for (i = 0; i < rsize; i++) {
a1 = x1[i];
a2 = x2[i];
a3 = x3[i];
SETMODULUS(P2);
s = ext_submod(a2, a1, umod);
s = MULMOD(s, INV_P1_MOD_P2);
_mpd_mul_words(&hi, &lo, s, p1);
lo = lo + a1;
if (lo < a1) hi++;
SETMODULUS(P3);
s = dw_submod(a3, hi, lo, umod);
s = MULMOD(s, INV_P1P2_MOD_P3);
z[0] = lo;
z[1] = hi;
z[2] = 0;
_crt_mulP1P2_3(t, s);
_crt_add3(z, t);
_crt_add3(carry, z);
x1[i] = _crt_div3(carry, carry, MPD_RADIX);
}
assert(carry[0] == 0 && carry[1] == 0 && carry[2] == 0);
}

View file

@ -4,10 +4,8 @@
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
void crt3(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_size_t nmemb);
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
#endif

View file

@ -39,10 +39,8 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
/* Bignum: The actual transform routine (decimation in frequency). */
/*
* Generate index pairs (x, bitreverse(x)) and carry out the permutation.
* n must be a power of two.
@ -55,7 +53,6 @@ bitreverse_permute(mpd_uint_t a[], mpd_size_t n)
mpd_size_t x = 0;
mpd_size_t r = 0;
mpd_uint_t t;
do { /* Invariant: r = bitreverse(x) */
if (r > x) {
t = a[x];
@ -72,105 +69,68 @@ bitreverse_permute(mpd_uint_t a[], mpd_size_t n)
} while (x < n);
}
/* Fast Number Theoretic Transform, decimation in frequency. */
void
fnt_dif2(mpd_uint_t a[], mpd_size_t n, struct fnt_params *tparams)
{
mpd_uint_t *wtable = tparams->wtable;
mpd_uint_t umod;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_uint_t u0, u1, v0, v1;
mpd_uint_t w, w0, w1, wstep;
mpd_size_t m, mhalf;
mpd_size_t j, r;
assert(ispower2(n));
assert(n >= 4);
SETMODULUS(tparams->modnum);
/* m == n */
mhalf = n / 2;
for (j = 0; j < mhalf; j += 2) {
w0 = wtable[j];
w1 = wtable[j+1];
u0 = a[j];
v0 = a[j+mhalf];
u1 = a[j+1];
v1 = a[j+1+mhalf];
a[j] = addmod(u0, v0, umod);
v0 = submod(u0, v0, umod);
a[j+1] = addmod(u1, v1, umod);
v1 = submod(u1, v1, umod);
MULMOD2(&v0, w0, &v1, w1);
a[j+mhalf] = v0;
a[j+1+mhalf] = v1;
}
wstep = 2;
for (m = n/2; m >= 2; m>>=1, wstep<<=1) {
mhalf = m / 2;
/* j == 0 */
for (r = 0; r < n; r += 2*m) {
u0 = a[r];
v0 = a[r+mhalf];
u1 = a[m+r];
v1 = a[m+r+mhalf];
a[r] = addmod(u0, v0, umod);
v0 = submod(u0, v0, umod);
a[m+r] = addmod(u1, v1, umod);
v1 = submod(u1, v1, umod);
a[r+mhalf] = v0;
a[m+r+mhalf] = v1;
}
for (j = 1; j < mhalf; j++) {
w = wtable[j*wstep];
for (r = 0; r < n; r += 2*m) {
u0 = a[r+j];
v0 = a[r+j+mhalf];
u1 = a[m+r+j];
v1 = a[m+r+j+mhalf];
a[r+j] = addmod(u0, v0, umod);
v0 = submod(u0, v0, umod);
a[m+r+j] = addmod(u1, v1, umod);
v1 = submod(u1, v1, umod);
MULMOD2C(&v0, &v1, w);
a[r+j+mhalf] = v0;
a[m+r+j+mhalf] = v1;
}
}
}
bitreverse_permute(a, n);
}

View file

@ -2,13 +2,7 @@
#define DIF_RADIX2_H
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
#include "third_party/python/Modules/_decimal/libmpdec/numbertheory.h"
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
void fnt_dif2(mpd_uint_t a[], mpd_size_t n, struct fnt_params *tparams);
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
void fnt_dif2(mpd_uint_t[], mpd_size_t, struct fnt_params *);
#endif

View file

@ -40,25 +40,20 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
/* Bignum: Fast transform for medium-sized coefficients. */
/* forward transform, sign = -1 */
int
std_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
{
struct fnt_params *tparams;
assert(ispower2(n));
assert(n >= 4);
assert(n <= 3*MPD_MAXTRANSFORM_2N);
if ((tparams = _mpd_init_fnt_params(n, -1, modnum)) == NULL) {
return 0;
}
fnt_dif2(a, n, tparams);
mpd_free(tparams);
return 1;
}
@ -68,16 +63,13 @@ int
std_inv_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
{
struct fnt_params *tparams;
assert(ispower2(n));
assert(n >= 4);
assert(n <= 3*MPD_MAXTRANSFORM_2N);
if ((tparams = _mpd_init_fnt_params(n, 1, modnum)) == NULL) {
return 0;
}
fnt_dif2(a, n, tparams);
mpd_free(tparams);
return 1;
}

View file

@ -1,14 +1,10 @@
#ifndef FNT_H
#define FNT_H
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
int std_fnt(mpd_uint_t a[], mpd_size_t n, int modnum);
int std_inv_fnt(mpd_uint_t a[], mpd_size_t n, int modnum);
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
int std_fnt(mpd_uint_t[], mpd_size_t, int);
int std_inv_fnt(mpd_uint_t[], mpd_size_t, int);
#endif

View file

@ -40,12 +40,261 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
/* Bignum: Cache efficient Matrix Fourier Transform for arrays of the
form 3 * 2**n (See literature/matrix-transform.txt). */
/*
Cache Efficient Matrix Fourier Transform
for arrays of form 3×2
#ifndef PPRO
The Matrix Fourier Transform
In libmpdec, the Matrix Fourier Transform [1] is called four-step
transform after a variant that appears in [2]. The algorithm requires
that the input array can be viewed as an R*C matrix.
All operations are done modulo p. For readability, the proofs drop all
instances of (mod p).
Algorithm four-step (forward transform)
a := input array
d := len(a) = R * C
p := prime
w := primitive root of unity of the prime field
r := w**((p-1)/d)
A := output array
1) Apply a length R FNT to each column.
2) Multiply each matrix element (addressed by j*C+m) by r**(j*m).
3) Apply a length C FNT to each row.
4) Transpose the matrix.
Proof (forward transform)
The algorithm can be derived starting from the regular definition of
the finite-field transform of length d:
d-1
,
\
A[k] = | a[l] × r**(k × l)
/
`
l = 0
The sum can be rearranged into the sum of the sums of columns:
C-1 R-1
, ,
\ \
= | | a[i × C + j] × r**(k × (i × C + j))
/ /
` `
j = 0 i = 0
Extracting a constant from the inner sum:
C-1 R-1
, ,
\ \
= | rᵏ×j × | a[i × C + j] × r**(k × i × C)
/ /
` `
j = 0 i = 0
Without any loss of generality, let k = n × R + m,
where n < C and m < R:
C-1 R-1
, ,
\ \
A[n×R+m] = | r**(R×n×j) × r**(m×j) × | a[i×C+j] × r**(R×C×n×i) × r**(C×m×i)
/ /
` `
j = 0 i = 0
Since r = w ** ((p-1) / (R×C)):
a) r**(R×C×n×i) = w**((p-1)×n×i) = 1
b) r**(C×m×i) = w**((p-1) / R) ** (m×i) = r_R ** (m×i)
c) r**(R×n×j) = w**((p-1) / C) ** (n×j) = r_C ** (n×j)
r_R := root of the subfield of length R.
r_C := root of the subfield of length C.
C-1 R-1
, ,
\ \
A[n×R+m] = | r_C**(n×j) × [ r**(m×j) × | a[i×C+j] × r_R**(m×i) ]
/ ^ /
` | ` 1) transform the columns
j = 0 | i = 0
^ |
| `-- 2) multiply
|
`-- 3) transform the rows
Note that the entire RHS is a function of n and m and that the results
for each pair (n, m) are stored in Fortran order.
Let the term in square brackets be 𝑓(m, j). Step 1) and 2) precalculate
the term for all (m, j). After that, the original matrix is now a lookup
table with the mth element in the jth column at location m × C + j.
Let the complete RHS be g(m, n). Step 3) does an in-place transform of
length n on all rows. After that, the original matrix is now a lookup
table with the mth element in the nth column at location m × C + n.
But each (m, n) pair should be written to location n × R + m. Therefore,
step 4) transposes the result of step 3).
Algorithm four-step (inverse transform)
A := input array
d := len(A) = R × C
p := prime
d := d² # inverse of d
w := primitive root of unity of the prime field
r := w**((p-1)/d) # root of the subfield
r := w**((p-1) - (p-1)/d) # inverse of r
a := output array
0) View the matrix as a C×R matrix.
1) Transpose the matrix, producing an R×C matrix.
2) Apply a length C FNT to each row.
3) Multiply each matrix element (addressed by i×C+n) by r**(i×n).
4) Apply a length R FNT to each column.
Proof (inverse transform)
The algorithm can be derived starting from the regular definition of
the finite-field inverse transform of length d:
d-1
,
\
a[k] = d × | A[l] × r ** (k × l)
/
`
l = 0
The sum can be rearranged into the sum of the sums of columns. Note
that at this stage we still have a C*R matrix, so C denotes the number
of rows:
R-1 C-1
, ,
\ \
= d × | | a[j × R + i] × r ** (k × (j × R + i))
/ /
` `
i = 0 j = 0
Extracting a constant from the inner sum:
R-1 C-1
, ,
\ \
= d × | r ** (k×i) × | a[j × R + i] × r ** (k × j × R)
/ /
` `
i = 0 j = 0
Without any loss of generality, let k = m * C + n,
where m < R and n < C:
R-1 C-1
, ,
\ \
A[m×C+n] = d × | r ** (C×m×i) × r ** (n×i) × | a[j×R+i] × r ** (R×C×m×j) × r ** (R×n×j)
/ /
` `
i = 0 j = 0
Since r = w**((p-1) - (p-1)/d) and d = R×C:
a) r ** (R×C×m×j) = w**((p-1)×R×C×m×j - (p-1)×m×j) = 1
b) r ** (C×m×i) = w**((p-1)×C - (p-1)/R) ** (m×i) = r_R ** (m×i)
c) r ** (R×n×j) = r_C ** (n×j)
d) d = d² = (R×C)² = R² × C² = R × C
r_R := inverse of the root of the subfield of length R.
r_C := inverse of the root of the subfield of length C.
R := inverse of R
C := inverse of C
R-1 C-1
, , 2) transform the rows of a^T
\ \
A[m×C+n] = R × | r_R ** (m×i) × [ r ** (n×i) × C × | a[j×R+i] × r_C ** (n×j) ]
/ ^ / ^
` | ` |
i = 0 | j = 0 |
^ | ` 1) Transpose input matrix
| ` 3) multiply to address elements by
| i × C + j
` 3) transform the columns
Note that the entire RHS is a function of m and n and that the results
for each pair (m, n) are stored in C order.
Let the term in square brackets be 𝑓(n, i). Without step 1), the sum
would perform a length C transform on the columns of the input matrix.
This is a) inefficient and b) the results are needed in C order, so
step 1) exchanges rows and columns.
Step 2) and 3) precalculate 𝑓(n, i) for all (n, i). After that, the
original matrix is now a lookup table with the ith element in the nth
column at location i × C + n.
Let the complete RHS be g(m, n). Step 4) does an in-place transform of
length m on all columns. After that, the original matrix is now a lookup
table with the mth element in the nth column at location m × C + n,
which means that all A[k] = A[m × C + n] are in the correct order.
[1] Joerg Arndt: "Matters Computational"
http://www.jjj.de/fxt/
[2] David H. Bailey: FFTs in External or Hierarchical Memory
http://crd.lbl.gov/~dhbailey/dhbpapers/
*/
static inline void
std_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3,
mpd_uint_t w3table[3], mpd_uint_t umod)
@ -53,90 +302,32 @@ std_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3,
mpd_uint_t r1, r2;
mpd_uint_t w;
mpd_uint_t s, tmp;
/* k = 0 -> w = 1 */
s = *x1;
s = addmod(s, *x2, umod);
s = addmod(s, *x3, umod);
r1 = s;
/* k = 1 */
s = *x1;
w = w3table[1];
tmp = MULMOD(*x2, w);
s = addmod(s, tmp, umod);
w = w3table[2];
tmp = MULMOD(*x3, w);
s = addmod(s, tmp, umod);
r2 = s;
/* k = 2 */
s = *x1;
w = w3table[2];
tmp = MULMOD(*x2, w);
s = addmod(s, tmp, umod);
w = w3table[1];
tmp = MULMOD(*x3, w);
s = addmod(s, tmp, umod);
*x3 = s;
*x2 = r2;
*x1 = r1;
}
#else /* PPRO */
static inline void
ppro_size3_ntt(mpd_uint_t *x1, mpd_uint_t *x2, mpd_uint_t *x3, mpd_uint_t w3table[3],
mpd_uint_t umod, double *dmod, uint32_t dinvmod[3])
{
mpd_uint_t r1, r2;
mpd_uint_t w;
mpd_uint_t s, tmp;
/* k = 0 -> w = 1 */
s = *x1;
s = addmod(s, *x2, umod);
s = addmod(s, *x3, umod);
r1 = s;
/* k = 1 */
s = *x1;
w = w3table[1];
tmp = ppro_mulmod(*x2, w, dmod, dinvmod);
s = addmod(s, tmp, umod);
w = w3table[2];
tmp = ppro_mulmod(*x3, w, dmod, dinvmod);
s = addmod(s, tmp, umod);
r2 = s;
/* k = 2 */
s = *x1;
w = w3table[2];
tmp = ppro_mulmod(*x2, w, dmod, dinvmod);
s = addmod(s, tmp, umod);
w = w3table[1];
tmp = ppro_mulmod(*x3, w, dmod, dinvmod);
s = addmod(s, tmp, umod);
*x3 = s;
*x2 = r2;
*x1 = r1;
}
#endif
/* forward transform, sign = -1; transform length = 3 * 2**n */
int
@ -148,25 +339,15 @@ four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
mpd_uint_t kernel, w0, w1, wstep;
mpd_uint_t *s, *p0, *p1, *p2;
mpd_uint_t umod;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_size_t i, k;
assert(n >= 48);
assert(n <= 3*MPD_MAXTRANSFORM_2N);
/* Length R transform on the columns. */
SETMODULUS(modnum);
_mpd_init_w3table(w3table, -1, modnum);
for (p0=a, p1=p0+C, p2=p0+2*C; p0<a+C; p0++,p1++,p2++) {
SIZE3_NTT(p0, p1, p2, w3table);
}
/* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
kernel = _mpd_getkernel(n, -1, modnum);
for (i = 1; i < R; i++) {
@ -182,20 +363,17 @@ four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
a[i*C+k+1] = x1;
}
}
/* Length C transform on the rows. */
for (s = a; s < a+n; s += C) {
if (!six_step_fnt(s, C, modnum)) {
return 0;
}
}
#if 0
/* An unordered transform is sufficient for convolution. */
/* Transpose the matrix. */
transpose_3xpow2(a, R, C);
#endif
return 1;
}
@ -209,30 +387,20 @@ inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
mpd_uint_t kernel, w0, w1, wstep;
mpd_uint_t *s, *p0, *p1, *p2;
mpd_uint_t umod;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_size_t i, k;
assert(n >= 48);
assert(n <= 3*MPD_MAXTRANSFORM_2N);
#if 0
/* An unordered transform is sufficient for convolution. */
/* Transpose the matrix, producing an R*C matrix. */
transpose_3xpow2(a, C, R);
#endif
/* Length C transform on the rows. */
for (s = a; s < a+n; s += C) {
if (!inv_six_step_fnt(s, C, modnum)) {
return 0;
}
}
/* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
SETMODULUS(modnum);
kernel = _mpd_getkernel(n, 1, modnum);
@ -249,13 +417,10 @@ inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
a[i*C+k+1] = x1;
}
}
/* Length R transform on the columns. */
_mpd_init_w3table(w3table, 1, modnum);
for (p0=a, p1=p0+C, p2=p0+2*C; p0<a+C; p0++,p1++,p2++) {
SIZE3_NTT(p0, p1, p2, w3table);
}
return 1;
}

View file

@ -1,14 +1,8 @@
#ifndef FOUR_STEP_H
#define FOUR_STEP_H
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
int four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
int inv_four_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
int four_step_fnt(mpd_uint_t *, mpd_size_t, int);
int inv_four_step_fnt(mpd_uint_t *, mpd_size_t, int);
#endif

View file

@ -70,7 +70,6 @@ _mpd_strneq(const char *s, const char *l, const char *u, size_t n)
}
s++; u++; l++;
}
return 1;
}
@ -79,12 +78,10 @@ strtoexp(const char *s)
{
char *end;
mpd_ssize_t retval;
errno = 0;
retval = mpd_strtossize(s, &end, 10);
if (errno == 0 && !(*s != '\0' && *end == '\0'))
errno = EINVAL;
return retval;
}
@ -206,11 +203,9 @@ mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
const char *dpoint = NULL, *exp = NULL;
size_t digits;
uint8_t sign = MPD_POS;
mpd_set_flags(dec, 0);
dec->len = 0;
dec->exp = 0;
/* sign */
if (*s == '+') {
s++;
@ -220,7 +215,6 @@ mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
sign = MPD_NEG;
s++;
}
if (_mpd_strneq(s, "nan", "NAN", 3)) { /* NaN */
s += 3;
mpd_setspecial(dec, sign, MPD_NAN);
@ -265,7 +259,6 @@ mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
/* scan for start of coefficient, decimal point, indicator, end */
if ((coeff = scan_dpoint_exp(s, &dpoint, &exp, &end)) == NULL)
goto conversion_error;
/* numeric-value: [exponent-part] */
if (exp) {
/* exponent-part */
@ -273,17 +266,15 @@ mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
dec->exp = strtoexp(exp);
if (errno) {
if (!(errno == ERANGE &&
(dec->exp == MPD_SSIZE_MAX ||
dec->exp == MPD_SSIZE_MIN)))
(dec->exp == MPD_SSIZE_MAX ||
dec->exp == MPD_SSIZE_MIN)))
goto conversion_error;
}
}
digits = end - coeff;
digits = end - coeff;
if (dpoint) {
size_t fracdigits = end-dpoint-1;
if (dpoint > coeff) digits--;
if (fracdigits > MPD_MAX_PREC) {
goto conversion_error;
}
@ -304,9 +295,7 @@ mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
dec->exp = MPD_SSIZE_MIN+1;
}
}
_mpd_idiv_word(&q, &r, (mpd_ssize_t)digits, MPD_RDIGITS);
len = (r == 0) ? q : q+1;
if (len == 0) {
goto conversion_error; /* GCOV_NOT_REACHED */
@ -316,13 +305,10 @@ mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
return;
}
dec->len = len;
string_to_coeff(dec->data, coeff, dpoint, (int)r, len);
mpd_setdigits(dec);
mpd_qfinalize(dec, ctx, status);
return;
conversion_error:
/* standard wants a positive NaN */
mpd_seterror(dec, MPD_Conversion_syntax, status);
@ -336,7 +322,6 @@ static inline char *
word_to_string(char *s, mpd_uint_t x, int n, char *dot)
{
switch(n) {
#ifdef CONFIG_64
case 20: EXTRACT_DIGIT(s, x, 10000000000000000000ULL, dot); /* GCOV_NOT_REACHED */
case 19: EXTRACT_DIGIT(s, x, 1000000000000000000ULL, dot);
case 18: EXTRACT_DIGIT(s, x, 100000000000000000ULL, dot);
@ -347,7 +332,6 @@ word_to_string(char *s, mpd_uint_t x, int n, char *dot)
case 13: EXTRACT_DIGIT(s, x, 1000000000000ULL, dot);
case 12: EXTRACT_DIGIT(s, x, 100000000000ULL, dot);
case 11: EXTRACT_DIGIT(s, x, 10000000000ULL, dot);
#endif
case 10: EXTRACT_DIGIT(s, x, 1000000000UL, dot);
case 9: EXTRACT_DIGIT(s, x, 100000000UL, dot);
case 8: EXTRACT_DIGIT(s, x, 10000000UL, dot);
@ -359,7 +343,6 @@ word_to_string(char *s, mpd_uint_t x, int n, char *dot)
case 2: EXTRACT_DIGIT(s, x, 10UL, dot);
default: if (s == dot) *s++ = '.'; *s++ = '0' + (char)x;
}
*s = '\0';
return s;
}
@ -369,13 +352,11 @@ static inline char *
exp_to_string(char *s, mpd_ssize_t x)
{
char sign = '+';
if (x < 0) {
sign = '-';
x = -x;
}
*s++ = sign;
return word_to_string(s, x, mpd_word_digits(x), NULL);
}
@ -572,7 +553,6 @@ _mpd_to_string(char **result, const mpd_t *dec, int flags, mpd_ssize_t dplace)
return -1;
}
if (mpd_isnegative(dec)) {
*cp++ = '-';
}
@ -678,8 +658,6 @@ _mpd_copy_utf8(char dest[5], const char *s)
const uchar *cp = (const uchar *)s;
uchar lb, ub;
int count, i;
if (*cp == 0) {
/* empty string */
dest[0] = '\0';
@ -727,7 +705,6 @@ _mpd_copy_utf8(char dest[5], const char *s)
/* invalid */
goto error;
}
dest[0] = *cp++;
if (*cp < lb || ub < *cp) {
goto error;
@ -740,9 +717,7 @@ _mpd_copy_utf8(char dest[5], const char *s)
dest[i] = *cp++;
}
dest[i] = '\0';
return count;
error:
dest[0] = '\0';
return -1;
@ -787,7 +762,6 @@ mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps)
spec->sep = "";
spec->grouping = "";
/* presume that the first character is a UTF-8 fill character */
if ((n = _mpd_copy_utf8(spec->fill, cp)) < 0) {
return 0;
@ -910,9 +884,8 @@ typedef struct {
static inline void
_mpd_bcopy(char *dest, const char *src, mpd_ssize_t n)
{
while (--n >= 0) {
dest[n] = src[n];
}
/* [jart] just use memmove */
memmove(dest, src, n);
}
static inline void
@ -921,7 +894,6 @@ _mbstr_copy_char(mpd_mbstr_t *dest, const char *src, mpd_ssize_t n)
dest->nbytes += n;
dest->nchars += (n > 0 ? 1 : 0);
dest->cur -= n;
if (dest->data != NULL) {
_mpd_bcopy(dest->data+dest->cur, src, n);
}
@ -933,7 +905,6 @@ _mbstr_copy_ascii(mpd_mbstr_t *dest, const char *src, mpd_ssize_t n)
dest->nbytes += n;
dest->nchars += n;
dest->cur -= n;
if (dest->data != NULL) {
_mpd_bcopy(dest->data+dest->cur, src, n);
}
@ -945,7 +916,6 @@ _mbstr_copy_pad(mpd_mbstr_t *dest, mpd_ssize_t n)
dest->nbytes += n;
dest->nchars += n;
dest->cur -= n;
if (dest->data != NULL) {
char *cp = dest->data + dest->cur;
while (--n >= 0) {
@ -1452,9 +1422,7 @@ mpd_snprint_flags(char *dest, int nmemb, uint32_t flags)
{
char *cp;
int n, j;
assert(nmemb >= MPD_MAX_FLAG_STRING);
*dest = '\0'; cp = dest;
for (j = 0; j < MPD_NUM_FLAGS; j++) {
if (flags & (1U<<j)) {
@ -1463,11 +1431,9 @@ mpd_snprint_flags(char *dest, int nmemb, uint32_t flags)
cp += n; nmemb -= n;
}
}
if (cp != dest) {
*(--cp) = '\0';
}
return (int)(cp-dest);
}
@ -1477,17 +1443,14 @@ mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_strin
{
char *cp;
int n, j;
assert(nmemb >= MPD_MAX_FLAG_LIST);
if (flag_string == NULL) {
flag_string = mpd_flag_string;
}
*dest = '[';
*(dest+1) = '\0';
cp = dest+1;
--nmemb;
for (j = 0; j < MPD_NUM_FLAGS; j++) {
if (flags & (1U<<j)) {
n = snprintf(cp, nmemb, "%s, ", flag_string[j]);
@ -1495,15 +1458,12 @@ mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_strin
cp += n; nmemb -= n;
}
}
/* erase the last ", " */
if (cp != dest+1) {
cp -= 2;
}
*cp++ = ']';
*cp = '\0';
return (int)(cp-dest); /* strlen, without NUL terminator */
}
@ -1514,17 +1474,14 @@ mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_s
char *cp;
int n, j;
int ieee_invalid_done = 0;
assert(nmemb >= MPD_MAX_SIGNAL_LIST);
if (signal_string == NULL) {
signal_string = mpd_signal_string;
}
*dest = '[';
*(dest+1) = '\0';
cp = dest+1;
--nmemb;
for (j = 0; j < MPD_NUM_FLAGS; j++) {
uint32_t f = flags & (1U<<j);
if (f) {
@ -1539,15 +1496,12 @@ mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_s
cp += n; nmemb -= n;
}
}
/* erase the last ", " */
if (cp != dest+1) {
cp -= 2;
}
*cp++ = ']';
*cp = '\0';
return (int)(cp-dest); /* strlen, without NUL terminator */
}
@ -1556,7 +1510,6 @@ void
mpd_fprint(FILE *file, const mpd_t *dec)
{
char *decstring;
decstring = mpd_to_sci(dec, 1);
if (decstring != NULL) {
fprintf(file, "%s\n", decstring);
@ -1571,7 +1524,6 @@ void
mpd_print(const mpd_t *dec)
{
char *decstring;
decstring = mpd_to_sci(dec, 1);
if (decstring != NULL) {
printf("%s\n", decstring);

View file

@ -1,15 +1,9 @@
#ifndef MPALLOC_H
#define MPALLOC_H
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
int mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status);
int mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
int mpd_realloc_dyn(mpd_t *result, mpd_ssize_t size, uint32_t *status);
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
int mpd_switch_to_dyn(mpd_t *, mpd_ssize_t, uint32_t *);
int mpd_switch_to_dyn_zero(mpd_t *, mpd_ssize_t, uint32_t *);
int mpd_realloc_dyn(mpd_t *, mpd_ssize_t, uint32_t *);
#endif

File diff suppressed because it is too large Load diff

View file

@ -5,85 +5,19 @@
#include "libc/limits.h"
#include "libc/stdio/stdio.h"
#include "third_party/python/pyconfig.h"
COSMOPOLITAN_C_START_
/* clang-format off */
#ifdef __cplusplus
extern "C" {
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#define MPD_CLEAR_STDC_LIMIT_MACROS
#endif
#endif
#ifndef __GNUC_STDC_INLINE__
#define __GNUC_STDC_INLINE__ 1
#endif
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
#define UNUSED __attribute__((__unused__))
#else
#define UNUSED
#endif
#if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \
defined(__GNUC__) && __GNUC__ >= 4 && !defined(__INTEL_COMPILER)
#define MPD_PRAGMA(x) _Pragma(x)
#define MPD_HIDE_SYMBOLS_START "GCC visibility push(hidden)"
#define MPD_HIDE_SYMBOLS_END "GCC visibility pop"
#else
#define MPD_PRAGMA(x)
#define MPD_HIDE_SYMBOLS_START
#define MPD_HIDE_SYMBOLS_END
#endif
#define EXTINLINE
/* This header file is internal for the purpose of building _decimal.so.
* All symbols should have local scope in the DSO. */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
/******************************************************************************/
/* Version */
/******************************************************************************/
#define MPD_VERSION "2.4.2"
#define MPD_MAJOR_VERSION 2
#define MPD_MINOR_VERSION 4
#define MPD_MICRO_VERSION 2
#define MPD_VERSION "2.4.2"
#define MPD_VERSION_HEX ((MPD_MAJOR_VERSION << 24) | \
(MPD_MINOR_VERSION << 16) | \
(MPD_MICRO_VERSION << 8))
const char *mpd_version(void);
/******************************************************************************/
/* Configuration */
/******************************************************************************/
#if defined(CONFIG_64) || defined(CONFIG_32)
#error "cannot use CONFIG_64 or CONFIG_32 with UNIVERSAL."
#endif
#if defined(__ppc__)
#define CONFIG_32
#define ANSI
#elif defined(__ppc64__)
#define CONFIG_64
#define ANSI
#elif defined(__i386__)
#define CONFIG_32
#define ANSI
#elif defined(__x86_64__)
#define CONFIG_64
#define ASM
#else
#error "unknown architecture for universal build."
#endif
/* BEGIN CONFIG_64 */
#if defined(CONFIG_64)
/* types for modular and base arithmetic */
#define MPD_UINT_MAX UINT64_MAX
#define MPD_BITS_PER_UINT 64
typedef uint64_t mpd_uint_t; /* unsigned mod type */
@ -97,7 +31,6 @@ typedef size_t mpd_size_t; /* unsigned size type */
typedef int64_t mpd_ssize_t;
#define _mpd_strtossize strtoll
/* decimal arithmetic */
#define MPD_RADIX 10000000000000000000ULL /* 10**19 */
#define MPD_RDIGITS 19
#define MPD_MAX_POW10 19
@ -117,57 +50,6 @@ typedef int64_t mpd_ssize_t;
/* conversion specifiers */
#define PRI_mpd_uint_t PRIu64
#define PRI_mpd_ssize_t PRIi64
/* END CONFIG_64 */
/* BEGIN CONFIG_32 */
#elif defined(CONFIG_32)
/* types for modular and base arithmetic */
#define MPD_UINT_MAX UINT32_MAX
#define MPD_BITS_PER_UINT 32
typedef uint32_t mpd_uint_t; /* unsigned mod type */
#ifndef LEGACY_COMPILER
#define MPD_UUINT_MAX UINT64_MAX
typedef uint64_t mpd_uuint_t; /* double width unsigned mod type */
#endif
#define MPD_SIZE_MAX SIZE_MAX
typedef size_t mpd_size_t; /* unsigned size type */
/* type for dec->len, dec->exp, ctx->prec */
#define MPD_SSIZE_MAX INT32_MAX
#define MPD_SSIZE_MIN INT32_MIN
typedef int32_t mpd_ssize_t;
#define _mpd_strtossize strtol
/* decimal arithmetic */
#define MPD_RADIX 1000000000UL /* 10**9 */
#define MPD_RDIGITS 9
#define MPD_MAX_POW10 9
#define MPD_EXPDIGITS 10 /* MPD_EXPDIGITS <= MPD_RDIGITS+1 */
#define MPD_MAXTRANSFORM_2N 33554432UL /* 2**25 */
#define MPD_MAX_PREC 425000000L
#define MPD_MAX_PREC_LOG2 32
#define MPD_ELIMIT 425000001L
#define MPD_MAX_EMAX 425000000L /* ELIMIT-1 */
#define MPD_MIN_EMIN (-425000000L) /* -EMAX */
#define MPD_MIN_ETINY (MPD_MIN_EMIN-(MPD_MAX_PREC-1))
#define MPD_EXP_INF 1000000001L /* allows for emax=999999999 in the tests */
#define MPD_EXP_CLAMP (-2000000001L) /* allows for emin=-999999999 in the tests */
#define MPD_MAXIMPORT 94444445L /* ceil((2*MPD_MAX_PREC)/MPD_RDIGITS) */
/* conversion specifiers */
#define PRI_mpd_uint_t PRIu32
#define PRI_mpd_ssize_t PRIi32
/* END CONFIG_32 */
#else
#error "define CONFIG_64 or CONFIG_32"
#endif
/* END CONFIG */
#if MPD_SIZE_MAX != MPD_UINT_MAX
#error "unsupported platform: need mpd_size_t == mpd_uint_t"
@ -256,39 +138,35 @@ typedef struct mpd_context_t {
#define MPD_DECIMAL64 64
#define MPD_DECIMAL128 128
#define MPD_MINALLOC_MIN 2
#define MPD_MINALLOC_MAX 64
extern mpd_ssize_t MPD_MINALLOC;
extern void (* mpd_traphandler)(mpd_context_t *);
void mpd_dflt_traphandler(mpd_context_t *);
void mpd_setminalloc(mpd_ssize_t n);
void mpd_init(mpd_context_t *ctx, mpd_ssize_t prec);
void mpd_maxcontext(mpd_context_t *ctx);
void mpd_defaultcontext(mpd_context_t *ctx);
void mpd_basiccontext(mpd_context_t *ctx);
int mpd_ieee_context(mpd_context_t *ctx, int bits);
mpd_ssize_t mpd_getprec(const mpd_context_t *ctx);
mpd_ssize_t mpd_getemax(const mpd_context_t *ctx);
mpd_ssize_t mpd_getemin(const mpd_context_t *ctx);
int mpd_getround(const mpd_context_t *ctx);
uint32_t mpd_gettraps(const mpd_context_t *ctx);
uint32_t mpd_getstatus(const mpd_context_t *ctx);
int mpd_getclamp(const mpd_context_t *ctx);
int mpd_getcr(const mpd_context_t *ctx);
int mpd_qsetprec(mpd_context_t *ctx, mpd_ssize_t prec);
int mpd_qsetemax(mpd_context_t *ctx, mpd_ssize_t emax);
int mpd_qsetemin(mpd_context_t *ctx, mpd_ssize_t emin);
int mpd_qsetround(mpd_context_t *ctx, int newround);
int mpd_qsettraps(mpd_context_t *ctx, uint32_t flags);
int mpd_qsetstatus(mpd_context_t *ctx, uint32_t flags);
int mpd_qsetclamp(mpd_context_t *ctx, int c);
int mpd_qsetcr(mpd_context_t *ctx, int c);
void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
void mpd_setminalloc(mpd_ssize_t);
void mpd_init(mpd_context_t *, mpd_ssize_t);
void mpd_maxcontext(mpd_context_t *);
void mpd_defaultcontext(mpd_context_t *);
void mpd_basiccontext(mpd_context_t *);
int mpd_ieee_context(mpd_context_t *, int);
mpd_ssize_t mpd_getprec(const mpd_context_t *);
mpd_ssize_t mpd_getemax(const mpd_context_t *);
mpd_ssize_t mpd_getemin(const mpd_context_t *);
int mpd_getround(const mpd_context_t *);
uint32_t mpd_gettraps(const mpd_context_t *);
uint32_t mpd_getstatus(const mpd_context_t *);
int mpd_getclamp(const mpd_context_t *);
int mpd_getcr(const mpd_context_t *);
int mpd_qsetprec(mpd_context_t *, mpd_ssize_t);
int mpd_qsetemax(mpd_context_t *, mpd_ssize_t);
int mpd_qsetemin(mpd_context_t *, mpd_ssize_t);
int mpd_qsetround(mpd_context_t *, int);
int mpd_qsettraps(mpd_context_t *, uint32_t);
int mpd_qsetstatus(mpd_context_t *, uint32_t);
int mpd_qsetclamp(mpd_context_t *, int);
int mpd_qsetcr(mpd_context_t *, int);
void mpd_addstatus_raise(mpd_context_t *, uint32_t);
/******************************************************************************/
@ -308,7 +186,6 @@ void mpd_addstatus_raise(mpd_context_t *ctx, uint32_t flags);
#define MPD_CONST_DATA ((uint8_t)128)
#define MPD_DATAFLAGS (MPD_STATIC_DATA|MPD_SHARED_DATA|MPD_CONST_DATA)
/* mpd_t */
typedef struct mpd_t {
uint8_t flags;
mpd_ssize_t exp;
@ -318,7 +195,6 @@ typedef struct mpd_t {
mpd_uint_t *data;
} mpd_t;
typedef unsigned char uchar;
@ -340,388 +216,352 @@ typedef struct mpd_spec_t {
} mpd_spec_t;
/* output to a string */
char *mpd_to_sci(const mpd_t *dec, int fmt);
char *mpd_to_eng(const mpd_t *dec, int fmt);
mpd_ssize_t mpd_to_sci_size(char **res, const mpd_t *dec, int fmt);
mpd_ssize_t mpd_to_eng_size(char **res, const mpd_t *dec, int fmt);
int mpd_validate_lconv(mpd_spec_t *spec);
int mpd_parse_fmt_str(mpd_spec_t *spec, const char *fmt, int caps);
char *mpd_qformat_spec(const mpd_t *dec, const mpd_spec_t *spec, const mpd_context_t *ctx, uint32_t *status);
char *mpd_qformat(const mpd_t *dec, const char *fmt, const mpd_context_t *ctx, uint32_t *status);
char *mpd_to_sci(const mpd_t *, int);
char *mpd_to_eng(const mpd_t *, int);
mpd_ssize_t mpd_to_sci_size(char **, const mpd_t *, int);
mpd_ssize_t mpd_to_eng_size(char **, const mpd_t *, int);
int mpd_validate_lconv(mpd_spec_t *);
int mpd_parse_fmt_str(mpd_spec_t *, const char *, int);
char *mpd_qformat_spec(const mpd_t *, const mpd_spec_t *, const mpd_context_t *, uint32_t *);
char *mpd_qformat(const mpd_t *, const char *, const mpd_context_t *, uint32_t *);
#define MPD_NUM_FLAGS 15
#define MPD_MAX_FLAG_STRING 208
#define MPD_MAX_FLAG_LIST (MPD_MAX_FLAG_STRING+18)
#define MPD_MAX_SIGNAL_LIST 121
int mpd_snprint_flags(char *dest, int nmemb, uint32_t flags);
int mpd_lsnprint_flags(char *dest, int nmemb, uint32_t flags, const char *flag_string[]);
int mpd_lsnprint_signals(char *dest, int nmemb, uint32_t flags, const char *signal_string[]);
int mpd_snprint_flags(char *, int, uint32_t);
int mpd_lsnprint_flags(char *, int, uint32_t, const char *[]);
int mpd_lsnprint_signals(char *, int, uint32_t, const char *[]);
/* output to a file */
void mpd_fprint(FILE *file, const mpd_t *dec);
void mpd_print(const mpd_t *dec);
void mpd_fprint(FILE *, const mpd_t *);
void mpd_print(const mpd_t *);
/* assignment from a string */
void mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx, uint32_t *status);
void mpd_qset_string(mpd_t *, const char *s, const mpd_context_t *, uint32_t *);
/* set to NaN with error flags */
void mpd_seterror(mpd_t *result, uint32_t flags, uint32_t *status);
void mpd_seterror(mpd_t *, uint32_t, uint32_t *);
/* set a special with sign and type */
void mpd_setspecial(mpd_t *dec, uint8_t sign, uint8_t type);
void mpd_setspecial(mpd_t *, uint8_t, uint8_t);
/* set coefficient to zero or all nines */
void mpd_zerocoeff(mpd_t *result);
void mpd_qmaxcoeff(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
void mpd_zerocoeff(mpd_t *);
void mpd_qmaxcoeff(mpd_t *, const mpd_context_t *, uint32_t *);
/* quietly assign a C integer type to an mpd_t */
void mpd_qset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
#ifndef LEGACY_COMPILER
void mpd_qset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
#endif
void mpd_qset_ssize(mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
void mpd_qset_i32(mpd_t *, int32_t, const mpd_context_t *, uint32_t *);
void mpd_qset_uint(mpd_t *, mpd_uint_t, const mpd_context_t *, uint32_t *);
void mpd_qset_u32(mpd_t *, uint32_t, const mpd_context_t *, uint32_t *);
void mpd_qset_i64(mpd_t *, int64_t, const mpd_context_t *, uint32_t *);
void mpd_qset_u64(mpd_t *, uint64_t, const mpd_context_t *, uint32_t *);
/* quietly assign a C integer type to an mpd_t with a static coefficient */
void mpd_qsset_ssize(mpd_t *result, mpd_ssize_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsset_i32(mpd_t *result, int32_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsset_uint(mpd_t *result, mpd_uint_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsset_u32(mpd_t *result, uint32_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsset_ssize(mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
void mpd_qsset_i32(mpd_t *, int32_t, const mpd_context_t *, uint32_t *);
void mpd_qsset_uint(mpd_t *, mpd_uint_t, const mpd_context_t *, uint32_t *);
void mpd_qsset_u32(mpd_t *, uint32_t, const mpd_context_t *, uint32_t *);
mpd_ssize_t mpd_qget_ssize(const mpd_t *, uint32_t *);
mpd_uint_t mpd_qget_uint(const mpd_t *, uint32_t *);
mpd_uint_t mpd_qabs_uint(const mpd_t *, uint32_t *);
int32_t mpd_qget_i32(const mpd_t *, uint32_t *);
uint32_t mpd_qget_u32(const mpd_t *, uint32_t *);
int64_t mpd_qget_i64(const mpd_t *, uint32_t *);
uint64_t mpd_qget_u64(const mpd_t *, uint32_t *);
int mpd_qcheck_nan(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
int mpd_qcheck_nans(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qfinalize(mpd_t *, const mpd_context_t *, uint32_t *);
const char *mpd_class(const mpd_t *, const mpd_context_t *);
mpd_t *mpd_qncopy(const mpd_t *);
int mpd_qcopy(mpd_t *, const mpd_t *, uint32_t *);
int mpd_qcopy_abs(mpd_t *, const mpd_t *, uint32_t *);
int mpd_qcopy_negate(mpd_t *, const mpd_t *, uint32_t *);
int mpd_qcopy_sign(mpd_t *, const mpd_t *, const mpd_t *, uint32_t *);
void mpd_qand(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qinvert(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qlogb(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qor(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qscaleb(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qxor(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
int mpd_same_quantum(const mpd_t *, const mpd_t *);
void mpd_qrotate(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
int mpd_qshiftl(mpd_t *, const mpd_t *, mpd_ssize_t, uint32_t *);
mpd_uint_t mpd_qshiftr(mpd_t *, const mpd_t *, mpd_ssize_t, uint32_t *);
mpd_uint_t mpd_qshiftr_inplace(mpd_t *, mpd_ssize_t);
void mpd_qshift(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qshiftn(mpd_t *, const mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
int mpd_qcmp(const mpd_t *, const mpd_t *, uint32_t *);
int mpd_qcompare(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
int mpd_qcompare_signal(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
int mpd_cmp_total(const mpd_t *, const mpd_t *);
int mpd_cmp_total_mag(const mpd_t *, const mpd_t *);
int mpd_compare_total(mpd_t *, const mpd_t *, const mpd_t *);
int mpd_compare_total_mag(mpd_t *, const mpd_t *, const mpd_t *);
void mpd_qround_to_intx(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qround_to_int(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qtrunc(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qfloor(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qceil(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qabs(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qmax(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qmax_mag(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qmin(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qmin_mag(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qminus(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qplus(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qnext_minus(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qnext_plus(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qnext_toward(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qquantize(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qrescale(mpd_t *, const mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
void mpd_qrescale_fmt(mpd_t *, const mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
void mpd_qreduce(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qadd(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qadd_ssize(mpd_t *, const mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
void mpd_qadd_i32(mpd_t *, const mpd_t *, int32_t, const mpd_context_t *, uint32_t *);
void mpd_qadd_uint(mpd_t *, const mpd_t *, mpd_uint_t, const mpd_context_t *, uint32_t *);
void mpd_qadd_u32(mpd_t *, const mpd_t *, uint32_t, const mpd_context_t *, uint32_t *);
void mpd_qsub(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qsub_ssize(mpd_t *, const mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
void mpd_qsub_i32(mpd_t *, const mpd_t *, int32_t, const mpd_context_t *, uint32_t *);
void mpd_qsub_uint(mpd_t *, const mpd_t *, mpd_uint_t, const mpd_context_t *, uint32_t *);
void mpd_qsub_u32(mpd_t *, const mpd_t *, uint32_t, const mpd_context_t *, uint32_t *);
void mpd_qmul(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qmul_ssize(mpd_t *, const mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
void mpd_qmul_i32(mpd_t *, const mpd_t *, int32_t, const mpd_context_t *, uint32_t *);
void mpd_qmul_uint(mpd_t *, const mpd_t *, mpd_uint_t, const mpd_context_t *, uint32_t *);
void mpd_qmul_u32(mpd_t *, const mpd_t *, uint32_t, const mpd_context_t *, uint32_t *);
void mpd_qfma(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *c, const mpd_context_t *, uint32_t *);
void mpd_qdiv(mpd_t *q, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qdiv_ssize(mpd_t *, const mpd_t *, mpd_ssize_t, const mpd_context_t *, uint32_t *);
void mpd_qdiv_i32(mpd_t *, const mpd_t *, int32_t, const mpd_context_t *, uint32_t *);
void mpd_qdiv_uint(mpd_t *, const mpd_t *, mpd_uint_t, const mpd_context_t *, uint32_t *);
void mpd_qdiv_u32(mpd_t *, const mpd_t *, uint32_t, const mpd_context_t *, uint32_t *);
void mpd_qdivint(mpd_t *q, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qrem(mpd_t *r, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qrem_near(mpd_t *r, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qpow(mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qpowmod(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qexp(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qln10(mpd_t *, mpd_ssize_t, uint32_t *);
void mpd_qln(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qlog10(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qsqrt(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qinvroot(mpd_t *, const mpd_t *, const mpd_context_t *, uint32_t *);
void mpd_qadd_i64(mpd_t *, const mpd_t *, int64_t, const mpd_context_t *, uint32_t *);
void mpd_qadd_u64(mpd_t *, const mpd_t *, uint64_t, const mpd_context_t *, uint32_t *);
void mpd_qsub_i64(mpd_t *, const mpd_t *, int64_t, const mpd_context_t *, uint32_t *);
void mpd_qsub_u64(mpd_t *, const mpd_t *, uint64_t, const mpd_context_t *, uint32_t *);
void mpd_qmul_i64(mpd_t *, const mpd_t *, int64_t, const mpd_context_t *, uint32_t *);
void mpd_qmul_u64(mpd_t *, const mpd_t *, uint64_t, const mpd_context_t *, uint32_t *);
void mpd_qdiv_i64(mpd_t *, const mpd_t *, int64_t, const mpd_context_t *, uint32_t *);
void mpd_qdiv_u64(mpd_t *, const mpd_t *, uint64_t, const mpd_context_t *, uint32_t *);
/* quietly get a C integer type from an mpd_t */
mpd_ssize_t mpd_qget_ssize(const mpd_t *dec, uint32_t *status);
mpd_uint_t mpd_qget_uint(const mpd_t *dec, uint32_t *status);
mpd_uint_t mpd_qabs_uint(const mpd_t *dec, uint32_t *status);
int32_t mpd_qget_i32(const mpd_t *dec, uint32_t *status);
uint32_t mpd_qget_u32(const mpd_t *dec, uint32_t *status);
#ifndef LEGACY_COMPILER
int64_t mpd_qget_i64(const mpd_t *dec, uint32_t *status);
uint64_t mpd_qget_u64(const mpd_t *dec, uint32_t *status);
#endif
/* quiet functions */
int mpd_qcheck_nan(mpd_t *nanresult, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
int mpd_qcheck_nans(mpd_t *nanresult, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qfinalize(mpd_t *result, const mpd_context_t *ctx, uint32_t *status);
const char *mpd_class(const mpd_t *a, const mpd_context_t *ctx);
int mpd_qcopy(mpd_t *result, const mpd_t *a, uint32_t *status);
mpd_t *mpd_qncopy(const mpd_t *a);
int mpd_qcopy_abs(mpd_t *result, const mpd_t *a, uint32_t *status);
int mpd_qcopy_negate(mpd_t *result, const mpd_t *a, uint32_t *status);
int mpd_qcopy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, uint32_t *status);
void mpd_qand(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qinvert(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qlogb(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qscaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qxor(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
int mpd_same_quantum(const mpd_t *a, const mpd_t *b);
void mpd_qrotate(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
int mpd_qshiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
mpd_uint_t mpd_qshiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, uint32_t *status);
mpd_uint_t mpd_qshiftr_inplace(mpd_t *result, mpd_ssize_t n);
void mpd_qshift(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qshiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, const mpd_context_t *ctx, uint32_t *status);
int mpd_qcmp(const mpd_t *a, const mpd_t *b, uint32_t *status);
int mpd_qcompare(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
int mpd_qcompare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
int mpd_cmp_total(const mpd_t *a, const mpd_t *b);
int mpd_cmp_total_mag(const mpd_t *a, const mpd_t *b);
int mpd_compare_total(mpd_t *result, const mpd_t *a, const mpd_t *b);
int mpd_compare_total_mag(mpd_t *result, const mpd_t *a, const mpd_t *b);
void mpd_qround_to_intx(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qround_to_int(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qtrunc(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qfloor(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qceil(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qabs(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmax(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmax_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmin(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmin_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qminus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qplus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qnext_minus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qnext_plus(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qquantize(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qrescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
void mpd_qrescale_fmt(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, const mpd_context_t *ctx, uint32_t *status);
void mpd_qreduce(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qadd(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qadd_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qadd_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qadd_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qadd_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qfma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_i32(mpd_t *result, const mpd_t *a, int32_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_u32(mpd_t *result, const mpd_t *a, uint32_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdivint(mpd_t *q, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qrem(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdivmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qpow(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_context_t *ctx, uint32_t *status);
void mpd_qpowmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, const mpd_context_t *ctx, uint32_t *status);
void mpd_qexp(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qln10(mpd_t *result, mpd_ssize_t prec, uint32_t *status);
void mpd_qln(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qlog10(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsqrt(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qinvroot(mpd_t *result, const mpd_t *a, const mpd_context_t *ctx, uint32_t *status);
#ifndef LEGACY_COMPILER
void mpd_qadd_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qadd_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsub_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qmul_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_i64(mpd_t *result, const mpd_t *a, int64_t b, const mpd_context_t *ctx, uint32_t *status);
void mpd_qdiv_u64(mpd_t *result, const mpd_t *a, uint64_t b, const mpd_context_t *ctx, uint32_t *status);
#endif
size_t mpd_sizeinbase(const mpd_t *a, uint32_t base);
void mpd_qimport_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen,
uint8_t srcsign, uint32_t srcbase,
const mpd_context_t *ctx, uint32_t *status);
void mpd_qimport_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen,
uint8_t srcsign, uint32_t srcbase,
const mpd_context_t *ctx, uint32_t *status);
size_t mpd_qexport_u16(uint16_t **rdata, size_t rlen, uint32_t base,
const mpd_t *src, uint32_t *status);
size_t mpd_qexport_u32(uint32_t **rdata, size_t rlen, uint32_t base,
const mpd_t *src, uint32_t *status);
size_t mpd_sizeinbase(const mpd_t *, uint32_t);
void mpd_qimport_u16(mpd_t *, const uint16_t *, size_t, uint8_t, uint32_t, const mpd_context_t *, uint32_t *);
void mpd_qimport_u32(mpd_t *, const uint32_t *, size_t, uint8_t, uint32_t, const mpd_context_t *, uint32_t *);
size_t mpd_qexport_u16(uint16_t **, size_t, uint32_t, const mpd_t *, uint32_t *);
size_t mpd_qexport_u32(uint32_t **, size_t, uint32_t, const mpd_t *, uint32_t *);
/******************************************************************************/
/* Signalling functions */
/******************************************************************************/
char *mpd_format(const mpd_t *dec, const char *fmt, mpd_context_t *ctx);
void mpd_import_u16(mpd_t *result, const uint16_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
void mpd_import_u32(mpd_t *result, const uint32_t *srcdata, size_t srclen, uint8_t srcsign, uint32_t base, mpd_context_t *ctx);
size_t mpd_export_u16(uint16_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
size_t mpd_export_u32(uint32_t **rdata, size_t rlen, uint32_t base, const mpd_t *src, mpd_context_t *ctx);
void mpd_finalize(mpd_t *result, mpd_context_t *ctx);
int mpd_check_nan(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
int mpd_check_nans(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_set_string(mpd_t *result, const char *s, mpd_context_t *ctx);
void mpd_maxcoeff(mpd_t *result, mpd_context_t *ctx);
void mpd_sset_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
void mpd_sset_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
void mpd_sset_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
void mpd_sset_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
void mpd_set_ssize(mpd_t *result, mpd_ssize_t a, mpd_context_t *ctx);
void mpd_set_i32(mpd_t *result, int32_t a, mpd_context_t *ctx);
void mpd_set_uint(mpd_t *result, mpd_uint_t a, mpd_context_t *ctx);
void mpd_set_u32(mpd_t *result, uint32_t a, mpd_context_t *ctx);
#ifndef LEGACY_COMPILER
void mpd_set_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
void mpd_set_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
#endif
mpd_ssize_t mpd_get_ssize(const mpd_t *a, mpd_context_t *ctx);
mpd_uint_t mpd_get_uint(const mpd_t *a, mpd_context_t *ctx);
mpd_uint_t mpd_abs_uint(const mpd_t *a, mpd_context_t *ctx);
int32_t mpd_get_i32(const mpd_t *a, mpd_context_t *ctx);
uint32_t mpd_get_u32(const mpd_t *a, mpd_context_t *ctx);
#ifndef LEGACY_COMPILER
int64_t mpd_get_i64(const mpd_t *a, mpd_context_t *ctx);
uint64_t mpd_get_u64(const mpd_t *a, mpd_context_t *ctx);
#endif
void mpd_and(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_copy(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_canonical(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_copy_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_copy_negate(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_copy_sign(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_invert(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_logb(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_or(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_rotate(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_scaleb(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_shiftl(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
mpd_uint_t mpd_shiftr(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
void mpd_shiftn(mpd_t *result, const mpd_t *a, mpd_ssize_t n, mpd_context_t *ctx);
void mpd_shift(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_xor(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_abs(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
int mpd_cmp(const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
int mpd_compare(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
int mpd_compare_signal(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_add(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_add_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
void mpd_add_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
void mpd_add_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
void mpd_add_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
void mpd_sub(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_sub_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
void mpd_sub_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
void mpd_sub_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
void mpd_sub_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
void mpd_div(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_div_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
void mpd_div_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
void mpd_div_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
void mpd_div_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
void mpd_divmod(mpd_t *q, mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_divint(mpd_t *q, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_exp(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_fma(mpd_t *result, const mpd_t *a, const mpd_t *b, const mpd_t *c, mpd_context_t *ctx);
void mpd_ln(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_log10(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_max(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_max_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_min(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_min_mag(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_mul(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_mul_ssize(mpd_t *result, const mpd_t *a, mpd_ssize_t b, mpd_context_t *ctx);
void mpd_mul_i32(mpd_t *result, const mpd_t *a, int32_t b, mpd_context_t *ctx);
void mpd_mul_uint(mpd_t *result, const mpd_t *a, mpd_uint_t b, mpd_context_t *ctx);
void mpd_mul_u32(mpd_t *result, const mpd_t *a, uint32_t b, mpd_context_t *ctx);
void mpd_next_minus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_next_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_next_toward(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_plus(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_pow(mpd_t *result, const mpd_t *base, const mpd_t *exp, mpd_context_t *ctx);
void mpd_powmod(mpd_t *result, const mpd_t *base, const mpd_t *exp, const mpd_t *mod, mpd_context_t *ctx);
void mpd_quantize(mpd_t *result, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_rescale(mpd_t *result, const mpd_t *a, mpd_ssize_t exp, mpd_context_t *ctx);
void mpd_reduce(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_rem(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_rem_near(mpd_t *r, const mpd_t *a, const mpd_t *b, mpd_context_t *ctx);
void mpd_round_to_intx(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_round_to_int(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_trunc(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_floor(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_ceil(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_sqrt(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
void mpd_invroot(mpd_t *result, const mpd_t *a, mpd_context_t *ctx);
#ifndef LEGACY_COMPILER
void mpd_add_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
void mpd_add_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
void mpd_sub_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
void mpd_sub_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
void mpd_div_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
void mpd_div_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
void mpd_mul_i64(mpd_t *result, const mpd_t *a, int64_t b, mpd_context_t *ctx);
void mpd_mul_u64(mpd_t *result, const mpd_t *a, uint64_t b, mpd_context_t *ctx);
#endif
char *mpd_format(const mpd_t *, const char *, mpd_context_t *);
void mpd_import_u16(mpd_t *, const uint16_t *, size_t, uint8_t, uint32_t, mpd_context_t *);
void mpd_import_u32(mpd_t *, const uint32_t *, size_t, uint8_t, uint32_t, mpd_context_t *);
size_t mpd_export_u16(uint16_t **, size_t, uint32_t, const mpd_t *, mpd_context_t *);
size_t mpd_export_u32(uint32_t **, size_t, uint32_t, const mpd_t *, mpd_context_t *);
void mpd_finalize(mpd_t *, mpd_context_t *);
int mpd_check_nan(mpd_t *, const mpd_t *, mpd_context_t *);
int mpd_check_nans(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_set_string(mpd_t *, const char *s, mpd_context_t *);
void mpd_maxcoeff(mpd_t *, mpd_context_t *);
void mpd_sset_ssize(mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_sset_i32(mpd_t *, int32_t, mpd_context_t *);
void mpd_sset_uint(mpd_t *, mpd_uint_t, mpd_context_t *);
void mpd_sset_u32(mpd_t *, uint32_t, mpd_context_t *);
void mpd_set_ssize(mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_set_i32(mpd_t *, int32_t, mpd_context_t *);
void mpd_set_uint(mpd_t *, mpd_uint_t, mpd_context_t *);
void mpd_set_u32(mpd_t *, uint32_t, mpd_context_t *);
void mpd_set_i64(mpd_t *, int64_t, mpd_context_t *);
void mpd_set_u64(mpd_t *, uint64_t, mpd_context_t *);
mpd_ssize_t mpd_get_ssize(const mpd_t *, mpd_context_t *);
mpd_uint_t mpd_get_uint(const mpd_t *, mpd_context_t *);
mpd_uint_t mpd_abs_uint(const mpd_t *, mpd_context_t *);
int32_t mpd_get_i32(const mpd_t *, mpd_context_t *);
uint32_t mpd_get_u32(const mpd_t *, mpd_context_t *);
int64_t mpd_get_i64(const mpd_t *, mpd_context_t *);
uint64_t mpd_get_u64(const mpd_t *, mpd_context_t *);
void mpd_and(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_copy(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_canonical(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_copy_abs(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_copy_negate(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_copy_sign(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_invert(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_logb(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_or(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_rotate(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_scaleb(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_shiftl(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *);
mpd_uint_t mpd_shiftr(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_shiftn(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_shift(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_xor(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_abs(mpd_t *, const mpd_t *, mpd_context_t *);
int mpd_cmp(const mpd_t *, const mpd_t *, mpd_context_t *);
int mpd_compare(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
int mpd_compare_signal(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_add(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_add_ssize(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_add_i32(mpd_t *, const mpd_t *, int32_t, mpd_context_t *);
void mpd_add_uint(mpd_t *, const mpd_t *, mpd_uint_t, mpd_context_t *);
void mpd_add_u32(mpd_t *, const mpd_t *, uint32_t, mpd_context_t *);
void mpd_sub(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_sub_ssize(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_sub_i32(mpd_t *, const mpd_t *, int32_t, mpd_context_t *);
void mpd_sub_uint(mpd_t *, const mpd_t *, mpd_uint_t, mpd_context_t *);
void mpd_sub_u32(mpd_t *, const mpd_t *, uint32_t, mpd_context_t *);
void mpd_div(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_div_ssize(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_div_i32(mpd_t *, const mpd_t *, int32_t, mpd_context_t *);
void mpd_div_uint(mpd_t *, const mpd_t *, mpd_uint_t, mpd_context_t *);
void mpd_div_u32(mpd_t *, const mpd_t *, uint32_t, mpd_context_t *);
void mpd_divmod(mpd_t *, mpd_t *r, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_divint(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_exp(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_fma(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *c, mpd_context_t *);
void mpd_ln(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_log10(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_max(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_max_mag(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_min(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_min_mag(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_minus(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_mul(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_mul_ssize(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_mul_i32(mpd_t *, const mpd_t *, int32_t, mpd_context_t *);
void mpd_mul_uint(mpd_t *, const mpd_t *, mpd_uint_t, mpd_context_t *);
void mpd_mul_u32(mpd_t *, const mpd_t *, uint32_t, mpd_context_t *);
void mpd_next_minus(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_next_plus(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_next_toward(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_plus(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_pow(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_powmod(mpd_t *, const mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_quantize(mpd_t *, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_rescale(mpd_t *, const mpd_t *, mpd_ssize_t, mpd_context_t *);
void mpd_reduce(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_rem(mpd_t *r, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_rem_near(mpd_t *r, const mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_round_to_intx(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_round_to_int(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_trunc(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_floor(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_ceil(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_sqrt(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_invroot(mpd_t *, const mpd_t *, mpd_context_t *);
void mpd_add_i64(mpd_t *, const mpd_t *, int64_t, mpd_context_t *);
void mpd_add_u64(mpd_t *, const mpd_t *, uint64_t, mpd_context_t *);
void mpd_sub_i64(mpd_t *, const mpd_t *, int64_t, mpd_context_t *);
void mpd_sub_u64(mpd_t *, const mpd_t *, uint64_t, mpd_context_t *);
void mpd_div_i64(mpd_t *, const mpd_t *, int64_t, mpd_context_t *);
void mpd_div_u64(mpd_t *, const mpd_t *, uint64_t, mpd_context_t *);
void mpd_mul_i64(mpd_t *, const mpd_t *, int64_t, mpd_context_t *);
void mpd_mul_u64(mpd_t *, const mpd_t *, uint64_t, mpd_context_t *);
/******************************************************************************/
/* Configuration specific */
/******************************************************************************/
#ifdef CONFIG_64
void mpd_qsset_i64(mpd_t *result, int64_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_qsset_u64(mpd_t *result, uint64_t a, const mpd_context_t *ctx, uint32_t *status);
void mpd_sset_i64(mpd_t *result, int64_t a, mpd_context_t *ctx);
void mpd_sset_u64(mpd_t *result, uint64_t a, mpd_context_t *ctx);
#endif
void mpd_qsset_i64(mpd_t *, int64_t, const mpd_context_t *, uint32_t *);
void mpd_qsset_u64(mpd_t *, uint64_t, const mpd_context_t *, uint32_t *);
void mpd_sset_i64(mpd_t *, int64_t, mpd_context_t *);
void mpd_sset_u64(mpd_t *, uint64_t, mpd_context_t *);
/******************************************************************************/
/* Get attributes of a decimal */
/******************************************************************************/
EXTINLINE mpd_ssize_t mpd_adjexp(const mpd_t *dec);
EXTINLINE mpd_ssize_t mpd_etiny(const mpd_context_t *ctx);
EXTINLINE mpd_ssize_t mpd_etop(const mpd_context_t *ctx);
EXTINLINE mpd_uint_t mpd_msword(const mpd_t *dec);
EXTINLINE int mpd_word_digits(mpd_uint_t word);
mpd_ssize_t mpd_adjexp(const mpd_t *);
mpd_ssize_t mpd_etiny(const mpd_context_t *);
mpd_ssize_t mpd_etop(const mpd_context_t *);
mpd_uint_t mpd_msword(const mpd_t *);
int mpd_word_digits(mpd_uint_t);
/* most significant digit of a word */
EXTINLINE mpd_uint_t mpd_msd(mpd_uint_t word);
mpd_uint_t mpd_msd(mpd_uint_t);
/* least significant digit of a word */
EXTINLINE mpd_uint_t mpd_lsd(mpd_uint_t word);
mpd_uint_t mpd_lsd(mpd_uint_t);
/* coefficient size needed to store 'digits' */
EXTINLINE mpd_ssize_t mpd_digits_to_size(mpd_ssize_t digits);
mpd_ssize_t mpd_digits_to_size(mpd_ssize_t);
/* number of digits in the exponent, undefined for MPD_SSIZE_MIN */
EXTINLINE int mpd_exp_digits(mpd_ssize_t exp);
EXTINLINE int mpd_iscanonical(const mpd_t *dec UNUSED);
EXTINLINE int mpd_isfinite(const mpd_t *dec);
EXTINLINE int mpd_isinfinite(const mpd_t *dec);
EXTINLINE int mpd_isinteger(const mpd_t *dec);
EXTINLINE int mpd_isnan(const mpd_t *dec);
EXTINLINE int mpd_isnegative(const mpd_t *dec);
EXTINLINE int mpd_ispositive(const mpd_t *dec);
EXTINLINE int mpd_isqnan(const mpd_t *dec);
EXTINLINE int mpd_issigned(const mpd_t *dec);
EXTINLINE int mpd_issnan(const mpd_t *dec);
EXTINLINE int mpd_isspecial(const mpd_t *dec);
EXTINLINE int mpd_iszero(const mpd_t *dec);
int mpd_exp_digits(mpd_ssize_t);
int mpd_iscanonical(const mpd_t *);
int mpd_isfinite(const mpd_t *);
int mpd_isinfinite(const mpd_t *);
int mpd_isinteger(const mpd_t *);
int mpd_isnan(const mpd_t *);
int mpd_isnegative(const mpd_t *);
int mpd_ispositive(const mpd_t *);
int mpd_isqnan(const mpd_t *);
int mpd_issigned(const mpd_t *);
int mpd_issnan(const mpd_t *);
int mpd_isspecial(const mpd_t *);
int mpd_iszero(const mpd_t *);
/* undefined for special numbers */
EXTINLINE int mpd_iszerocoeff(const mpd_t *dec);
EXTINLINE int mpd_isnormal(const mpd_t *dec, const mpd_context_t *ctx);
EXTINLINE int mpd_issubnormal(const mpd_t *dec, const mpd_context_t *ctx);
int mpd_iszerocoeff(const mpd_t *);
int mpd_isnormal(const mpd_t *, const mpd_context_t *);
int mpd_issubnormal(const mpd_t *, const mpd_context_t *);
/* odd word */
EXTINLINE int mpd_isoddword(mpd_uint_t word);
int mpd_isoddword(mpd_uint_t);
/* odd coefficient */
EXTINLINE int mpd_isoddcoeff(const mpd_t *dec);
int mpd_isoddcoeff(const mpd_t *);
/* odd decimal, only defined for integers */
int mpd_isodd(const mpd_t *dec);
int mpd_isodd(const mpd_t *);
/* even decimal, only defined for integers */
int mpd_iseven(const mpd_t *dec);
int mpd_iseven(const mpd_t *);
/* 0 if dec is positive, 1 if dec is negative */
EXTINLINE uint8_t mpd_sign(const mpd_t *dec);
uint8_t mpd_sign(const mpd_t *);
/* 1 if dec is positive, -1 if dec is negative */
EXTINLINE int mpd_arith_sign(const mpd_t *dec);
EXTINLINE long mpd_radix(void);
EXTINLINE int mpd_isdynamic(const mpd_t *dec);
EXTINLINE int mpd_isstatic(const mpd_t *dec);
EXTINLINE int mpd_isdynamic_data(const mpd_t *dec);
EXTINLINE int mpd_isstatic_data(const mpd_t *dec);
EXTINLINE int mpd_isshared_data(const mpd_t *dec);
EXTINLINE int mpd_isconst_data(const mpd_t *dec);
EXTINLINE mpd_ssize_t mpd_trail_zeros(const mpd_t *dec);
int mpd_arith_sign(const mpd_t *);
long mpd_radix(void);
int mpd_isdynamic(const mpd_t *);
int mpd_isstatic(const mpd_t *);
int mpd_isdynamic_data(const mpd_t *);
int mpd_isstatic_data(const mpd_t *);
int mpd_isshared_data(const mpd_t *);
int mpd_isconst_data(const mpd_t *);
mpd_ssize_t mpd_trail_zeros(const mpd_t *);
/******************************************************************************/
/* Set attributes of a decimal */
/******************************************************************************/
/* set number of decimal digits in the coefficient */
EXTINLINE void mpd_setdigits(mpd_t *result);
EXTINLINE void mpd_set_sign(mpd_t *result, uint8_t sign);
/* copy sign from another decimal */
EXTINLINE void mpd_signcpy(mpd_t *result, const mpd_t *a);
EXTINLINE void mpd_set_infinity(mpd_t *result);
EXTINLINE void mpd_set_qnan(mpd_t *result);
EXTINLINE void mpd_set_snan(mpd_t *result);
EXTINLINE void mpd_set_negative(mpd_t *result);
EXTINLINE void mpd_set_positive(mpd_t *result);
EXTINLINE void mpd_set_dynamic(mpd_t *result);
EXTINLINE void mpd_set_static(mpd_t *result);
EXTINLINE void mpd_set_dynamic_data(mpd_t *result);
EXTINLINE void mpd_set_static_data(mpd_t *result);
EXTINLINE void mpd_set_shared_data(mpd_t *result);
EXTINLINE void mpd_set_const_data(mpd_t *result);
EXTINLINE void mpd_clear_flags(mpd_t *result);
EXTINLINE void mpd_set_flags(mpd_t *result, uint8_t flags);
EXTINLINE void mpd_copy_flags(mpd_t *result, const mpd_t *a);
void mpd_setdigits(mpd_t *);
void mpd_set_sign(mpd_t *, uint8_t);
void mpd_signcpy(mpd_t *, const mpd_t *);
void mpd_set_infinity(mpd_t *);
void mpd_set_qnan(mpd_t *);
void mpd_set_snan(mpd_t *);
void mpd_set_negative(mpd_t *);
void mpd_set_positive(mpd_t *);
void mpd_set_dynamic(mpd_t *);
void mpd_set_static(mpd_t *);
void mpd_set_dynamic_data(mpd_t *);
void mpd_set_static_data(mpd_t *);
void mpd_set_shared_data(mpd_t *);
void mpd_set_const_data(mpd_t *);
void mpd_clear_flags(mpd_t *);
void mpd_set_flags(mpd_t *, uint8_t);
void mpd_copy_flags(mpd_t *, const mpd_t *);
/******************************************************************************/
@ -743,45 +583,30 @@ EXTINLINE void mpd_copy_flags(mpd_t *result, const mpd_t *a);
/* Memory handling */
/******************************************************************************/
extern void *(* mpd_mallocfunc)(size_t size);
extern void *(* mpd_callocfunc)(size_t nmemb, size_t size);
extern void *(* mpd_reallocfunc)(void *ptr, size_t size);
extern void (* mpd_free)(void *ptr);
extern void *(*mpd_mallocfunc)(size_t);
extern void *(*mpd_callocfunc)(size_t, size_t);
extern void *(*mpd_reallocfunc)(void *, size_t);
extern void (*mpd_free)(void *);
void *mpd_callocfunc_em(size_t nmemb, size_t size);
void *mpd_callocfunc_em(size_t, size_t);
void *mpd_alloc(mpd_size_t nmemb, mpd_size_t size);
void *mpd_calloc(mpd_size_t nmemb, mpd_size_t size);
void *mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err);
void *mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size);
void *mpd_alloc(mpd_size_t, mpd_size_t);
void *mpd_calloc(mpd_size_t, mpd_size_t);
void *mpd_realloc(void *, mpd_size_t, mpd_size_t, uint8_t *);
void *mpd_sh_alloc(mpd_size_t, mpd_size_t, mpd_size_t);
mpd_t *mpd_qnew(void);
mpd_t *mpd_new(mpd_context_t *ctx);
mpd_t *mpd_qnew_size(mpd_ssize_t size);
EXTINLINE void mpd_del(mpd_t *dec);
mpd_t *mpd_new(mpd_context_t *);
mpd_t *mpd_qnew_size(mpd_ssize_t);
void mpd_del(mpd_t *);
EXTINLINE void mpd_uint_zero(mpd_uint_t *dest, mpd_size_t len);
EXTINLINE int mpd_qresize(mpd_t *result, mpd_ssize_t size, uint32_t *status);
EXTINLINE int mpd_qresize_zero(mpd_t *result, mpd_ssize_t size, uint32_t *status);
EXTINLINE void mpd_minalloc(mpd_t *result);
int mpd_resize(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
#ifdef __cplusplus
#ifdef MPD_CLEAR_STDC_LIMIT_MACROS
#undef MPD_CLEAR_STDC_LIMIT_MACROS
#undef __STDC_LIMIT_MACROS
#endif
} /* END extern "C" */
#endif
void mpd_uint_zero(mpd_uint_t *, mpd_size_t);
int mpd_qresize(mpd_t *, mpd_ssize_t, uint32_t *);
int mpd_qresize_zero(mpd_t *, mpd_ssize_t, uint32_t *);
void mpd_minalloc(mpd_t *);
int mpd_resize(mpd_t *, mpd_ssize_t, mpd_context_t *);
int mpd_resize_zero(mpd_t *, mpd_ssize_t, mpd_context_t *);
COSMOPOLITAN_C_END_
#endif /* MPDECIMAL_H */

View file

@ -38,10 +38,8 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
/* Bignum: Initialize the Number Theoretic Transform. */
/*
* Return the nth root of unity in F(p). This corresponds to e**((2*pi*i)/n)
* in the Fourier transform. We have w**n == 1 (mod p).
@ -53,16 +51,10 @@ mpd_uint_t
_mpd_getkernel(mpd_uint_t n, int sign, int modnum)
{
mpd_uint_t umod, p, r, xi;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
SETMODULUS(modnum);
r = mpd_roots[modnum]; /* primitive root of F(p) */
p = umod;
xi = (p-1) / n;
if (sign == -1)
return POWMOD(r, (p-1-xi));
else
@ -80,38 +72,28 @@ _mpd_init_fnt_params(mpd_size_t n, int sign, int modnum)
{
struct fnt_params *tparams;
mpd_uint_t umod;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_uint_t kernel, w;
mpd_uint_t i;
mpd_size_t nhalf;
assert(ispower2(n));
assert(sign == -1 || sign == 1);
assert(P1 <= modnum && modnum <= P3);
nhalf = n/2;
tparams = mpd_sh_alloc(sizeof *tparams, nhalf, sizeof (mpd_uint_t));
if (tparams == NULL) {
return NULL;
}
SETMODULUS(modnum);
kernel = _mpd_getkernel(n, sign, modnum);
tparams->modnum = modnum;
tparams->modulus = umod;
tparams->kernel = kernel;
/* wtable[] := w**0, w**1, ..., w**(nhalf-1) */
w = 1;
for (i = 0; i < nhalf; i++) {
tparams->wtable[i] = w;
w = MULMOD(w, kernel);
}
return tparams;
}
@ -120,15 +102,9 @@ void
_mpd_init_w3table(mpd_uint_t w3table[3], int sign, int modnum)
{
mpd_uint_t umod;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_uint_t kernel;
SETMODULUS(modnum);
kernel = _mpd_getkernel(3, sign, modnum);
w3table[0] = 1;
w3table[1] = kernel;
w3table[2] = POWMOD(kernel, 2);

View file

@ -2,40 +2,20 @@
#define NUMBER_THEORY_H
#include "third_party/python/Modules/_decimal/libmpdec/constants.h"
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
/* transform parameters */
struct fnt_params {
int modnum;
mpd_uint_t modulus;
mpd_uint_t kernel;
mpd_uint_t wtable[];
int modnum;
mpd_uint_t modulus;
mpd_uint_t kernel;
mpd_uint_t wtable[];
};
mpd_uint_t _mpd_getkernel(mpd_uint_t n, int sign, int modnum);
struct fnt_params *_mpd_init_fnt_params(mpd_size_t n, int sign, int modnum);
void _mpd_init_w3table(mpd_uint_t w3table[3], int sign, int modnum);
mpd_uint_t _mpd_getkernel(mpd_uint_t, int, int);
struct fnt_params *_mpd_init_fnt_params(mpd_size_t, int, int);
void _mpd_init_w3table(mpd_uint_t[3], int, int);
#ifdef PPRO
static inline void
ppro_setmodulus(int modnum, mpd_uint_t *umod, double *dmod, uint32_t dinvmod[3])
{
*dmod = *umod = mpd_moduli[modnum];
dinvmod[0] = mpd_invmoduli[modnum][0];
dinvmod[1] = mpd_invmoduli[modnum][1];
dinvmod[2] = mpd_invmoduli[modnum][2];
static inline void std_setmodulus(int modnum, mpd_uint_t *umod) {
*umod = mpd_moduli[modnum];
}
#else
static inline void
std_setmodulus(int modnum, mpd_uint_t *umod)
{
*umod = mpd_moduli[modnum];
}
#endif
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
#endif

View file

@ -41,10 +41,66 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
/*
Cache Efficient Matrix Fourier Transform
for arrays of form 2
/* Bignum: Cache efficient Matrix Fourier Transform for arrays of the
form 2**n (See literature/six-step.txt). */
The Six Step Transform
In libmpdec, the six-step transform is the Matrix Fourier Transform in
disguise. It is called six-step transform after a variant that appears
in [1]. The algorithm requires that the input array can be viewed as an
R×C matrix.
Algorithm six-step (forward transform)
1a) Transpose the matrix.
1b) Apply a length R FNT to each row.
1c) Transpose the matrix.
2) Multiply each matrix element (addressed by j×C+m) by r**(j×m).
3) Apply a length C FNT to each row.
4) Transpose the matrix.
Note that steps 1a) - 1c) are exactly equivalent to step 1) of the Matrix
Fourier Transform. For large R, it is faster to transpose twice and do
a transform on the rows than to perform a column transpose directly.
Algorithm six-step (inverse transform)
0) View the matrix as a C×R matrix.
1) Transpose the matrix, producing an R×C matrix.
2) Apply a length C FNT to each row.
3) Multiply each matrix element (addressed by i×C+n) by r**(i×n).
4a) Transpose the matrix.
4b) Apply a length R FNT to each row.
4c) Transpose the matrix.
Again, steps 4a) - 4c) are equivalent to step 4) of the Matrix Fourier
Transform.
[1] David H. Bailey: FFTs in External or Hierarchical Memory
http://crd.lbl.gov/~dhbailey/dhbpapers/
*/
/* forward transform with sign = -1 */
int
@ -54,28 +110,18 @@ six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
mpd_size_t log2n, C, R;
mpd_uint_t kernel;
mpd_uint_t umod;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_uint_t *x, w0, w1, wstep;
mpd_size_t i, k;
assert(ispower2(n));
assert(n >= 16);
assert(n <= MPD_MAXTRANSFORM_2N);
log2n = mpd_bsr(n);
C = ((mpd_size_t)1) << (log2n / 2); /* number of columns */
R = ((mpd_size_t)1) << (log2n - (log2n / 2)); /* number of rows */
/* Transpose the matrix. */
if (!transpose_pow2(a, R, C)) {
return 0;
}
/* Length R transform on the rows. */
if ((tparams = _mpd_init_fnt_params(R, -1, modnum)) == NULL) {
return 0;
@ -83,13 +129,11 @@ six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
for (x = a; x < a+n; x += R) {
fnt_dif2(x, R, tparams);
}
/* Transpose the matrix. */
if (!transpose_pow2(a, C, R)) {
mpd_free(tparams);
return 0;
}
/* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
SETMODULUS(modnum);
kernel = _mpd_getkernel(n, -1, modnum);
@ -106,7 +150,6 @@ six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
a[i*C+k+1] = x1;
}
}
/* Length C transform on the rows. */
if (C != R) {
mpd_free(tparams);
@ -118,7 +161,6 @@ six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
fnt_dif2(x, C, tparams);
}
mpd_free(tparams);
#if 0
/* An unordered transform is sufficient for convolution. */
/* Transpose the matrix. */
@ -126,11 +168,9 @@ six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
return 0;
}
#endif
return 1;
}
/* reverse transform, sign = 1 */
int
inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
@ -139,23 +179,14 @@ inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
mpd_size_t log2n, C, R;
mpd_uint_t kernel;
mpd_uint_t umod;
#ifdef PPRO
double dmod;
uint32_t dinvmod[3];
#endif
mpd_uint_t *x, w0, w1, wstep;
mpd_size_t i, k;
assert(ispower2(n));
assert(n >= 16);
assert(n <= MPD_MAXTRANSFORM_2N);
log2n = mpd_bsr(n);
C = ((mpd_size_t)1) << (log2n / 2); /* number of columns */
R = ((mpd_size_t)1) << (log2n - (log2n / 2)); /* number of rows */
#if 0
/* An unordered transform is sufficient for convolution. */
/* Transpose the matrix, producing an R*C matrix. */
@ -163,7 +194,6 @@ inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
return 0;
}
#endif
/* Length C transform on the rows. */
if ((tparams = _mpd_init_fnt_params(C, 1, modnum)) == NULL) {
return 0;
@ -171,7 +201,6 @@ inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
for (x = a; x < a+n; x += C) {
fnt_dif2(x, C, tparams);
}
/* Multiply each matrix element (addressed by i*C+k) by r**(i*k). */
SETMODULUS(modnum);
kernel = _mpd_getkernel(n, 1, modnum);
@ -188,13 +217,11 @@ inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
a[i*C+k+1] = x1;
}
}
/* Transpose the matrix. */
if (!transpose_pow2(a, R, C)) {
mpd_free(tparams);
return 0;
}
/* Length R transform on the rows. */
if (R != C) {
mpd_free(tparams);
@ -206,11 +233,9 @@ inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum)
fnt_dif2(x, R, tparams);
}
mpd_free(tparams);
/* Transpose the matrix. */
if (!transpose_pow2(a, C, R)) {
return 0;
}
return 1;
}

View file

@ -4,11 +4,9 @@
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
int six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
int inv_six_step_fnt(mpd_uint_t *a, mpd_size_t n, int modnum);
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
#endif

View file

@ -39,22 +39,18 @@ libmpdec (BSD-2)\\n\
Copyright 2008-2016 Stefan Krah\"");
asm(".include \"libc/disclaimer.inc\"");
#define BUFSIZE 4096
#define SIDE 128
/* Bignum: The transpose functions are used for very large transforms
in sixstep.c and fourstep.c. */
/* Definition of the matrix transpose */
void
std_trans(mpd_uint_t dest[], mpd_uint_t src[], mpd_size_t rows, mpd_size_t cols)
{
mpd_size_t idest, isrc;
mpd_size_t r, c;
for (r = 0; r < rows; r++) {
isrc = r * cols;
idest = r;
@ -83,10 +79,7 @@ swap_halfrows_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols, int dir
mpd_size_t m, r=0;
mpd_size_t offset;
mpd_size_t next;
assert(cols == mul_size_t(2, rows));
if (dir == FORWARD_CYCLE) {
r = rows;
}
@ -96,52 +89,36 @@ swap_halfrows_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols, int dir
else {
abort(); /* GCOV_NOT_REACHED */
}
m = cols - 1;
hmax = rows; /* cycles start at odd halfrows */
dbits = 8 * sizeof *done;
if ((done = mpd_calloc(hmax/(sizeof *done) + 1, sizeof *done)) == NULL) {
return 0;
}
for (hn = 1; hn <= hmax; hn += 2) {
if (done[hn/dbits] & mpd_bits[hn%dbits]) {
continue;
}
readbuf = buf1; writebuf = buf2;
for (offset = 0; offset < cols/2; offset += b) {
stride = (offset + b < cols/2) ? b : cols/2-offset;
hp = matrix + hn*cols/2;
memcpy(readbuf, hp+offset, stride*(sizeof *readbuf));
pointerswap(&readbuf, &writebuf);
next = mulmod_size_t(hn, r, m);
hp = matrix + next*cols/2;
while (next != hn) {
memcpy(readbuf, hp+offset, stride*(sizeof *readbuf));
memcpy(hp+offset, writebuf, stride*(sizeof *writebuf));
pointerswap(&readbuf, &writebuf);
done[next/dbits] |= mpd_bits[next%dbits];
next = mulmod_size_t(next, r, m);
hp = matrix + next*cols/2;
}
memcpy(hp+offset, writebuf, stride*(sizeof *writebuf));
done[hn/dbits] |= mpd_bits[hn%dbits];
}
}
mpd_free(done);
return 1;
}
@ -153,7 +130,6 @@ squaretrans(mpd_uint_t *buf, mpd_size_t cols)
mpd_uint_t tmp;
mpd_size_t idest, isrc;
mpd_size_t r, c;
for (r = 0; r < cols; r++) {
c = r+1;
isrc = r*cols + c;
@ -182,13 +158,9 @@ squaretrans_pow2(mpd_uint_t *matrix, mpd_size_t size)
mpd_size_t b = size;
mpd_size_t r, c;
mpd_size_t i;
while (b > SIDE) b >>= 1;
for (r = 0; r < size; r += b) {
for (c = r; c < size; c += b) {
from = matrix + r*size + c;
to = buf1;
for (i = 0; i < b; i++) {
@ -197,7 +169,6 @@ squaretrans_pow2(mpd_uint_t *matrix, mpd_size_t size)
to += b;
}
squaretrans(buf1, b);
if (r == c) {
to = matrix + r*size + c;
from = buf1;
@ -217,7 +188,6 @@ squaretrans_pow2(mpd_uint_t *matrix, mpd_size_t size)
to += b;
}
squaretrans(buf2, b);
to = matrix + c*size + r;
from = buf1;
for (i = 0; i < b; i++) {
@ -225,7 +195,6 @@ squaretrans_pow2(mpd_uint_t *matrix, mpd_size_t size)
from += b;
to += size;
}
to = matrix + r*size + c;
from = buf2;
for (i = 0; i < b; i++) {
@ -236,7 +205,6 @@ squaretrans_pow2(mpd_uint_t *matrix, mpd_size_t size)
}
}
}
}
/*
@ -247,10 +215,8 @@ int
transpose_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols)
{
mpd_size_t size = mul_size_t(rows, cols);
assert(ispower2(rows));
assert(ispower2(cols));
if (cols == rows) {
squaretrans_pow2(matrix, rows);
}
@ -269,8 +235,7 @@ transpose_pow2(mpd_uint_t *matrix, mpd_size_t rows, mpd_size_t cols)
}
}
else {
abort(); /* GCOV_NOT_REACHED */
unreachable;
}
return 1;
}

View file

@ -4,7 +4,6 @@
/* clang-format off */
/* Internal header file: all symbols have local scope in the DSO */
MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
enum {FORWARD_CYCLE, BACKWARD_CYCLE};
@ -20,6 +19,5 @@ static inline void pointerswap(mpd_uint_t **a, mpd_uint_t **b)
*a = tmp;
}
MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
#endif

View file

@ -4,68 +4,57 @@
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
/* clang-format off */
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__STRICT_ANSI__)
/*****************************************************************************/
/* Low level native arithmetic on basic types */
/*****************************************************************************/
/** ------------------------------------------------------------
** Double width multiplication and division
** ------------------------------------------------------------
*/
#if defined(CONFIG_64)
#if defined(ANSI)
#if defined(HAVE_UINT128_T)
static inline void
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
{
__uint128_t hl;
hl = (__uint128_t)a * b;
*hi = hl >> 64;
*lo = (mpd_uint_t)hl;
mpd_uint_t h, l;
asm ( "mulq %3\n\t"
: "=d" (h), "=a" (l)
: "%a" (a), "rm" (b)
: "cc"
);
*hi = h;
*lo = l;
}
static inline void
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
mpd_uint_t d)
{
__uint128_t hl;
hl = ((__uint128_t)hi<<64) + lo;
*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
*r = (mpd_uint_t)(hl - (__uint128_t)(*q) * d);
mpd_uint_t qq, rr;
asm ( "divq %4\n\t"
: "=a" (qq), "=d" (rr)
: "a" (lo), "d" (hi), "rm" (d)
: "cc"
);
*q = qq;
*r = rr;
}
#else
static inline void
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
{
uint32_t w[4], carry;
uint32_t ah, al, bh, bl;
uint64_t hl;
ah = (uint32_t)(a>>32); al = (uint32_t)a;
bh = (uint32_t)(b>>32); bl = (uint32_t)b;
hl = (uint64_t)al * bl;
w[0] = (uint32_t)hl;
carry = (uint32_t)(hl>>32);
hl = (uint64_t)ah * bl + carry;
w[1] = (uint32_t)hl;
w[2] = (uint32_t)(hl>>32);
hl = (uint64_t)al * bh + w[1];
w[1] = (uint32_t)hl;
carry = (uint32_t)(hl>>32);
hl = ((uint64_t)ah * bh + w[2]) + carry;
w[2] = (uint32_t)hl;
w[3] = (uint32_t)(hl>>32);
*hi = ((uint64_t)w[3]<<32) + w[2];
*lo = ((uint64_t)w[1]<<32) + w[0];
}
@ -82,9 +71,7 @@ static inline int
nlz(uint64_t x)
{
int n;
if (x == 0) return(64);
n = 0;
if (x <= 0x00000000FFFFFFFF) {n = n +32; x = x <<32;}
if (x <= 0x0000FFFFFFFFFFFF) {n = n +16; x = x <<16;}
@ -92,7 +79,6 @@ nlz(uint64_t x)
if (x <= 0x0FFFFFFFFFFFFFFF) {n = n + 4; x = x << 4;}
if (x <= 0x3FFFFFFFFFFFFFFF) {n = n + 2; x = x << 2;}
if (x <= 0x7FFFFFFFFFFFFFFF) {n = n + 1;}
return n;
}
@ -107,21 +93,16 @@ _mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
un32, un21, un10,
rhat, t;
int s;
assert(u1 < v);
s = nlz(v);
v = v << s;
vn1 = v >> 32;
vn0 = v & 0xFFFFFFFF;
t = (s == 0) ? 0 : u0 >> (64 - s);
un32 = (u1 << s) | t;
un10 = u0 << s;
un1 = un10 >> 32;
un0 = un10 & 0xFFFFFFFF;
q1 = un32 / vn1;
rhat = un32 - q1*vn1;
again1:
@ -130,7 +111,6 @@ again1:
rhat = rhat + vn1;
if (rhat < b) goto again1;
}
/*
* Before again1 we had:
* (1) q1*vn1 + rhat = un32
@ -157,7 +137,6 @@ again1:
* on the result.
*/
un21 = un32*b + un1 - q1*v;
q0 = un21 / vn1;
rhat = un21 - q0*vn1;
again2:
@ -166,55 +145,18 @@ again2:
rhat = rhat + vn1;
if (rhat < b) goto again2;
}
*q = q1*b + q0;
*r = (un21*b + un0 - q0*v) >> s;
}
#endif
/* END ANSI */
#elif defined(ASM)
static inline void
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
{
mpd_uint_t h, l;
__asm__ ( "mulq %3\n\t"
: "=d" (h), "=a" (l)
: "%a" (a), "rm" (b)
: "cc"
);
*hi = h;
*lo = l;
}
static inline void
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
mpd_uint_t d)
{
mpd_uint_t qq, rr;
__asm__ ( "divq %4\n\t"
: "=a" (qq), "=d" (rr)
: "a" (lo), "d" (hi), "rm" (d)
: "cc"
);
*q = qq;
*r = rr;
}
/* END GCC ASM */
#else
#error "need platform specific 128 bit multiplication and division"
#endif
#endif /* ANSI */
#define DIVMOD(q, r, v, d) *q = v / d; *r = v - *q * d
static inline void
_mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
{
assert(exp <= 19);
if (exp <= 9) {
if (exp <= 4) {
switch (exp) {
@ -251,240 +193,13 @@ _mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
case 16: DIVMOD(q, r, v, 10000000000000000ULL); break;
case 17: DIVMOD(q, r, v, 100000000000000000ULL); break;
case 18: DIVMOD(q, r, v, 1000000000000000000ULL); break;
case 19: DIVMOD(q, r, v, 10000000000000000000ULL); break; /* GCOV_NOT_REACHED */
case 19: DIVMOD(q, r, v, 10000000000000000000ULL); break;
default: unreachable;
}
}
}
}
/* END CONFIG_64 */
#elif defined(CONFIG_32)
#if defined(ANSI)
#if !defined(LEGACY_COMPILER)
static inline void
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
{
mpd_uuint_t hl;
hl = (mpd_uuint_t)a * b;
*hi = hl >> 32;
*lo = (mpd_uint_t)hl;
}
static inline void
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
mpd_uint_t d)
{
mpd_uuint_t hl;
hl = ((mpd_uuint_t)hi<<32) + lo;
*q = (mpd_uint_t)(hl / d); /* quotient is known to fit */
*r = (mpd_uint_t)(hl - (mpd_uuint_t)(*q) * d);
}
/* END ANSI + uint64_t */
#else
static inline void
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
{
uint16_t w[4], carry;
uint16_t ah, al, bh, bl;
uint32_t hl;
ah = (uint16_t)(a>>16); al = (uint16_t)a;
bh = (uint16_t)(b>>16); bl = (uint16_t)b;
hl = (uint32_t)al * bl;
w[0] = (uint16_t)hl;
carry = (uint16_t)(hl>>16);
hl = (uint32_t)ah * bl + carry;
w[1] = (uint16_t)hl;
w[2] = (uint16_t)(hl>>16);
hl = (uint32_t)al * bh + w[1];
w[1] = (uint16_t)hl;
carry = (uint16_t)(hl>>16);
hl = ((uint32_t)ah * bh + w[2]) + carry;
w[2] = (uint16_t)hl;
w[3] = (uint16_t)(hl>>16);
*hi = ((uint32_t)w[3]<<16) + w[2];
*lo = ((uint32_t)w[1]<<16) + w[0];
}
/*
* By Henry S. Warren: http://www.hackersdelight.org/HDcode/divlu.c.txt
* http://www.hackersdelight.org/permissions.htm:
* "You are free to use, copy, and distribute any of the code on this web
* site, whether modified by you or not. You need not give attribution."
*
* Slightly modified, comments are mine.
*/
static inline int
nlz(uint32_t x)
{
int n;
if (x == 0) return(32);
n = 0;
if (x <= 0x0000FFFF) {n = n +16; x = x <<16;}
if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;}
if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;}
if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;}
if (x <= 0x7FFFFFFF) {n = n + 1;}
return n;
}
static inline void
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t u1, mpd_uint_t u0,
mpd_uint_t v)
{
const mpd_uint_t b = 65536;
mpd_uint_t un1, un0,
vn1, vn0,
q1, q0,
un32, un21, un10,
rhat, t;
int s;
assert(u1 < v);
s = nlz(v);
v = v << s;
vn1 = v >> 16;
vn0 = v & 0xFFFF;
t = (s == 0) ? 0 : u0 >> (32 - s);
un32 = (u1 << s) | t;
un10 = u0 << s;
un1 = un10 >> 16;
un0 = un10 & 0xFFFF;
q1 = un32 / vn1;
rhat = un32 - q1*vn1;
again1:
if (q1 >= b || q1*vn0 > b*rhat + un1) {
q1 = q1 - 1;
rhat = rhat + vn1;
if (rhat < b) goto again1;
}
/*
* Before again1 we had:
* (1) q1*vn1 + rhat = un32
* (2) q1*vn1*b + rhat*b + un1 = un32*b + un1
*
* The statements inside the if-clause do not change the value
* of the left-hand side of (2), and the loop is only exited
* if q1*vn0 <= rhat*b + un1, so:
*
* (3) q1*vn1*b + q1*vn0 <= un32*b + un1
* (4) q1*v <= un32*b + un1
* (5) 0 <= un32*b + un1 - q1*v
*
* By (5) we are certain that the possible add-back step from
* Knuth's algorithm D is never required.
*
* Since the final quotient is less than 2**32, the following
* must be true:
*
* (6) un32*b + un1 - q1*v <= UINT32_MAX
*
* This means that in the following line, the high words
* of un32*b and q1*v can be discarded without any effect
* on the result.
*/
un21 = un32*b + un1 - q1*v;
q0 = un21 / vn1;
rhat = un21 - q0*vn1;
again2:
if (q0 >= b || q0*vn0 > b*rhat + un0) {
q0 = q0 - 1;
rhat = rhat + vn1;
if (rhat < b) goto again2;
}
*q = q1*b + q0;
*r = (un21*b + un0 - q0*v) >> s;
}
#endif /* END ANSI + LEGACY_COMPILER */
/* END ANSI */
#elif defined(ASM)
static inline void
_mpd_mul_words(mpd_uint_t *hi, mpd_uint_t *lo, mpd_uint_t a, mpd_uint_t b)
{
mpd_uint_t h, l;
__asm__ ( "mull %3\n\t"
: "=d" (h), "=a" (l)
: "%a" (a), "rm" (b)
: "cc"
);
*hi = h;
*lo = l;
}
static inline void
_mpd_div_words(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t hi, mpd_uint_t lo,
mpd_uint_t d)
{
mpd_uint_t qq, rr;
__asm__ ( "divl %4\n\t"
: "=a" (qq), "=d" (rr)
: "a" (lo), "d" (hi), "rm" (d)
: "cc"
);
*q = qq;
*r = rr;
}
/* END GCC ASM */
#else
#error "need platform specific 64 bit multiplication and division"
#endif
#define DIVMOD(q, r, v, d) *q = v / d; *r = v - *q * d
static inline void
_mpd_divmod_pow10(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t exp)
{
assert(exp <= 9);
if (exp <= 4) {
switch (exp) {
case 0: *q = v; *r = 0; break;
case 1: DIVMOD(q, r, v, 10UL); break;
case 2: DIVMOD(q, r, v, 100UL); break;
case 3: DIVMOD(q, r, v, 1000UL); break;
case 4: DIVMOD(q, r, v, 10000UL); break;
}
}
else {
switch (exp) {
case 5: DIVMOD(q, r, v, 100000UL); break;
case 6: DIVMOD(q, r, v, 1000000UL); break;
case 7: DIVMOD(q, r, v, 10000000UL); break;
case 8: DIVMOD(q, r, v, 100000000UL); break;
case 9: DIVMOD(q, r, v, 1000000000UL); break; /* GCOV_NOT_REACHED */
}
}
}
/* END CONFIG_32 */
/* NO CONFIG */
#else
#error "define CONFIG_64 or CONFIG_32"
#endif /* CONFIG */
static inline void
_mpd_div_word(mpd_uint_t *q, mpd_uint_t *r, mpd_uint_t v, mpd_uint_t d)
{
@ -499,7 +214,6 @@ _mpd_idiv_word(mpd_ssize_t *q, mpd_ssize_t *r, mpd_ssize_t v, mpd_ssize_t d)
*r = v - *q * d;
}
/** ------------------------------------------------------------
** Arithmetic with overflow checking
** ------------------------------------------------------------
@ -537,7 +251,6 @@ static inline mpd_size_t
mul_size_t(mpd_size_t a, mpd_size_t b)
{
mpd_uint_t hi, lo;
_mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
if (hi) {
mpd_err_fatal("mul_size_t(): overflow: check the context"); /* GCOV_NOT_REACHED */
@ -549,7 +262,6 @@ static inline mpd_size_t
add_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow)
{
mpd_size_t ret;
*overflow = 0;
ret = a + b;
if (ret < a) *overflow = 1;
@ -560,7 +272,6 @@ static inline mpd_size_t
mul_size_t_overflow(mpd_size_t a, mpd_size_t b, mpd_size_t *overflow)
{
mpd_uint_t lo;
_mpd_mul_words((mpd_uint_t *)overflow, &lo, (mpd_uint_t)a,
(mpd_uint_t)b);
return lo;
@ -578,15 +289,9 @@ mulmod_size_t(mpd_size_t a, mpd_size_t b, mpd_size_t m)
{
mpd_uint_t hi, lo;
mpd_uint_t q, r;
_mpd_mul_words(&hi, &lo, (mpd_uint_t)a, (mpd_uint_t)b);
_mpd_div_words(&q, &r, hi, lo, (mpd_uint_t)m);
return r;
}
#endif /* TYPEARITH_H */

View file

@ -1,20 +1,14 @@
#ifndef UMODARITH_H
#define UMODARITH_H
#include "libc/log/libfatal.internal.h"
#include "third_party/python/Modules/_decimal/libmpdec/constants.h"
#include "third_party/python/Modules/_decimal/libmpdec/mpdecimal.h"
#include "third_party/python/Modules/_decimal/libmpdec/typearith.h"
/* clang-format off */
/* Bignum: Low level routines for unsigned modular arithmetic. These are
used in the fast convolution functions for very large coefficients. */
/**************************************************************************/
/* ANSI modular arithmetic */
/**************************************************************************/
/*
* Restrictions: a < m and b < m
* ACL2 proof: umodarith.lisp: addmod-correct
@ -23,11 +17,9 @@ static inline mpd_uint_t
addmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
{
mpd_uint_t s;
s = a + b;
s = (s < a) ? s - m : s;
s = (s >= m) ? s - m : s;
return s;
}
@ -39,10 +31,8 @@ static inline mpd_uint_t
submod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
{
mpd_uint_t d;
d = a - b;
d = (a < b) ? d + m : d;
return d;
}
@ -54,13 +44,10 @@ static inline mpd_uint_t
ext_submod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
{
mpd_uint_t d;
a = (a >= m) ? a - m : a;
b = (b >= m) ? b - m : b;
d = a - b;
d = (a < b) ? d + m : d;
return d;
}
@ -73,10 +60,8 @@ static inline mpd_uint_t
dw_reduce(mpd_uint_t hi, mpd_uint_t lo, mpd_uint_t m)
{
mpd_uint_t r1, r2, w;
_mpd_div_word(&w, &r1, hi, m);
_mpd_div_words(&w, &r2, r1, lo, m);
return r2;
}
@ -89,142 +74,213 @@ static inline mpd_uint_t
dw_submod(mpd_uint_t a, mpd_uint_t hi, mpd_uint_t lo, mpd_uint_t m)
{
mpd_uint_t d, r;
r = dw_reduce(hi, lo, m);
d = a - r;
d = (a < r) ? d + m : d;
return d;
}
#ifdef CONFIG_64
/**************************************************************************/
/* 64-bit modular arithmetic */
/**************************************************************************/
/*
* A proof of the algorithm is in literature/mulmod-64.txt. An ACL2
* proof is in umodarith.lisp: section "Fast modular reduction".
/**
* Calculates (a × b) % 𝑝 where 𝑝 is special
*
* Algorithm: calculate (a * b) % p:
* In the whole comment, "" stands for "is congruent with".
*
* a) hi, lo <- a * b # Calculate a * b.
* Result of a × b in terms of high/low words:
*
* b) hi, lo <- R(hi, lo) # Reduce modulo p.
* (1) hi × 2 + lo = a × b
*
* c) Repeat step b) until 0 <= hi * 2**64 + lo < 2*p.
* Special primes:
*
* d) If the result is less than p, return lo. Otherwise return lo - p.
* (2) 𝑝 = 2 - z + 1, where z = 2
*
* i.e. 0xfffffffffffffc01
* 0xfffffffffffff001
* 0xffffffffff000001
* 0xffffffff00000001
* 0xfffffffc00000001
* 0xffffff0000000001
* 0xffffff0000000001
*
* Single step modular reduction:
*
* (3) R(hi, lo) = hi × z - hi + lo
*
*
* Strategy
* --------
*
* a) Set (hi, lo) to the result of a × b.
*
* b) Set (hi, lo) to the result of R(hi, lo).
*
* c) Repeat step b) until 0 hi × 2 + lo < 𝟸×𝑝.
*
* d) If the result is less than 𝑝, return lo. Otherwise return lo - 𝑝.
*
*
* The reduction step b) preserves congruence
* ------------------------------------------
*
* hi × 2 + lo hi × z - hi + lo (mod 𝑝)
*
* Proof:
* ~~~~~~
*
* hi × 2 + lo = (2 - z + 1) × hi + z × hi - hi + lo
*
* = 𝑝 × hi + z × hi - hi + lo
*
* z × hi - hi + lo (mod 𝑝)
*
*
* Maximum numbers of step b)
* --------------------------
*
* To avoid unnecessary formalism, define:
*
* def R(hi, lo, z):
* return divmod(hi * z - hi + lo, 2**64)
*
* For simplicity, assume hi=2-1, lo=2-1 after the
* initial multiplication a × b. This is of course impossible
* but certainly covers all cases.
*
* Then, for p1:
*
* z = 2³²
* hi = 2-1
* lo = 2-1
* p1 = 2 - z + 1
* hi, lo = R(hi, lo, z) # First reduction
* hi, lo = R(hi, lo, z) # Second reduction
* hi × 2 + lo < 2 × p1 # True
*
* For p2:
*
* z = 2³
* hi = 2-1
* lo = 2-1
* p2 = 2 - z + 1
* hi, lo = R(hi, lo, z) # First reduction
* hi, lo = R(hi, lo, z) # Second reduction
* hi, lo = R(hi, lo, z) # Third reduction
* hi × 2 + lo < 2 × p2 # True
*
* For p3:
*
* z = 2
* hi = 2-1
* lo = 2-1
* p3 = 2 - z + 1
* hi, lo = R(hi, lo, z) # First reduction
* hi, lo = R(hi, lo, z) # Second reduction
* hi, lo = R(hi, lo, z) # Third reduction
* hi × 2 + lo < 2 × p3 # True
*
* Step d) preserves congruence and yields a result < 𝑝
* ----------------------------------------------------
*
* Case hi = 0:
*
* Case lo < 𝑝: trivial.
*
* Case lo 𝑝:
*
* lo lo - 𝑝 (mod 𝑝) # result is congruent
*
* 𝑝 lo < 𝟸×𝑝 0 lo - 𝑝 < 𝑝 # result is in the correct range
*
* Case hi = 1:
*
* 𝑝 < 2 Λ 2 + lo < 𝟸×𝑝 lo < 𝑝 # lo is always less than 𝑝
*
* 2 + lo 2 + (lo - 𝑝) (mod 𝑝) # result is congruent
*
* = lo - 𝑝 # exactly the same value as the previous RHS
* # in uint64_t arithmetic.
*
* 𝑝 < 2 + lo < 𝟸×𝑝 0 < 2 + (lo - 𝑝) < 𝑝 # correct range
*
*
* [1] http://www.apfloat.org/apfloat/2.40/apfloat.pdf
*/
static inline mpd_uint_t
x64_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
{
mpd_uint_t hi, lo, x, y;
_mpd_mul_words(&hi, &lo, a, b);
if (m & (1ULL<<32)) { /* P1 */
/* first reduction */
x = y = hi;
hi >>= 32;
x = lo - x;
if (x > lo) hi--;
y <<= 32;
lo = y + x;
if (lo < y) hi++;
/* second reduction */
x = y = hi;
hi >>= 32;
x = lo - x;
if (x > lo) hi--;
y <<= 32;
lo = y + x;
if (lo < y) hi++;
return (hi || lo >= m ? lo - m : lo);
return hi || lo >= m ? lo - m : lo;
}
else if (m & (1ULL<<34)) { /* P2 */
/* first reduction */
x = y = hi;
hi >>= 30;
x = lo - x;
if (x > lo) hi--;
y <<= 34;
lo = y + x;
if (lo < y) hi++;
/* second reduction */
x = y = hi;
hi >>= 30;
x = lo - x;
if (x > lo) hi--;
y <<= 34;
lo = y + x;
if (lo < y) hi++;
/* third reduction */
x = y = hi;
hi >>= 30;
x = lo - x;
if (x > lo) hi--;
y <<= 34;
lo = y + x;
if (lo < y) hi++;
return (hi || lo >= m ? lo - m : lo);
return hi || lo >= m ? lo - m : lo;
}
else { /* P3 */
/* first reduction */
x = y = hi;
hi >>= 24;
x = lo - x;
if (x > lo) hi--;
y <<= 40;
lo = y + x;
if (lo < y) hi++;
/* second reduction */
x = y = hi;
hi >>= 24;
x = lo - x;
if (x > lo) hi--;
y <<= 40;
lo = y + x;
if (lo < y) hi++;
/* third reduction */
x = y = hi;
hi >>= 24;
x = lo - x;
if (x > lo) hi--;
y <<= 40;
lo = y + x;
if (lo < y) hi++;
return (hi || lo >= m ? lo - m : lo);
return hi || lo >= m ? lo - m : lo;
}
}
@ -247,375 +303,13 @@ static inline mpd_uint_t
x64_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
{
mpd_uint_t r = 1;
while (exp > 0) {
if (exp & 1)
r = x64_mulmod(r, base, umod);
base = x64_mulmod(base, base, umod);
exp >>= 1;
}
return r;
}
/* END CONFIG_64 */
#else /* CONFIG_32 */
/**************************************************************************/
/* 32-bit modular arithmetic */
/**************************************************************************/
#if defined(ANSI)
#if !defined(LEGACY_COMPILER)
/* HAVE_UINT64_T */
static inline mpd_uint_t
std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
{
return ((mpd_uuint_t) a * b) % m;
}
static inline void
std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
{
*a = ((mpd_uuint_t) *a * w) % m;
*b = ((mpd_uuint_t) *b * w) % m;
}
static inline void
std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
mpd_uint_t m)
{
*a0 = ((mpd_uuint_t) *a0 * b0) % m;
*a1 = ((mpd_uuint_t) *a1 * b1) % m;
}
/* END HAVE_UINT64_T */
#else
/* LEGACY_COMPILER */
static inline mpd_uint_t
std_mulmod(mpd_uint_t a, mpd_uint_t b, mpd_uint_t m)
{
mpd_uint_t hi, lo, q, r;
_mpd_mul_words(&hi, &lo, a, b);
_mpd_div_words(&q, &r, hi, lo, m);
return r;
}
static inline void
std_mulmod2c(mpd_uint_t *a, mpd_uint_t *b, mpd_uint_t w, mpd_uint_t m)
{
*a = std_mulmod(*a, w, m);
*b = std_mulmod(*b, w, m);
}
static inline void
std_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
mpd_uint_t m)
{
*a0 = std_mulmod(*a0, b0, m);
*a1 = std_mulmod(*a1, b1, m);
}
/* END LEGACY_COMPILER */
#endif
static inline mpd_uint_t
std_powmod(mpd_uint_t base, mpd_uint_t exp, mpd_uint_t umod)
{
mpd_uint_t r = 1;
while (exp > 0) {
if (exp & 1)
r = std_mulmod(r, base, umod);
base = std_mulmod(base, base, umod);
exp >>= 1;
}
return r;
}
#endif /* ANSI CONFIG_32 */
/**************************************************************************/
/* Pentium Pro modular arithmetic */
/**************************************************************************/
/*
* A proof of the algorithm is in literature/mulmod-ppro.txt. The FPU
* control word must be set to 64-bit precision and truncation mode
* prior to using these functions.
*
* Algorithm: calculate (a * b) % p:
*
* p := prime < 2**31
* pinv := (long double)1.0 / p (precalculated)
*
* a) n = a * b # Calculate exact product.
* b) qest = n * pinv # Calculate estimate for q = n / p.
* c) q = (qest+2**63)-2**63 # Truncate qest to the exact quotient.
* d) r = n - q * p # Calculate remainder.
*
* Remarks:
*
* - p = dmod and pinv = dinvmod.
* - dinvmod points to an array of three uint32_t, which is interpreted
* as an 80 bit long double by fldt.
* - Intel compilers prior to version 11 do not seem to handle the
* __GNUC__ inline assembly correctly.
* - random tests are provided in tests/extended/ppro_mulmod.c
*/
#if defined(PPRO)
#if defined(ASM)
/* Return (a * b) % dmod */
static inline mpd_uint_t
ppro_mulmod(mpd_uint_t a, mpd_uint_t b, double *dmod, uint32_t *dinvmod)
{
mpd_uint_t retval;
__asm__ (
"fildl %2\n\t"
"fildl %1\n\t"
"fmulp %%st, %%st(1)\n\t"
"fldt (%4)\n\t"
"fmul %%st(1), %%st\n\t"
"flds %5\n\t"
"fadd %%st, %%st(1)\n\t"
"fsubrp %%st, %%st(1)\n\t"
"fldl (%3)\n\t"
"fmulp %%st, %%st(1)\n\t"
"fsubrp %%st, %%st(1)\n\t"
"fistpl %0\n\t"
: "=m" (retval)
: "m" (a), "m" (b), "r" (dmod), "r" (dinvmod), "m" (MPD_TWO63)
: "st", "memory"
);
return retval;
}
/*
* Two modular multiplications in parallel:
* *a0 = (*a0 * w) % dmod
* *a1 = (*a1 * w) % dmod
*/
static inline void
ppro_mulmod2c(mpd_uint_t *a0, mpd_uint_t *a1, mpd_uint_t w,
double *dmod, uint32_t *dinvmod)
{
__asm__ (
"fildl %2\n\t"
"fildl (%1)\n\t"
"fmul %%st(1), %%st\n\t"
"fxch %%st(1)\n\t"
"fildl (%0)\n\t"
"fmulp %%st, %%st(1) \n\t"
"fldt (%4)\n\t"
"flds %5\n\t"
"fld %%st(2)\n\t"
"fmul %%st(2)\n\t"
"fadd %%st(1)\n\t"
"fsub %%st(1)\n\t"
"fmull (%3)\n\t"
"fsubrp %%st, %%st(3)\n\t"
"fxch %%st(2)\n\t"
"fistpl (%0)\n\t"
"fmul %%st(2)\n\t"
"fadd %%st(1)\n\t"
"fsubp %%st, %%st(1)\n\t"
"fmull (%3)\n\t"
"fsubrp %%st, %%st(1)\n\t"
"fistpl (%1)\n\t"
: : "r" (a0), "r" (a1), "m" (w),
"r" (dmod), "r" (dinvmod),
"m" (MPD_TWO63)
: "st", "memory"
);
}
/*
* Two modular multiplications in parallel:
* *a0 = (*a0 * b0) % dmod
* *a1 = (*a1 * b1) % dmod
*/
static inline void
ppro_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
double *dmod, uint32_t *dinvmod)
{
__asm__ (
"fildl %3\n\t"
"fildl (%2)\n\t"
"fmulp %%st, %%st(1)\n\t"
"fildl %1\n\t"
"fildl (%0)\n\t"
"fmulp %%st, %%st(1)\n\t"
"fldt (%5)\n\t"
"fld %%st(2)\n\t"
"fmul %%st(1), %%st\n\t"
"fxch %%st(1)\n\t"
"fmul %%st(2), %%st\n\t"
"flds %6\n\t"
"fldl (%4)\n\t"
"fxch %%st(3)\n\t"
"fadd %%st(1), %%st\n\t"
"fxch %%st(2)\n\t"
"fadd %%st(1), %%st\n\t"
"fxch %%st(2)\n\t"
"fsub %%st(1), %%st\n\t"
"fxch %%st(2)\n\t"
"fsubp %%st, %%st(1)\n\t"
"fxch %%st(1)\n\t"
"fmul %%st(2), %%st\n\t"
"fxch %%st(1)\n\t"
"fmulp %%st, %%st(2)\n\t"
"fsubrp %%st, %%st(3)\n\t"
"fsubrp %%st, %%st(1)\n\t"
"fxch %%st(1)\n\t"
"fistpl (%2)\n\t"
"fistpl (%0)\n\t"
: : "r" (a0), "m" (b0), "r" (a1), "m" (b1),
"r" (dmod), "r" (dinvmod),
"m" (MPD_TWO63)
: "st", "memory"
);
}
/* END PPRO GCC ASM */
#elif defined(MASM)
/* Return (a * b) % dmod */
static inline mpd_uint_t __cdecl
ppro_mulmod(mpd_uint_t a, mpd_uint_t b, double *dmod, uint32_t *dinvmod)
{
mpd_uint_t retval;
__asm {
mov eax, dinvmod
mov edx, dmod
fild b
fild a
fmulp st(1), st
fld TBYTE PTR [eax]
fmul st, st(1)
fld MPD_TWO63
fadd st(1), st
fsubp st(1), st
fld QWORD PTR [edx]
fmulp st(1), st
fsubp st(1), st
fistp retval
}
return retval;
}
/*
* Two modular multiplications in parallel:
* *a0 = (*a0 * w) % dmod
* *a1 = (*a1 * w) % dmod
*/
static inline mpd_uint_t __cdecl
ppro_mulmod2c(mpd_uint_t *a0, mpd_uint_t *a1, mpd_uint_t w,
double *dmod, uint32_t *dinvmod)
{
__asm {
mov ecx, dmod
mov edx, a1
mov ebx, dinvmod
mov eax, a0
fild w
fild DWORD PTR [edx]
fmul st, st(1)
fxch st(1)
fild DWORD PTR [eax]
fmulp st(1), st
fld TBYTE PTR [ebx]
fld MPD_TWO63
fld st(2)
fmul st, st(2)
fadd st, st(1)
fsub st, st(1)
fmul QWORD PTR [ecx]
fsubp st(3), st
fxch st(2)
fistp DWORD PTR [eax]
fmul st, st(2)
fadd st, st(1)
fsubrp st(1), st
fmul QWORD PTR [ecx]
fsubp st(1), st
fistp DWORD PTR [edx]
}
}
/*
* Two modular multiplications in parallel:
* *a0 = (*a0 * b0) % dmod
* *a1 = (*a1 * b1) % dmod
*/
static inline void __cdecl
ppro_mulmod2(mpd_uint_t *a0, mpd_uint_t b0, mpd_uint_t *a1, mpd_uint_t b1,
double *dmod, uint32_t *dinvmod)
{
__asm {
mov ecx, dmod
mov edx, a1
mov ebx, dinvmod
mov eax, a0
fild b1
fild DWORD PTR [edx]
fmulp st(1), st
fild b0
fild DWORD PTR [eax]
fmulp st(1), st
fld TBYTE PTR [ebx]
fld st(2)
fmul st, st(1)
fxch st(1)
fmul st, st(2)
fld DWORD PTR MPD_TWO63
fld QWORD PTR [ecx]
fxch st(3)
fadd st, st(1)
fxch st(2)
fadd st, st(1)
fxch st(2)
fsub st, st(1)
fxch st(2)
fsubrp st(1), st
fxch st(1)
fmul st, st(2)
fxch st(1)
fmulp st(2), st
fsubp st(3), st
fsubp st(1), st
fxch st(1)
fistp DWORD PTR [edx]
fistp DWORD PTR [eax]
}
}
#endif /* PPRO MASM (_MSC_VER) */
/* Return (base ** exp) % dmod */
static inline mpd_uint_t
ppro_powmod(mpd_uint_t base, mpd_uint_t exp, double *dmod, uint32_t *dinvmod)
{
mpd_uint_t r = 1;
while (exp > 0) {
if (exp & 1)
r = ppro_mulmod(r, base, dmod, dinvmod);
base = ppro_mulmod(base, base, dmod, dinvmod);
exp >>= 1;
}
return r;
}
#endif /* PPRO */
#endif /* CONFIG_32 */
#endif /* UMODARITH_H */

View file

@ -1301,3 +1301,8 @@ PyInit__functools(void)
}
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__functools = {
"_functools",
PyInit__functools,
};

View file

@ -1,18 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
Copyright 2021 Justine Alexandra Roberts Tunney
Copying of this file is authorized only if (1) you are Justine Tunney,
or (2) you make absolutely no changes to your copy.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#define PY_SSIZE_T_CLEAN
#include "libc/calls/calls.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "third_party/mbedtls/error.h"
#include "third_party/mbedtls/md.h"
#include "third_party/mbedtls/pkcs5.h"
#include "third_party/python/Include/Python.h"
#include "third_party/python/Include/ezprint.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/object.h"
#include "third_party/python/Include/pyerrors.h"
#include "third_party/python/Include/pystrhex.h"
#include "third_party/python/Include/structmember.h"
#include "third_party/python/Include/yoink.h"
@ -27,6 +45,7 @@ PYTHON_PROVIDE("_hashlib.__name__");
PYTHON_PROVIDE("_hashlib.__package__");
PYTHON_PROVIDE("_hashlib.__spec__");
PYTHON_PROVIDE("_hashlib.new");
PYTHON_PROVIDE("_hashlib.pbkdf2_hmac");
PYTHON_PROVIDE("_hashlib.mbedtls_md5");
PYTHON_PROVIDE("_hashlib.mbedtls_md_meth_names");
PYTHON_PROVIDE("_hashlib.mbedtls_sha1");
@ -35,52 +54,39 @@ PYTHON_PROVIDE("_hashlib.mbedtls_sha256");
PYTHON_PROVIDE("_hashlib.mbedtls_sha384");
PYTHON_PROVIDE("_hashlib.mbedtls_sha512");
#include "third_party/python/Modules/clinic/_hashmbedtls.inc"
/*[clinic input]
module _hashlib
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c2b4ff081bac4be1]*/
#define MUNCH_SIZE 65536
#ifndef HASH_OBJ_CONSTRUCTOR
#define HASH_OBJ_CONSTRUCTOR 0
#endif
typedef struct {
struct Hasher {
PyObject_HEAD
PyObject *name;
mbedtls_md_context_t ctx;
#ifdef WITH_THREAD
PyThread_type_lock lock;
#endif
} EVPobject;
};
static PyTypeObject EVPtype;
static PyObject *CONST_MD5_name_obj;
static PyObject *CONST_SHA1_name_obj;
static PyObject *CONST_SHA224_name_obj;
static PyObject *CONST_SHA256_name_obj;
static PyObject *CONST_SHA384_name_obj;
static PyObject *CONST_SHA512_name_obj;
static PyObject *CONST_BLAKE2B256_name_obj;
static PyTypeObject hasher_type;
static const PyObject *CONST_MD5_name_obj;
static const PyObject *CONST_SHA1_name_obj;
static const PyObject *CONST_SHA224_name_obj;
static const PyObject *CONST_SHA256_name_obj;
static const PyObject *CONST_SHA384_name_obj;
static const PyObject *CONST_SHA512_name_obj;
static const PyObject *CONST_BLAKE2B256_name_obj;
static PyObject *
SetMbedtlsError(PyObject *exc, int rc)
{
char b[128];
mbedtls_strerror(rc, b, sizeof(b));
stpcpy(b, "MBEDTLS - ");
mbedtls_strerror(rc, b + 10, sizeof(b) - 10);
PyErr_SetString(exc, b);
return NULL;
}
static EVPobject *
newEVPobject(PyObject *name)
static struct Hasher *
hasher_new(PyObject *name)
{
EVPobject *self;
if ((self = PyObject_New(EVPobject, &EVPtype))) {
struct Hasher *self;
if ((self = PyObject_New(struct Hasher, &hasher_type))) {
mbedtls_md_init(&self->ctx);
Py_INCREF(name);
self->name = name;
@ -92,28 +98,13 @@ newEVPobject(PyObject *name)
}
static int
EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
hasher_hash(struct Hasher *self, const void *p, Py_ssize_t n)
{
int rc;
unsigned int process;
const unsigned char *cp;
for (cp = vp; 0 < len; len -= process, cp += process) {
if (len > MUNCH_SIZE) {
process = MUNCH_SIZE;
} else {
process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int);
}
if ((rc = mbedtls_md_update(&self->ctx, cp, process)) < 0) {
return rc;
}
}
return 0;
return mbedtls_md_update(&self->ctx, p, n);
}
/* Internal methods for a hash object */
static void
EVP_dealloc(EVPobject *self)
hasher_dealloc(struct Hasher *self)
{
#ifdef WITH_THREAD
if (self->lock)
@ -125,7 +116,7 @@ EVP_dealloc(EVPobject *self)
}
static int
locked_mbedtls_md_clone(mbedtls_md_context_t *new_ctx_p, EVPobject *self)
mbedtls_md_clone_locked(mbedtls_md_context_t *new_ctx_p, struct Hasher *self)
{
int rc;
ENTER_HASHLIB(self);
@ -136,29 +127,34 @@ locked_mbedtls_md_clone(mbedtls_md_context_t *new_ctx_p, EVPobject *self)
return rc;
}
/* External methods for a hash object */
PyDoc_STRVAR(EVP_copy__doc__, "Return a copy of the hash object.");
PyDoc_STRVAR(hashlib_copy__doc__, "\
copy($self, /)\n\
--\n\
\n\
Return a copy of the hash object.");
static PyObject *
EVP_copy(EVPobject *self, PyObject *unused)
hashlib_copy(struct Hasher *self, PyObject *unused)
{
int rc;
EVPobject *newobj;
if ((newobj = newEVPobject(self->name))) {
if ((rc = locked_mbedtls_md_clone(&newobj->ctx, self))) {
EVP_dealloc(newobj);
struct Hasher *newobj;
if ((newobj = hasher_new(self->name))) {
if ((rc = mbedtls_md_clone_locked(&newobj->ctx, self))) {
hasher_dealloc(newobj);
return SetMbedtlsError(PyExc_ValueError, rc);
}
}
return (PyObject *)newobj;
}
PyDoc_STRVAR(EVP_digest__doc__,
"Return the digest value as a bytes object.");
PyDoc_STRVAR(hashlib_digest__doc__, "\
digest($self, /)\n\
--\n\
\n\
Return the digest value as a bytes object.");
static PyObject *
EVP_digest(EVPobject *self, PyObject *unused)
hashlib_digest(struct Hasher *self, PyObject *unused)
{
int rc;
PyObject *retval;
@ -166,7 +162,7 @@ EVP_digest(EVPobject *self, PyObject *unused)
mbedtls_md_context_t temp_ctx;
unsigned char digest[MBEDTLS_MD_MAX_SIZE];
mbedtls_md_init(&temp_ctx);
if (!(rc = locked_mbedtls_md_clone(&temp_ctx, self))) {
if (!(rc = mbedtls_md_clone_locked(&temp_ctx, self))) {
digest_size = mbedtls_md_get_size(temp_ctx.md_info);
if (!(rc = mbedtls_md_finish(&temp_ctx, digest))) {
retval = PyBytes_FromStringAndSize((const char *)digest, digest_size);
@ -180,11 +176,14 @@ EVP_digest(EVPobject *self, PyObject *unused)
return retval;
}
PyDoc_STRVAR(EVP_hexdigest__doc__,
"Return the digest value as a string of hexadecimal digits.");
PyDoc_STRVAR(hashlib_hexdigest__doc__, "\
hexdigest($self, /)\n\
--\n\
\n\
Return the digest value as a string of hexadecimal digits.");
static PyObject *
EVP_hexdigest(EVPobject *self, PyObject *unused)
hashlib_hexdigest(struct Hasher *self, PyObject *unused)
{
int rc;
PyObject *retval;
@ -192,7 +191,7 @@ EVP_hexdigest(EVPobject *self, PyObject *unused)
mbedtls_md_context_t temp_ctx;
unsigned char digest[MBEDTLS_MD_MAX_SIZE];
mbedtls_md_init(&temp_ctx);
if (!(rc = locked_mbedtls_md_clone(&temp_ctx, self))) {
if (!(rc = mbedtls_md_clone_locked(&temp_ctx, self))) {
digest_size = mbedtls_md_get_size(temp_ctx.md_info);
if (!(rc = mbedtls_md_finish(&temp_ctx, digest))) {
retval = _Py_strhex((const char *)digest, digest_size);
@ -206,338 +205,210 @@ EVP_hexdigest(EVPobject *self, PyObject *unused)
return retval;
}
PyDoc_STRVAR(EVP_update__doc__,
"Update this hash object's state with the provided string.");
PyDoc_STRVAR(hashlib_update__doc__, "\
update($self, bytes, /)\n\
--\n\
\n\
Update this hash object's state with the provided string.");
static PyObject *
EVP_update(EVPobject *self, PyObject *args)
hashlib_update(struct Hasher *self, PyObject *args)
{
PyObject *obj;
Py_buffer view;
if (!PyArg_ParseTuple(args, "O:update", &obj)) return 0;
GET_BUFFER_VIEW_OR_ERROUT(obj, &view);
EVP_hash(self, view.buf, view.len);
PyBuffer_Release(&view);
Py_buffer data;
if (!PyArg_ParseTuple(args, "y*:update", &data)) return 0;
hasher_hash(self, data.buf, data.len);
PyBuffer_Release(&data);
Py_RETURN_NONE;
}
static PyMethodDef EVP_methods[] = {
{"update", (PyCFunction)EVP_update, METH_VARARGS, EVP_update__doc__},
{"digest", (PyCFunction)EVP_digest, METH_NOARGS, EVP_digest__doc__},
{"hexdigest", (PyCFunction)EVP_hexdigest, METH_NOARGS, EVP_hexdigest__doc__},
{"copy", (PyCFunction)EVP_copy, METH_NOARGS, EVP_copy__doc__},
{NULL, NULL} /* sentinel */
static PyMethodDef hashlib_methods[] = {
{"update", (PyCFunction)hashlib_update, METH_VARARGS, hashlib_update__doc__},
{"digest", (PyCFunction)hashlib_digest, METH_NOARGS, hashlib_digest__doc__},
{"hexdigest", (PyCFunction)hashlib_hexdigest, METH_NOARGS, hashlib_hexdigest__doc__},
{"copy", (PyCFunction)hashlib_copy, METH_NOARGS, hashlib_copy__doc__},
{0}
};
static PyObject *
EVP_get_block_size(EVPobject *self, void *closure)
hashlib_get_block_size(struct Hasher *self, void *closure)
{
return PyLong_FromLong(mbedtls_md_get_block_size(self->ctx.md_info));
}
static PyObject *
EVP_get_digest_size(EVPobject *self, void *closure)
hashlib_get_digest_size(struct Hasher *self, void *closure)
{
return PyLong_FromLong(mbedtls_md_get_size(self->ctx.md_info));
}
static PyMemberDef EVP_members[] = {
{"name", T_OBJECT, offsetof(EVPobject, name), READONLY, PyDoc_STR("algorithm name.")},
{NULL}
static PyMemberDef hashlib_members[] = {
{"name", T_OBJECT, offsetof(struct Hasher, name), READONLY, PyDoc_STR("algorithm name.")},
{0}
};
static PyGetSetDef EVP_getseters[] = {
{"digest_size", (getter)EVP_get_digest_size, NULL, NULL, NULL},
{"block_size", (getter)EVP_get_block_size, NULL, NULL, NULL},
{NULL}
static PyGetSetDef hashlib_getseters[] = {
{"digest_size", (getter)hashlib_get_digest_size, NULL, NULL, NULL},
{"block_size", (getter)hashlib_get_block_size, NULL, NULL, NULL},
{0}
};
static PyObject *
EVP_repr(EVPobject *self)
hasher_repr(struct Hasher *self)
{
return PyUnicode_FromFormat("<%U HASH object @ %p>", self->name, self);
}
#if HASH_OBJ_CONSTRUCTOR
#error wut
static int
EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"name", "string", NULL};
PyObject *name_obj = NULL;
PyObject *data_obj = NULL;
Py_buffer view;
char *nameStr;
const mbedtls_md_info_t *digest;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:HASH", kwlist,
&name_obj, &data_obj)) {
return -1;
}
if (data_obj)
GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);
if (!PyArg_Parse(name_obj, "s", &nameStr)) {
PyErr_SetString(PyExc_TypeError, "name must be a string");
if (data_obj)
PyBuffer_Release(&view);
return -1;
}
digest = mbedtls_md_info_from_string(nameStr);
if (!digest) {
PyErr_SetString(PyExc_ValueError, "unknown hash function");
if (data_obj)
PyBuffer_Release(&view);
return -1;
}
if (!EVP_DigestInit(self->ctx, digest)) {
SetMbedtlsError(PyExc_ValueError);
if (data_obj)
PyBuffer_Release(&view);
return -1;
}
Py_INCREF(name_obj);
Py_XSETREF(self->name, name_obj);
if (data_obj) {
if (view.len >= HASHLIB_GIL_MINSIZE) {
Py_BEGIN_ALLOW_THREADS
EVP_hash(self, view.buf, view.len);
Py_END_ALLOW_THREADS
} else {
EVP_hash(self, view.buf, view.len);
}
PyBuffer_Release(&view);
}
return 0;
}
#endif
PyDoc_STRVAR(hashtype_doc,
"A hash represents the object used to calculate a checksum of a\n\
string of information.\n\
\n\
Methods:\n\
\n\
update() -- updates the current digest with an additional string\n\
digest() -- return the current digest value\n\
hexdigest() -- return the current digest as a string of hexadecimal digits\n\
copy() -- return a copy of the current hash object\n\
\n\
Attributes:\n\
\n\
name -- the hash algorithm being used by this object\n\
digest_size -- number of bytes in this hashes output\n");
static PyTypeObject EVPtype = {
static PyTypeObject hasher_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_hashlib.HASH", /*tp_name*/
sizeof(EVPobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)EVP_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
(reprfunc)EVP_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
hashtype_doc, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
EVP_methods, /* tp_methods */
EVP_members, /* tp_members */
EVP_getseters, /* tp_getset */
#if 1
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
#endif
#if HASH_OBJ_CONSTRUCTOR
(initproc)EVP_tp_init, /* tp_init */
#endif
/*tp_name*/ "_hashlib.HASH",
/*tp_basicsize*/ sizeof(struct Hasher),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)hasher_dealloc,
/*tp_print*/ 0,
/*tp_getattr*/ 0,
/*tp_setattr*/ 0,
/*tp_reserved*/ 0,
/*tp_repr*/ (reprfunc)hasher_repr,
/*tp_as_number*/ 0,
/*tp_as_sequence*/ 0,
/*tp_as_mapping*/ 0,
/*tp_hash*/ 0,
/*tp_call*/ 0,
/*tp_str*/ 0,
/*tp_getattro*/ 0,
/*tp_setattro*/ 0,
/*tp_as_buffer*/ 0,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ hashtype_doc,
/*tp_traverse*/ 0,
/*tp_clear*/ 0,
/*tp_richcompare*/ 0,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ 0,
/*tp_iternext*/ 0,
/*tp_methods*/ hashlib_methods,
/*tp_members*/ hashlib_members,
/*tp_getset*/ hashlib_getseters,
/*tp_base*/ 0,
/*tp_dict*/ 0,
/*tp_descr_get*/ 0,
/*tp_descr_set*/ 0,
/*tp_dictoffset*/ 0,
};
static PyObject *
EVPnew(PyObject *name_obj,
const mbedtls_md_info_t *digest,
const unsigned char *cp, Py_ssize_t len)
NewHasher(PyObject *name_obj,
const mbedtls_md_info_t *digest,
void *p, Py_ssize_t n)
{
int rc;
EVPobject *self;
struct Hasher *self;
if (!digest) {
PyErr_SetString(PyExc_ValueError, "unsupported hash type");
return NULL;
}
if ((self = newEVPobject(name_obj)) == NULL)
return NULL;
if ((rc = mbedtls_md_setup(&self->ctx, digest, 0))) {
if (!(self = hasher_new(name_obj))) return 0;
if ((rc = mbedtls_md_setup(&self->ctx, digest, 0)) ||
(rc = mbedtls_md_starts(&self->ctx))) {
SetMbedtlsError(PyExc_ValueError, rc);
Py_DECREF(self);
return NULL;
}
if (cp && len) {
if (len >= HASHLIB_GIL_MINSIZE) {
if (n) {
if (n >= HASHLIB_GIL_MINSIZE) {
Py_BEGIN_ALLOW_THREADS
EVP_hash(self, cp, len);
hasher_hash(self, p, n);
Py_END_ALLOW_THREADS
} else {
EVP_hash(self, cp, len);
hasher_hash(self, p, n);
}
}
return (PyObject *)self;
}
/* The module-level function: new() */
PyDoc_STRVAR(EVP_new__doc__,
"Return a new hash object using the named algorithm.\n\
PyDoc_STRVAR(hashlib_new__doc__,
"new($module, name, string=b'')\n\
--\n\
\n\
Return a new hash object using the named algorithm.\n\
An optional string argument may be provided and will be\n\
automatically hashed.\n\
\n\
The MD5 and SHA1 algorithms are always supported.\n");
static PyObject *
EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
hashlib_new(PyObject *self, PyObject *args, PyObject *kwdict)
{
static char *kwlist[] = {"name", "string", NULL};
PyObject *name_obj = NULL;
PyObject *data_obj = NULL;
Py_buffer view = { 0 };
PyObject *ret_obj;
char *name;
const mbedtls_md_info_t *digest;
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|O:new", kwlist,
&name_obj, &data_obj)) {
PyObject *res;
Py_buffer data = {0};
PyObject *name_obj = 0;
static char *kwlist[] = {"name", "string", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|y*:new", kwlist,
&name_obj, &data)) {
return NULL;
}
if (!PyArg_Parse(name_obj, "s", &name)) {
PyErr_SetString(PyExc_TypeError, "name must be a string");
PyBuffer_Release(&data);
return NULL;
}
if (data_obj)
GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);
digest = mbedtls_md_info_from_string(name);
ret_obj = EVPnew(name_obj, digest, (unsigned char*)view.buf, view.len);
if (data_obj)
PyBuffer_Release(&view);
return ret_obj;
res = NewHasher(name_obj, mbedtls_md_info_from_string(name),
data.buf, data.len);
PyBuffer_Release(&data);
return res;
}
#if (MBEDTLS_VERSION_NUMBER >= 0x10000000 && !defined(MBEDTLS_NO_HMAC) \
&& !defined(MBEDTLS_NO_SHA))
#define PY_PBKDF2_HMAC 1
#if !HAS_FAST_PKCS5_PBKDF2_HMAC
/* Improved implementation of PKCS5_PBKDF2_HMAC()
*
* PKCS5_PBKDF2_HMAC_fast() hashes the password exactly one time instead of
* `iter` times. Today (2013) the iteration count is typically 100,000 or
* more. The improved algorithm is not subject to a Denial-of-Service
* vulnerability with overly large passwords.
*
* Also Mbedtls < 1.0 don't provide PKCS5_PBKDF2_HMAC(), only
* PKCS5_PBKDF2_SHA1.
*/
static int
PKCS5_PBKDF2_HMAC_fast(const char *pass, int passlen,
const unsigned char *salt, int saltlen,
int iter, const mbedtls_md_info_t *digest,
int keylen, unsigned char *out)
pbkdf2(const mbedtls_md_info_t *digest,
const void *pass, size_t passlen,
const void *salt, size_t saltlen,
size_t c, size_t dklen, void *dk)
{
unsigned char digtmp[MBEDTLS_MD_MAX_SIZE], *p, itmp[4];
int cplen, j, k, tkeylen, mdlen;
unsigned long i = 1;
HMAC_CTX hctx_tpl, hctx;
mdlen = mbedtls_md_get_size(digest);
if (mdlen < 0)
return 0;
HMAC_CTX_init(&hctx_tpl);
HMAC_CTX_init(&hctx);
p = out;
tkeylen = keylen;
if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
int rc;
mbedtls_md_context_t ctx;
mbedtls_md_init(&ctx);
if (!(rc = mbedtls_md_setup(&ctx, digest, 1))) {
rc = mbedtls_pkcs5_pbkdf2_hmac(
&ctx, pass, passlen, salt, saltlen, c, dklen, dk);
}
while (tkeylen) {
if (tkeylen > mdlen)
cplen = mdlen;
else
cplen = tkeylen;
/* We are unlikely to ever use more than 256 blocks (5120 bits!)
* but just in case...
*/
itmp[0] = (unsigned char)((i >> 24) & 0xff);
itmp[1] = (unsigned char)((i >> 16) & 0xff);
itmp[2] = (unsigned char)((i >> 8) & 0xff);
itmp[3] = (unsigned char)(i & 0xff);
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, salt, saltlen)
|| !HMAC_Update(&hctx, itmp, 4)
|| !HMAC_Final(&hctx, digtmp, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
}
HMAC_CTX_cleanup(&hctx);
memcpy(p, digtmp, cplen);
for (j = 1; j < iter; j++) {
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, digtmp, mdlen)
|| !HMAC_Final(&hctx, digtmp, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
}
HMAC_CTX_cleanup(&hctx);
for (k = 0; k < cplen; k++) {
p[k] ^= digtmp[k];
}
}
tkeylen-= cplen;
i++;
p+= cplen;
}
HMAC_CTX_cleanup(&hctx_tpl);
return 1;
mbedtls_md_free(&ctx);
return rc;
}
#endif
PyDoc_STRVAR(pbkdf2_hmac__doc__,
"pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) -> key\n\
"pbkdf2_hmac($module, hash_name, password, salt, iterations, dklen=None)\n\
--\n\
\n\
Password based key derivation function 2 (PKCS #5 v2.0) with HMAC as\n\
Password based key derivation function 2 (PKCS #5 v2.o) with HMAC as\n\
pseudorandom function.");
static PyObject *
pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict)
{
static char *kwlist[] = {"hash_name", "password", "salt", "iterations",
"dklen", NULL};
PyObject *key_obj = NULL, *dklen_obj = Py_None;
static char *kwlist[] = {
"hash_name",
"password",
"salt",
"iterations",
"dklen",
NULL,
};
int rc;
char *name, *key;
Py_buffer password, salt;
long iterations, dklen;
int retval;
PyObject *key_obj = NULL;
PyObject *dklen_obj = Py_None;
const mbedtls_md_info_t *digest;
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "sy*y*l|O:pbkdf2_hmac",
kwlist, &name, &password, &salt,
@ -594,21 +465,12 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict)
}
key = PyBytes_AS_STRING(key_obj);
Py_BEGIN_ALLOW_THREADS
#if HAS_FAST_PKCS5_PBKDF2_HMAC
retval = PKCS5_PBKDF2_HMAC((char*)password.buf, (int)password.len,
(unsigned char *)salt.buf, (int)salt.len,
iterations, digest, dklen,
(unsigned char *)key);
#else
retval = PKCS5_PBKDF2_HMAC_fast((char*)password.buf, (int)password.len,
(unsigned char *)salt.buf, (int)salt.len,
iterations, digest, dklen,
(unsigned char *)key);
#endif
rc = pbkdf2(digest, password.buf, password.len,
salt.buf, salt.len, iterations, dklen, key);
Py_END_ALLOW_THREADS
if (retval) {
if (rc) {
Py_CLEAR(key_obj);
SetMbedtlsError(PyExc_ValueError, retval);
SetMbedtlsError(PyExc_ValueError, rc);
goto end;
}
end:
@ -616,120 +478,6 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict)
PyBuffer_Release(&salt);
return key_obj;
}
#endif
#if MBEDTLS_VERSION_NUMBER > 0x10100000L && !defined(MBEDTLS_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)
#define PY_SCRYPT 1
/* XXX: Parameters salt, n, r and p should be required keyword-only parameters.
They are optional in the Argument Clinic declaration only due to a
limitation of PyArg_ParseTupleAndKeywords. */
/*[clinic input]
_hashlib.scrypt
password: Py_buffer
*
salt: Py_buffer = None
n as n_obj: object(subclass_of='&PyLong_Type') = None
r as r_obj: object(subclass_of='&PyLong_Type') = None
p as p_obj: object(subclass_of='&PyLong_Type') = None
maxmem: long = 0
dklen: long = 64
scrypt password-based key derivation function.
[clinic start generated code]*/
static PyObject *
_hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt,
PyObject *n_obj, PyObject *r_obj, PyObject *p_obj,
long maxmem, long dklen)
/*[clinic end generated code: output=14849e2aa2b7b46c input=48a7d63bf3f75c42]*/
{
PyObject *key_obj = NULL;
char *key;
int retval;
unsigned long n, r, p;
if (password->len > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"password is too long.");
return NULL;
}
if (salt->buf == NULL) {
PyErr_SetString(PyExc_TypeError,
"salt is required");
return NULL;
}
if (salt->len > INT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"salt is too long.");
return NULL;
}
n = PyLong_AsUnsignedLong(n_obj);
if (n == (unsigned long) -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"n is required and must be an unsigned int");
return NULL;
}
if (n < 2 || n & (n - 1)) {
PyErr_SetString(PyExc_ValueError,
"n must be a power of 2.");
return NULL;
}
r = PyLong_AsUnsignedLong(r_obj);
if (r == (unsigned long) -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"r is required and must be an unsigned int");
return NULL;
}
p = PyLong_AsUnsignedLong(p_obj);
if (p == (unsigned long) -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError,
"p is required and must be an unsigned int");
return NULL;
}
if (maxmem < 0 || maxmem > INT_MAX) {
/* Mbedtls 1.1.0 restricts maxmem to 32MB. It may change in the
future. The maxmem constant is private to Mbedtls. */
PyErr_Format(PyExc_ValueError,
"maxmem must be positive and smaller than %d",
INT_MAX);
return NULL;
}
if (dklen < 1 || dklen > INT_MAX) {
PyErr_Format(PyExc_ValueError,
"dklen must be greater than 0 and smaller than %d",
INT_MAX);
return NULL;
}
/* let Mbedtls validate the rest */
retval = EVP_PBE_scrypt(NULL, 0, NULL, 0, n, r, p, maxmem, NULL, 0);
if (!retval) {
/* sorry, can't do much better */
PyErr_SetString(PyExc_ValueError,
"Invalid paramemter combination for n, r, p, maxmem.");
return NULL;
}
key_obj = PyBytes_FromStringAndSize(NULL, dklen);
if (key_obj == NULL) {
return NULL;
}
key = PyBytes_AS_STRING(key_obj);
Py_BEGIN_ALLOW_THREADS
retval = EVP_PBE_scrypt(
(const char*)password->buf, (size_t)password->len,
(const unsigned char *)salt->buf, (size_t)salt->len,
n, r, p, maxmem,
(unsigned char *)key, (size_t)dklen
);
Py_END_ALLOW_THREADS
if (!retval) {
Py_CLEAR(key_obj);
SetMbedtlsError(PyExc_ValueError);
return NULL;
}
return key_obj;
}
#endif
static PyObject *
GenerateHashNameList(void)
@ -751,40 +499,26 @@ GenerateHashNameList(void)
return set;
}
/*
* This macro generates constructor function definitions for specific
* hash algorithms. These constructors are much faster than calling
* the generic one passing it a python string and are noticeably
* faster than calling a python new() wrapper. That is important for
* code that wants to make hashes of a bunch of small strings.
* The first call will lazy-initialize, which reports an exception
* if initialization fails.
*/
#define GEN_CONSTRUCTOR(NAME, STRNAME) \
static PyObject * \
EVP_new_ ## NAME (PyObject *self, PyObject *args) \
{ \
PyObject *ret; \
PyObject *data = 0; \
Py_buffer view = { 0 }; \
if (!PyArg_ParseTuple(args, "|O:" STRNAME , &data)) return 0; \
if (data) GET_BUFFER_VIEW_OR_ERROUT(data, &view); \
ret = EVPnew(CONST_ ## NAME ## _name_obj, \
mbedtls_md_info_from_type(MBEDTLS_MD_ ## NAME), \
(unsigned char *)view.buf, view.len); \
if (data) PyBuffer_Release(&view); \
return ret; \
}
static PyObject * \
hashlib_new_ ## NAME (PyObject *self, PyObject *args) \
{ \
PyObject *ret; \
Py_buffer data = {0}; \
if (!PyArg_ParseTuple(args, "|y*:" STRNAME, &data)) return 0; \
ret = NewHasher(CONST_ ## NAME ## _name_obj, \
mbedtls_md_info_from_type(MBEDTLS_MD_ ## NAME), \
data.buf, data.len); \
PyBuffer_Release(&data); \
return ret; \
}
/* a PyMethodDef structure for the constructor */
#define CONSTRUCTOR_METH_DEF(NAME, STRNAME) \
{"mbedtls_" STRNAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
PyDoc_STR("Returns a " STRNAME \
" hash object; optionally initialized with a string") \
}
#define CONSTRUCTOR_METH_DEF(NAME, STRNAME) \
{"mbedtls_" STRNAME, (PyCFunction)hashlib_new_ ## NAME, METH_VARARGS,\
PyDoc_STR("mbedtls_" STRNAME "($module, string=b'')\n--\n\n" \
"Returns a " STRNAME " hash object; optionally " \
"initialized with a string")}
/* used in the init function to setup a constructor: initialize Mbedtls
constructor constants if they haven't been initialized already. */
#define INIT_CONSTRUCTOR_CONSTANTS(NAME, STRNAME) \
if (CONST_ ## NAME ## _name_obj == NULL) { \
CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \
@ -798,15 +532,9 @@ GEN_CONSTRUCTOR(SHA384, "sha384")
GEN_CONSTRUCTOR(SHA512, "sha512")
GEN_CONSTRUCTOR(BLAKE2B256, "blake2b256")
/* List of functions exported by this module */
static struct PyMethodDef EVP_functions[] = {
{"new", (PyCFunction)EVP_new, METH_VARARGS|METH_KEYWORDS, EVP_new__doc__},
#ifdef PY_PBKDF2_HMAC
{"pbkdf2_hmac", (PyCFunction)pbkdf2_hmac, METH_VARARGS|METH_KEYWORDS,
pbkdf2_hmac__doc__},
#endif
_HASHLIB_SCRYPT_METHODDEF
static struct PyMethodDef hashlib_functions[] = {
{"new", (PyCFunction)hashlib_new, METH_VARARGS|METH_KEYWORDS, hashlib_new__doc__},
{"pbkdf2_hmac", (PyCFunction)pbkdf2_hmac, METH_VARARGS|METH_KEYWORDS, pbkdf2_hmac__doc__},
CONSTRUCTOR_METH_DEF(MD5, "md5"),
CONSTRUCTOR_METH_DEF(SHA1, "sha1"),
CONSTRUCTOR_METH_DEF(SHA224, "sha224"),
@ -814,7 +542,7 @@ static struct PyMethodDef EVP_functions[] = {
CONSTRUCTOR_METH_DEF(SHA384, "sha384"),
CONSTRUCTOR_METH_DEF(SHA512, "sha512"),
CONSTRUCTOR_METH_DEF(BLAKE2B256, "blake2b256"),
{NULL}
{0}
};
static struct PyModuleDef _hashlibmodule = {
@ -822,7 +550,7 @@ static struct PyModuleDef _hashlibmodule = {
"_hashlib",
NULL,
-1,
EVP_functions,
hashlib_functions,
NULL,
NULL,
NULL,
@ -833,11 +561,9 @@ PyMODINIT_FUNC
PyInit__hashlib(void)
{
PyObject *m, *mbedtls_md_meth_names;
Py_TYPE(&EVPtype) = &PyType_Type;
if (PyType_Ready(&EVPtype) < 0)
return NULL;
if (!(m = PyModule_Create(&_hashlibmodule)))
return NULL;
Py_TYPE(&hasher_type) = &PyType_Type;
if (PyType_Ready(&hasher_type) < 0) return 0;
if (!(m = PyModule_Create(&_hashlibmodule))) return 0;
if (!(mbedtls_md_meth_names = GenerateHashNameList())) {
Py_DECREF(m);
return NULL;
@ -846,8 +572,8 @@ PyInit__hashlib(void)
Py_DECREF(m);
return NULL;
}
Py_INCREF((PyObject *)&EVPtype);
PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
Py_INCREF((PyObject *)&hasher_type);
PyModule_AddObject(m, "HASH", (PyObject *)&hasher_type);
INIT_CONSTRUCTOR_CONSTANTS(MD5, "md5")
INIT_CONSTRUCTOR_CONSTANTS(SHA1, "sha1")
INIT_CONSTRUCTOR_CONSTANTS(SHA224, "sha224")

View file

@ -28,7 +28,6 @@ PYTHON_PROVIDE("_heapq.heapreplace");
C implementation derived directly from heapq.py in Py2.3
which was written by Kevin O'Connor, augmented by Tim Peters,
annotated by François Pinard, and converted to C by Raymond Hettinger.
*/
static int
@ -37,14 +36,12 @@ siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
PyObject *newitem, *parent, **arr;
Py_ssize_t parentpos, size;
int cmp;
assert(PyList_Check(heap));
size = PyList_GET_SIZE(heap);
if (pos >= size) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return -1;
}
/* Follow the path to the root, moving parents down until finding
a place newitem fits. */
arr = _PyList_ITEMS(heap);
@ -82,7 +79,6 @@ siftup(PyListObject *heap, Py_ssize_t pos)
Py_ssize_t startpos, endpos, childpos, limit;
PyObject *tmp1, *tmp2, **arr;
int cmp;
assert(PyList_Check(heap));
endpos = PyList_GET_SIZE(heap);
startpos = pos;
@ -90,7 +86,6 @@ siftup(PyListObject *heap, Py_ssize_t pos)
PyErr_SetString(PyExc_IndexError, "index out of range");
return -1;
}
/* Bubble up the smaller child until hitting a leaf. */
arr = _PyList_ITEMS(heap);
limit = endpos >> 1; /* smallest pos that has no child */
@ -130,18 +125,14 @@ static PyObject *
heappush(PyObject *self, PyObject *args)
{
PyObject *heap, *item;
if (!PyArg_UnpackTuple(args, "heappush", 2, 2, &heap, &item))
return NULL;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
if (PyList_Append(heap, item))
return NULL;
if (siftdown((PyListObject *)heap, 0, PyList_GET_SIZE(heap)-1))
return NULL;
Py_RETURN_NONE;
@ -155,19 +146,16 @@ heappop_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t))
{
PyObject *lastelt, *returnitem;
Py_ssize_t n;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
/* raises IndexError if the heap is empty */
n = PyList_GET_SIZE(heap);
if (n == 0) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return NULL;
}
lastelt = PyList_GET_ITEM(heap, n-1) ;
Py_INCREF(lastelt);
if (PyList_SetSlice(heap, n-1, n, NULL)) {
@ -175,7 +163,6 @@ heappop_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t))
return NULL;
}
n--;
if (!n)
return lastelt;
returnitem = PyList_GET_ITEM(heap, 0);
@ -200,20 +187,16 @@ static PyObject *
heapreplace_internal(PyObject *args, int siftup_func(PyListObject *, Py_ssize_t))
{
PyObject *heap, *item, *returnitem;
if (!PyArg_UnpackTuple(args, "heapreplace", 2, 2, &heap, &item))
return NULL;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
if (PyList_GET_SIZE(heap) == 0) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return NULL;
}
returnitem = PyList_GET_ITEM(heap, 0);
Py_INCREF(item);
PyList_SET_ITEM(heap, 0, item);
@ -243,23 +226,19 @@ this routine unless written as part of a conditional replacement:\n\n\
static PyObject *
heappushpop(PyObject *self, PyObject *args)
{
PyObject *heap, *item, *returnitem;
int cmp;
PyObject *top, *heap, *item, *returnitem;
if (!PyArg_UnpackTuple(args, "heappushpop", 2, 2, &heap, &item))
return NULL;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
if (PyList_GET_SIZE(heap) == 0) {
Py_INCREF(item);
return item;
}
PyObject* top = PyList_GET_ITEM(heap, 0);
top = PyList_GET_ITEM(heap, 0);
Py_INCREF(top);
cmp = PyObject_RichCompareBool(top, item, Py_LT);
Py_DECREF(top);
@ -269,12 +248,10 @@ heappushpop(PyObject *self, PyObject *args)
Py_INCREF(item);
return item;
}
if (PyList_GET_SIZE(heap) == 0) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return NULL;
}
returnitem = PyList_GET_ITEM(heap, 0);
Py_INCREF(item);
PyList_SET_ITEM(heap, 0, item);
@ -290,16 +267,27 @@ PyDoc_STRVAR(heappushpop_doc,
from the heap. The combined action runs more efficiently than\n\
heappush() followed by a separate call to heappop().");
static Py_ssize_t
static inline Py_ssize_t
keep_top_bit(Py_ssize_t n)
{
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* [jart] constant-time bitscan */
if (n > 0) {
return (Py_ssize_t)1 << (__builtin_clzll(n) ^
(sizeof(long long) * CHAR_BIT - 1));
} else if (n < 0) {
return n;
} else {
return 0;
}
#else
int i = 0;
while (n > 1) {
n >>= 1;
i++;
}
return n << i;
#endif
}
/* Cache friendly version of heapify()
@ -326,11 +314,9 @@ static PyObject *
cache_friendly_heapify(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t))
{
Py_ssize_t i, j, m, mhalf, leftmost;
m = PyList_GET_SIZE(heap) >> 1; /* index of first childless node */
leftmost = keep_top_bit(m + 1) - 1; /* leftmost node in row of m */
mhalf = m >> 1; /* parent of first childless node */
for (i = leftmost - 1 ; i >= mhalf ; i--) {
j = i;
while (1) {
@ -341,7 +327,6 @@ cache_friendly_heapify(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_
j >>= 1;
}
}
for (i = m - 1 ; i >= leftmost ; i--) {
j = i;
while (1) {
@ -359,12 +344,10 @@ static PyObject *
heapify_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t))
{
Py_ssize_t i, n;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
/* For heaps likely to be bigger than L1 cache, we use the cache
friendly heapify function. For smaller heaps that fit entirely
in cache, we prefer the simpler algorithm with less branching.
@ -372,7 +355,6 @@ heapify_internal(PyObject *heap, int siftup_func(PyListObject *, Py_ssize_t))
n = PyList_GET_SIZE(heap);
if (n > 2500)
return cache_friendly_heapify(heap, siftup_func);
/* Transform bottom-up. The largest index there's any point to
looking at is the largest with a child index in-range, so must
have 2*i + 1 < n, or i < (n-1)/2. If n is even = 2*j, this is
@ -401,14 +383,12 @@ siftdown_max(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
PyObject *newitem, *parent, **arr;
Py_ssize_t parentpos, size;
int cmp;
assert(PyList_Check(heap));
size = PyList_GET_SIZE(heap);
if (pos >= size) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return -1;
}
/* Follow the path to the root, moving parents down until finding
a place newitem fits. */
arr = _PyList_ITEMS(heap);
@ -446,7 +426,6 @@ siftup_max(PyListObject *heap, Py_ssize_t pos)
Py_ssize_t startpos, endpos, childpos, limit;
PyObject *tmp1, *tmp2, **arr;
int cmp;
assert(PyList_Check(heap));
endpos = PyList_GET_SIZE(heap);
startpos = pos;
@ -454,7 +433,6 @@ siftup_max(PyListObject *heap, Py_ssize_t pos)
PyErr_SetString(PyExc_IndexError, "index out of range");
return -1;
}
/* Bubble up the smaller child until hitting a leaf. */
arr = _PyList_ITEMS(heap);
limit = endpos >> 1; /* smallest pos that has no child */
@ -515,23 +493,39 @@ heapify_max(PyObject *self, PyObject *heap)
PyDoc_STRVAR(heapify_max_doc, "Maxheap variant of heapify.");
static PyMethodDef heapq_methods[] = {
{"heappush", (PyCFunction)heappush,
METH_VARARGS, heappush_doc},
{"heappushpop", (PyCFunction)heappushpop,
METH_VARARGS, heappushpop_doc},
{"heappop", (PyCFunction)heappop,
METH_O, heappop_doc},
{"heapreplace", (PyCFunction)heapreplace,
METH_VARARGS, heapreplace_doc},
{"heapify", (PyCFunction)heapify,
METH_O, heapify_doc},
{"_heappop_max", (PyCFunction)heappop_max,
METH_O, heappop_max_doc},
{"_heapreplace_max",(PyCFunction)heapreplace_max,
METH_VARARGS, heapreplace_max_doc},
{"_heapify_max", (PyCFunction)heapify_max,
METH_O, heapify_max_doc},
{NULL, NULL} /* sentinel */
{"heappush",
(PyCFunction)heappush,
METH_VARARGS,
heappush_doc},
{"heappushpop",
(PyCFunction)heappushpop,
METH_VARARGS,
heappushpop_doc},
{"heappop",
(PyCFunction)heappop,
METH_O,
heappop_doc},
{"heapreplace",
(PyCFunction)heapreplace,
METH_VARARGS,
heapreplace_doc},
{"heapify",
(PyCFunction)heapify,
METH_O,
heapify_doc},
{"_heappop_max",
(PyCFunction)heappop_max,
METH_O,
heappop_max_doc},
{"_heapreplace_max",
(PyCFunction)heapreplace_max,
METH_VARARGS,
heapreplace_max_doc},
{"_heapify_max",
(PyCFunction)heapify_max,
METH_O,
heapify_max_doc},
{0}
};
PyDoc_STRVAR(module_doc,
@ -676,7 +670,6 @@ PyMODINIT_FUNC
PyInit__heapq(void)
{
PyObject *m, *about;
m = PyModule_Create(&_heapqmodule);
if (m == NULL)
return NULL;
@ -684,3 +677,8 @@ PyInit__heapq(void)
PyModule_AddObject(m, "__about__", about);
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__heapq = {
"_heapq",
PyInit__heapq,
};

View file

@ -206,8 +206,8 @@ write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
| | <--to pad-->|<---to write---> |
0 buf position
*/
memset(PyBytes_AS_STRING(self->buf) + self->string_size, '\0',
(self->pos - self->string_size) * sizeof(char));
bzero(PyBytes_AS_STRING(self->buf) + self->string_size,
(self->pos - self->string_size) * sizeof(char));
}
/* Copy the data to the internal buffer, overwriting some of the existing

View file

@ -257,8 +257,8 @@ write_str(stringio *self, PyObject *obj)
0 buf position
*/
memset(self->buf + self->string_size, '\0',
(self->pos - self->string_size) * sizeof(Py_UCS4));
bzero(self->buf + self->string_size,
(self->pos - self->string_size) * sizeof(Py_UCS4));
}
/* Copy the data to the internal buffer, overwriting some of the

View file

@ -559,7 +559,6 @@ read_console_w(HANDLE handle, DWORD maxlen, DWORD *readlen) {
*readlen = 0;
//DebugBreak();
Py_BEGIN_ALLOW_THREADS
DWORD off = 0;
while (off < maxlen) {

View file

@ -775,3 +775,8 @@ c-basic-offset: 4
indent-tabs-mode: nil
End:
*/
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__locale = {
"_locale",
PyInit__locale,
};

View file

@ -31,11 +31,6 @@ PYTHON_PROVIDE("_sha3.sha3_512");
PYTHON_PROVIDE("_sha3.shake_128");
PYTHON_PROVIDE("_sha3.shake_256");
/*
Ran preprocessor on working build, because spaghetti structure of
upstream Python 3.6 source code was unnaceptably incomprehensible
*/
typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn;
typedef struct KeccakWidth1600_SpongeInstanceStruct {

View file

@ -1,3 +1,9 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
#include "third_party/python/Include/abstract.h"
@ -509,21 +515,21 @@ pending_exception(ProfilerObject *pObj)
/************************************************************/
static PyStructSequence_Field profiler_entry_fields[] = {
{"code", "code object or built-in function name"},
{"callcount", "how many times this was called"},
{"reccallcount", "how many times called recursively"},
{"totaltime", "total time in this entry"},
{"inlinetime", "inline time in this entry (not in subcalls)"},
{"calls", "details of the calls"},
{"code", PyDoc_STR("code object or built-in function name")},
{"callcount", PyDoc_STR("how many times this was called")},
{"reccallcount", PyDoc_STR("how many times called recursively")},
{"totaltime", PyDoc_STR("total time in this entry")},
{"inlinetime", PyDoc_STR("inline time in this entry (not in subcalls)")},
{"calls", PyDoc_STR("details of the calls")},
{0}
};
static PyStructSequence_Field profiler_subentry_fields[] = {
{"code", "called code object or built-in function name"},
{"callcount", "how many times this is called"},
{"reccallcount", "how many times this is called recursively"},
{"totaltime", "total time spent in this call"},
{"inlinetime", "inline time (not in further subcalls)"},
{"code", PyDoc_STR("called code object or built-in function name")},
{"callcount", PyDoc_STR("how many times this is called")},
{"reccallcount", PyDoc_STR("how many times this is called recursively")},
{"totaltime", PyDoc_STR("total time spent in this call")},
{"inlinetime", PyDoc_STR("inline time (not in further subcalls)")},
{0}
};

View file

@ -1286,25 +1286,26 @@ PyMODINIT_FUNC
PyInit__operator(void)
{
PyObject *m;
/* Create the module and add the functions */
m = PyModule_Create(&operatormodule);
if (m == NULL)
return NULL;
if (PyType_Ready(&itemgetter_type) < 0)
return NULL;
Py_INCREF(&itemgetter_type);
PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type);
if (PyType_Ready(&attrgetter_type) < 0)
return NULL;
Py_INCREF(&attrgetter_type);
PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type);
if (PyType_Ready(&methodcaller_type) < 0)
return NULL;
Py_INCREF(&methodcaller_type);
PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type);
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__operator = {
"_operator",
PyInit__operator,
};

View file

@ -4,7 +4,12 @@
Python 3
https://docs.python.org/3/license.html │
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/grnd.h"
#include "third_party/python/Include/floatobject.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/longobject.h"
@ -22,6 +27,11 @@
PYTHON_PROVIDE("_random");
PYTHON_PROVIDE("_random.Random");
asm(".ident\t\"\\n\\n\
mt19937 (BSD-3)\\n\
Copyright 1997-2004 Makoto Matsumoto and Takuji Nishimura\"");
asm(".include \"libc/disclaimer.inc\"");
/* ------------------------------------------------------------------
The code in this module was based on a download from:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
@ -166,7 +176,6 @@ init_genrand(RandomObject *self, uint32_t s)
{
int mti;
uint32_t *mt;
mt = self->state;
mt[0]= s;
for (mti=1; mti<N; mti++) {
@ -189,7 +198,6 @@ init_by_array(RandomObject *self, uint32_t init_key[], size_t key_length)
{
size_t i, j, k; /* was signed in the original code. RDH 12/16/2002 */
uint32_t *mt;
mt = self->state;
init_genrand(self, 19650218U);
i=1; j=0;
@ -207,7 +215,6 @@ init_by_array(RandomObject *self, uint32_t init_key[], size_t key_length)
i++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
}
mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
}
@ -220,9 +227,8 @@ static int
random_seed_urandom(RandomObject *self)
{
PY_UINT32_T key[N];
if (_PyOS_URandomNonblock(key, sizeof(key)) < 0) {
return -1;
abort();
}
init_by_array(self, key, Py_ARRAY_LENGTH(key));
return 0;
@ -233,17 +239,13 @@ random_seed_time_pid(RandomObject *self)
{
_PyTime_t now;
uint32_t key[5];
now = _PyTime_GetSystemClock();
key[0] = (PY_UINT32_T)(now & 0xffffffffU);
key[1] = (PY_UINT32_T)(now >> 32);
key[2] = (PY_UINT32_T)getpid();
now = _PyTime_GetMonotonicClock();
key[3] = (PY_UINT32_T)(now & 0xffffffffU);
key[4] = (PY_UINT32_T)(now >> 32);
init_by_array(self, key, Py_ARRAY_LENGTH(key));
}

View file

@ -25,6 +25,7 @@
*/
#include "third_party/python/Include/pythread.h"
#include "third_party/python/Include/structmember.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/python/Modules/_sqlite/cache.h"
#include "third_party/python/Modules/_sqlite/connection.h"
#include "third_party/python/Modules/_sqlite/cursor.h"
@ -33,6 +34,8 @@
#include "third_party/python/Modules/_sqlite/statement.h"
#include "third_party/python/Modules/_sqlite/util.h"
PYTHON_YOINK("sqlite3.dump");
asm(".ident\t\"\\n\\n\
pysqlite (zlib license)\\n\
Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>\"");

View file

@ -4,6 +4,7 @@
Python 3
https://docs.python.org/3/license.html │
*/
#define PY_SSIZE_T_CLEAN
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/boolobject.h"
#include "third_party/python/Include/bytesobject.h"
@ -36,10 +37,15 @@ PYTHON_PROVIDE("_sre.__name__");
PYTHON_PROVIDE("_sre.__package__");
PYTHON_PROVIDE("_sre.__spec__");
PYTHON_PROVIDE("_sre.compile");
PYTHON_PROVIDE("_sre.copyright");
PYTHON_PROVIDE("_sre.getcodesize");
PYTHON_PROVIDE("_sre.getlower");
asm(".ident\t\"\\n\\n\
SRE 2.2.2 (Python license)\\n\
Copyright 1997-2002 Secret Labs AB\"");
asm(".include \"libc/disclaimer.inc\"");
/* clang-format off */
/*
* Secret Labs' Regular Expression Engine
*
@ -77,11 +83,6 @@ PYTHON_PROVIDE("_sre.getlower");
* other compatibility work.
*/
static const char copyright[] =
" SRE 2.2.2 Copyright (c) 1997-2002 by Secret Labs AB ";
#define PY_SSIZE_T_CLEAN
#define SRE_CODE_BITS (8 * sizeof(SRE_CODE))
/* name of this module, minus the leading underscore */
@ -148,17 +149,25 @@ static unsigned int sre_upper(unsigned int ch)
/* locale-specific character predicates */
/* !(c & ~N) == (c < N+1) for any unsigned c, this avoids
* warnings when c's type supports only numbers < N+1 */
#define SRE_LOC_IS_ALNUM(ch) (!((ch) & ~255) ? isalnum((ch)) : 0)
#define SRE_LOC_IS_ALNUM(ch) (!((ch) & ~255) ? Py_ISALNUM((ch)) : 0)
#define SRE_LOC_IS_WORD(ch) (SRE_LOC_IS_ALNUM((ch)) || (ch) == '_')
static unsigned int sre_lower_locale(unsigned int ch)
static inline unsigned int sre_lower_locale(unsigned int ch)
{
#ifdef __COSMOPOLITAN__
return sre_lower(ch);
#else
return ((ch) < 256 ? (unsigned int)tolower((ch)) : ch);
#endif
}
static unsigned int sre_upper_locale(unsigned int ch)
static inline unsigned int sre_upper_locale(unsigned int ch)
{
#ifdef __COSMOPOLITAN__
return sre_upper(ch);
#else
return ((ch) < 256 ? (unsigned int)toupper((ch)) : ch);
#endif
}
/* unicode-specific character predicates */
@ -199,12 +208,10 @@ sre_category(SRE_CODE category, unsigned int ch)
return SRE_IS_LINEBREAK(ch);
case SRE_CATEGORY_NOT_LINEBREAK:
return !SRE_IS_LINEBREAK(ch);
case SRE_CATEGORY_LOC_WORD:
return SRE_LOC_IS_WORD(ch);
case SRE_CATEGORY_LOC_NOT_WORD:
return !SRE_LOC_IS_WORD(ch);
case SRE_CATEGORY_UNI_DIGIT:
return SRE_UNI_IS_DIGIT(ch);
case SRE_CATEGORY_UNI_NOT_DIGIT:
@ -225,8 +232,6 @@ sre_category(SRE_CODE category, unsigned int ch)
return 0;
}
/* helpers */
static void
data_stack_dealloc(SRE_STATE* state)
{
@ -2734,8 +2739,8 @@ pattern_richcompare(PyObject *lefto, PyObject *righto, int op)
produce different codes depending on the locale used to compile the
pattern when the re.LOCALE flag is used. Don't compare groups,
indexgroup nor groupindex: they are derivated from the pattern. */
cmp = (memcmp(left->code, right->code,
sizeof(left->code[0]) * left->codesize) == 0);
cmp = !bcmp(left->code, right->code,
sizeof(left->code[0]) * left->codesize);
}
if (cmp) {
cmp = PyObject_RichCompareBool(left->pattern, right->pattern,
@ -2948,7 +2953,8 @@ static struct PyModuleDef sremodule = {
NULL
};
PyMODINIT_FUNC PyInit__sre(void)
PyMODINIT_FUNC
PyInit__sre(void)
{
PyObject* m;
PyObject* d;
@ -2988,13 +2994,10 @@ PyMODINIT_FUNC PyInit__sre(void)
Py_DECREF(x);
}
x = PyUnicode_FromString(copyright);
if (x) {
PyDict_SetItemString(d, "copyright", x);
Py_DECREF(x);
}
return m;
}
/* vim:ts=4:sw=4:et
*/
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__sre = {
"_sre",
PyInit__sre,
};

View file

@ -1786,8 +1786,7 @@ s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf)
/* XXX(nnorwitz): why does i need to be a local? can we use
the offset parameter or do we need the wider width? */
Py_ssize_t i;
memset(buf, '\0', soself->s_size);
bzero(buf, soself->s_size);
i = offset;
for (code = soself->s_codes; code->fmtdef != NULL; code++) {
const formatdef *e = code->fmtdef;

View file

@ -2605,7 +2605,7 @@ cmp_contig(PyObject *self, PyObject *args)
goto result;
}
if (memcmp((char *)v1.buf, (char *)v2.buf, v1.len) != 0) {
if (bcmp((char *)v1.buf, (char *)v2.buf, v1.len)) {
goto result;
}

View file

@ -1816,9 +1816,9 @@ typecode_to_mformat_code(char typecode)
case 'f':
if (sizeof(float) == 4) {
const float y = 16711938.0;
if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0)
if (!bcmp(&y, "\x4b\x7f\x01\x02", 4))
return IEEE_754_FLOAT_BE;
if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0)
if (!bcmp(&y, "\x02\x01\x7f\x4b", 4))
return IEEE_754_FLOAT_LE;
}
return UNKNOWN_FORMAT;
@ -1826,9 +1826,9 @@ typecode_to_mformat_code(char typecode)
case 'd':
if (sizeof(double) == 8) {
const double x = 9006104071832581.0;
if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)
if (!bcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8))
return IEEE_754_DOUBLE_BE;
if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)
if (!bcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8))
return IEEE_754_DOUBLE_LE;
}
return UNKNOWN_FORMAT;

View file

@ -5,6 +5,7 @@
https://docs.python.org/3/license.html │
*/
#define PY_SSIZE_T_CLEAN
#include "dsp/core/core.h"
#include "libc/math.h"
#include "third_party/python/Include/dictobject.h"
#include "third_party/python/Include/floatobject.h"
@ -71,256 +72,12 @@ fbound(double val, double minval, double maxval)
else if (val < minval + 1.0) {
val = minval;
}
/* Round towards minus infinity (-inf) */
val = floor(val);
/* Cast double to integer: round towards zero */
return (int)val;
}
/* Code shamelessly stolen from sox, 12.17.7, g711.c
** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
/* From g711.c:
*
* December 30, 1994:
* Functions linear2alaw, linear2ulaw have been updated to correctly
* convert unquantized 16 bit values.
* Tables for direct u- to A-law and A- to u-law conversions have been
* corrected.
* Borge Lindberg, Center for PersonKommunikation, Aalborg University.
* bli@cpk.auc.dk
*
*/
#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
#define CLIP 32635
#define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */
#define QUANT_MASK (0xf) /* Quantization field mask. */
#define SEG_SHIFT (4) /* Left shift for segment number. */
#define SEG_MASK (0x70) /* Segment field mask. */
static const int16_t seg_aend[8] = {
0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF
};
static const int16_t seg_uend[8] = {
0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF
};
static int16_t
search(int16_t val, const int16_t *table, int size)
{
int i;
for (i = 0; i < size; i++) {
if (val <= *table++)
return (i);
}
return (size);
}
#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
#define st_alaw2linear16(uc) (_st_alaw2linear16[uc])
static const int16_t _st_ulaw2linear16[256] = {
-32124, -31100, -30076, -29052, -28028, -27004, -25980,
-24956, -23932, -22908, -21884, -20860, -19836, -18812,
-17788, -16764, -15996, -15484, -14972, -14460, -13948,
-13436, -12924, -12412, -11900, -11388, -10876, -10364,
-9852, -9340, -8828, -8316, -7932, -7676, -7420,
-7164, -6908, -6652, -6396, -6140, -5884, -5628,
-5372, -5116, -4860, -4604, -4348, -4092, -3900,
-3772, -3644, -3516, -3388, -3260, -3132, -3004,
-2876, -2748, -2620, -2492, -2364, -2236, -2108,
-1980, -1884, -1820, -1756, -1692, -1628, -1564,
-1500, -1436, -1372, -1308, -1244, -1180, -1116,
-1052, -988, -924, -876, -844, -812, -780,
-748, -716, -684, -652, -620, -588, -556,
-524, -492, -460, -428, -396, -372, -356,
-340, -324, -308, -292, -276, -260, -244,
-228, -212, -196, -180, -164, -148, -132,
-120, -112, -104, -96, -88, -80, -72,
-64, -56, -48, -40, -32, -24, -16,
-8, 0, 32124, 31100, 30076, 29052, 28028,
27004, 25980, 24956, 23932, 22908, 21884, 20860,
19836, 18812, 17788, 16764, 15996, 15484, 14972,
14460, 13948, 13436, 12924, 12412, 11900, 11388,
10876, 10364, 9852, 9340, 8828, 8316, 7932,
7676, 7420, 7164, 6908, 6652, 6396, 6140,
5884, 5628, 5372, 5116, 4860, 4604, 4348,
4092, 3900, 3772, 3644, 3516, 3388, 3260,
3132, 3004, 2876, 2748, 2620, 2492, 2364,
2236, 2108, 1980, 1884, 1820, 1756, 1692,
1628, 1564, 1500, 1436, 1372, 1308, 1244,
1180, 1116, 1052, 988, 924, 876, 844,
812, 780, 748, 716, 684, 652, 620,
588, 556, 524, 492, 460, 428, 396,
372, 356, 340, 324, 308, 292, 276,
260, 244, 228, 212, 196, 180, 164,
148, 132, 120, 112, 104, 96, 88,
80, 72, 64, 56, 48, 40, 32,
24, 16, 8, 0
};
/*
* linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
* stored in an unsigned char. This function should only be called with
* the data shifted such that it only contains information in the lower
* 14-bits.
*
* In order to simplify the encoding process, the original linear magnitude
* is biased by adding 33 which shifts the encoding range from (0 - 8158) to
* (33 - 8191). The result can be seen in the following encoding table:
*
* Biased Linear Input Code Compressed Code
* ------------------------ ---------------
* 00000001wxyza 000wxyz
* 0000001wxyzab 001wxyz
* 000001wxyzabc 010wxyz
* 00001wxyzabcd 011wxyz
* 0001wxyzabcde 100wxyz
* 001wxyzabcdef 101wxyz
* 01wxyzabcdefg 110wxyz
* 1wxyzabcdefgh 111wxyz
*
* Each biased linear code has a leading 1 which identifies the segment
* number. The value of the segment number is equal to 7 minus the number
* of leading 0's. The quantization interval is directly available as the
* four bits wxyz. * The trailing bits (a - h) are ignored.
*
* Ordinarily the complement of the resulting code word is used for
* transmission, and so the code word is complemented before it is returned.
*
* For further information see John C. Bellamy's Digital Telephony, 1982,
* John Wiley & Sons, pps 98-111 and 472-476.
*/
static unsigned char
st_14linear2ulaw(int16_t pcm_val) /* 2's complement (14-bit range) */
{
int16_t mask;
int16_t seg;
unsigned char uval;
/* u-law inverts all bits */
/* Get the sign and the magnitude of the value. */
if (pcm_val < 0) {
pcm_val = -pcm_val;
mask = 0x7F;
} else {
mask = 0xFF;
}
if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
pcm_val += (BIAS >> 2);
/* Convert the scaled magnitude to segment number. */
seg = search(pcm_val, seg_uend, 8);
/*
* Combine the sign, segment, quantization bits;
* and complement the code word.
*/
if (seg >= 8) /* out of range, return maximum value. */
return (unsigned char) (0x7F ^ mask);
else {
uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
return (uval ^ mask);
}
}
static const int16_t _st_alaw2linear16[256] = {
-5504, -5248, -6016, -5760, -4480, -4224, -4992,
-4736, -7552, -7296, -8064, -7808, -6528, -6272,
-7040, -6784, -2752, -2624, -3008, -2880, -2240,
-2112, -2496, -2368, -3776, -3648, -4032, -3904,
-3264, -3136, -3520, -3392, -22016, -20992, -24064,
-23040, -17920, -16896, -19968, -18944, -30208, -29184,
-32256, -31232, -26112, -25088, -28160, -27136, -11008,
-10496, -12032, -11520, -8960, -8448, -9984, -9472,
-15104, -14592, -16128, -15616, -13056, -12544, -14080,
-13568, -344, -328, -376, -360, -280, -264,
-312, -296, -472, -456, -504, -488, -408,
-392, -440, -424, -88, -72, -120, -104,
-24, -8, -56, -40, -216, -200, -248,
-232, -152, -136, -184, -168, -1376, -1312,
-1504, -1440, -1120, -1056, -1248, -1184, -1888,
-1824, -2016, -1952, -1632, -1568, -1760, -1696,
-688, -656, -752, -720, -560, -528, -624,
-592, -944, -912, -1008, -976, -816, -784,
-880, -848, 5504, 5248, 6016, 5760, 4480,
4224, 4992, 4736, 7552, 7296, 8064, 7808,
6528, 6272, 7040, 6784, 2752, 2624, 3008,
2880, 2240, 2112, 2496, 2368, 3776, 3648,
4032, 3904, 3264, 3136, 3520, 3392, 22016,
20992, 24064, 23040, 17920, 16896, 19968, 18944,
30208, 29184, 32256, 31232, 26112, 25088, 28160,
27136, 11008, 10496, 12032, 11520, 8960, 8448,
9984, 9472, 15104, 14592, 16128, 15616, 13056,
12544, 14080, 13568, 344, 328, 376, 360,
280, 264, 312, 296, 472, 456, 504,
488, 408, 392, 440, 424, 88, 72,
120, 104, 24, 8, 56, 40, 216,
200, 248, 232, 152, 136, 184, 168,
1376, 1312, 1504, 1440, 1120, 1056, 1248,
1184, 1888, 1824, 2016, 1952, 1632, 1568,
1760, 1696, 688, 656, 752, 720, 560,
528, 624, 592, 944, 912, 1008, 976,
816, 784, 880, 848
};
/*
* linear2alaw() accepts a 13-bit signed integer and encodes it as A-law data
* stored in an unsigned char. This function should only be called with
* the data shifted such that it only contains information in the lower
* 13-bits.
*
* Linear Input Code Compressed Code
* ------------------------ ---------------
* 0000000wxyza 000wxyz
* 0000001wxyza 001wxyz
* 000001wxyzab 010wxyz
* 00001wxyzabc 011wxyz
* 0001wxyzabcd 100wxyz
* 001wxyzabcde 101wxyz
* 01wxyzabcdef 110wxyz
* 1wxyzabcdefg 111wxyz
*
* For further information see John C. Bellamy's Digital Telephony, 1982,
* John Wiley & Sons, pps 98-111 and 472-476.
*/
static unsigned char
st_linear2alaw(int16_t pcm_val) /* 2's complement (13-bit range) */
{
int16_t mask;
int16_t seg;
unsigned char aval;
/* A-law using even bit inversion */
if (pcm_val >= 0) {
mask = 0xD5; /* sign (7th) bit = 1 */
} else {
mask = 0x55; /* sign bit = 0 */
pcm_val = -pcm_val - 1;
}
/* Convert the scaled magnitude to segment number. */
seg = search(pcm_val, seg_aend, 8);
/* Combine the sign, segment, and quantization bits. */
if (seg >= 8) /* out of range, return maximum value. */
return (unsigned char) (0x7F ^ mask);
else {
aval = (unsigned char) seg << SEG_SHIFT;
if (seg < 2)
aval |= (pcm_val >> 1) & QUANT_MASK;
else
aval |= (pcm_val >> seg) & QUANT_MASK;
return (aval ^ mask);
}
}
/* End of code taken from sox */
/* Intel ADPCM step variation table */
static const int indexTable[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
@ -344,7 +101,6 @@ static const int stepsizeTable[89] = {
*(T *)((unsigned char *)(cp) + (i)) = (T)(val); \
} while (0)
#define GETINT8(cp, i) GETINTX(signed char, (cp), (i))
#define GETINT16(cp, i) GETINTX(int16_t, (cp), (i))
#define GETINT32(cp, i) GETINTX(int32_t, (cp), (i))
@ -361,7 +117,6 @@ static const int stepsizeTable[89] = {
(((signed char *)(cp) + (i))[2] << 16) )
#endif
#define SETINT8(cp, i, val) SETINTX(signed char, (cp), (i), (val))
#define SETINT16(cp, i, val) SETINTX(int16_t, (cp), (i), (val))
#define SETINT32(cp, i, val) SETINTX(int32_t, (cp), (i), (val))
@ -380,7 +135,6 @@ static const int stepsizeTable[89] = {
} while (0)
#endif
#define GETRAWSAMPLE(size, cp, i) ( \
(size == 1) ? (int)GETINT8((cp), (i)) : \
(size == 2) ? (int)GETINT16((cp), (i)) : \
@ -398,7 +152,6 @@ static const int stepsizeTable[89] = {
SETINT32((cp), (i), (val)); \
} while(0)
#define GETSAMPLE32(size, cp, i) ( \
(size == 1) ? (int)GETINT8((cp), (i)) << 24 : \
(size == 2) ? (int)GETINT16((cp), (i)) << 16 : \
@ -416,7 +169,6 @@ static const int stepsizeTable[89] = {
SETINT32((cp), (i), (val)); \
} while(0)
static PyObject *AudioopError;
static int
@ -426,8 +178,7 @@ audioop_check_size(int size)
PyErr_SetString(AudioopError, "Size should be 1, 2, 3 or 4");
return 0;
}
else
return 1;
return 1;
}
static int
@ -464,7 +215,6 @@ audioop_getsample_impl(PyObject *module, Py_buffer *fragment, int width,
/*[clinic end generated code: output=8fe1b1775134f39a input=88edbe2871393549]*/
{
int val;
if (!audioop_check_parameters(fragment->len, width))
return NULL;
if (index < 0 || index >= fragment->len/width) {
@ -491,7 +241,6 @@ audioop_max_impl(PyObject *module, Py_buffer *fragment, int width)
{
Py_ssize_t i;
unsigned int absval, max = 0;
if (!audioop_check_parameters(fragment->len, width))
return NULL;
for (i = 0; i < fragment->len; i += width) {
@ -657,7 +406,6 @@ audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
Py_ssize_t j, best_j;
double aj_m1, aj_lm1;
double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
if (fragment->len & 1 || reference->len & 1) {
PyErr_SetString(AudioopError, "Strings should be even-sized");
return NULL;
@ -666,7 +414,6 @@ audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
len1 = fragment->len >> 1;
cp2 = (const int16_t *)reference->buf;
len2 = reference->len >> 1;
if (len1 < len2) {
PyErr_SetString(AudioopError, "First sample should be longer");
return NULL;
@ -674,31 +421,22 @@ audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
sum_ri_2 = _sum2(cp2, cp2, len2);
sum_aij_2 = _sum2(cp1, cp1, len2);
sum_aij_ri = _sum2(cp1, cp2, len2);
result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri) / sum_aij_2;
best_result = result;
best_j = 0;
for ( j=1; j<=len1-len2; j++) {
aj_m1 = (double)cp1[j-1];
aj_lm1 = (double)cp1[j+len2-1];
sum_aij_2 = sum_aij_2 + aj_lm1*aj_lm1 - aj_m1*aj_m1;
sum_aij_ri = _sum2(cp1+j, cp2, len2);
result = (sum_ri_2*sum_aij_2 - sum_aij_ri*sum_aij_ri)
/ sum_aij_2;
if ( result < best_result ) {
best_result = result;
best_j = j;
}
}
factor = _sum2(cp1+best_j, cp2, len2) / sum_ri_2;
return Py_BuildValue("(nf)", best_j, factor);
}
@ -821,7 +559,6 @@ audioop_avgpp_impl(PyObject *module, Py_buffer *fragment, int width)
double sum = 0.0;
unsigned int avg;
int diff, prevdiff, nextreme = 0;
if (!audioop_check_parameters(fragment->len, width))
return NULL;
if (fragment->len <= width)
@ -1100,26 +837,21 @@ audioop_add_impl(PyObject *module, Py_buffer *fragment1,
Py_ssize_t i;
int minval, maxval, newval;
PyObject *rv;
if (!audioop_check_parameters(fragment1->len, width))
return NULL;
if (fragment1->len != fragment2->len) {
PyErr_SetString(AudioopError, "Lengths should be the same");
return NULL;
}
maxval = maxvals[width];
minval = minvals[width];
rv = PyBytes_FromStringAndSize(NULL, fragment1->len);
if (rv == NULL)
return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
for (i = 0; i < fragment1->len; i += width) {
int val1 = GETRAWSAMPLE(width, fragment1->buf, i);
int val2 = GETRAWSAMPLE(width, fragment2->buf, i);
if (width < 4) {
newval = val1 + val2;
/* truncate in case of overflow */
@ -1133,7 +865,6 @@ audioop_add_impl(PyObject *module, Py_buffer *fragment1,
/* truncate in case of overflow */
newval = fbound(fval, minval, maxval);
}
SETRAWSAMPLE(width, ncp, i, newval);
}
return rv;
@ -1158,17 +889,13 @@ audioop_bias_impl(PyObject *module, Py_buffer *fragment, int width, int bias)
Py_ssize_t i;
unsigned int val = 0, mask;
PyObject *rv;
if (!audioop_check_parameters(fragment->len, width))
return NULL;
rv = PyBytes_FromStringAndSize(NULL, fragment->len);
if (rv == NULL)
return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
mask = masks[width];
for (i = 0; i < fragment->len; i += width) {
if (width == 1)
val = GETINTX(unsigned char, fragment->buf, i);
@ -1180,11 +907,9 @@ audioop_bias_impl(PyObject *module, Py_buffer *fragment, int width, int bias)
assert(width == 4);
val = GETINTX(uint32_t, fragment->buf, i);
}
val += (unsigned int)bias;
/* wrap around in case of overflow */
val &= mask;
if (width == 1)
SETINTX(unsigned char, ncp, i, val);
else if (width == 2)
@ -1216,15 +941,12 @@ audioop_reverse_impl(PyObject *module, Py_buffer *fragment, int width)
unsigned char *ncp;
Py_ssize_t i;
PyObject *rv;
if (!audioop_check_parameters(fragment->len, width))
return NULL;
rv = PyBytes_FromStringAndSize(NULL, fragment->len);
if (rv == NULL)
return NULL;
ncp = (unsigned char *)PyBytes_AsString(rv);
for (i = 0; i < fragment->len; i += width) {
int val = GETRAWSAMPLE(width, fragment->buf, i);
SETRAWSAMPLE(width, ncp, fragment->len - i - width, val);
@ -1246,22 +968,20 @@ static PyObject *
audioop_byteswap_impl(PyObject *module, Py_buffer *fragment, int width)
/*[clinic end generated code: output=50838a9e4b87cd4d input=fae7611ceffa5c82]*/
{
unsigned char *ncp;
int j;
Py_ssize_t i;
PyObject *rv;
unsigned char *ncp;
if (!audioop_check_parameters(fragment->len, width))
return NULL;
rv = PyBytes_FromStringAndSize(NULL, fragment->len);
if (rv == NULL)
return NULL;
ncp = (unsigned char *)PyBytes_AsString(rv);
for (i = 0; i < fragment->len; i += width) {
int j;
for (j = 0; j < width; j++)
for (j = 0; j < width; j++) {
ncp[i + width - 1 - j] = ((unsigned char *)fragment->buf)[i + j];
}
}
return rv;
}
@ -1533,18 +1253,17 @@ audioop_lin2ulaw_impl(PyObject *module, Py_buffer *fragment, int width)
unsigned char *ncp;
Py_ssize_t i;
PyObject *rv;
if (!audioop_check_parameters(fragment->len, width))
return NULL;
rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
if (rv == NULL)
return NULL;
ncp = (unsigned char *)PyBytes_AsString(rv);
for (i = 0; i < fragment->len; i += width) {
int val = GETSAMPLE32(width, fragment->buf, i);
*ncp++ = st_14linear2ulaw(val >> 18);
*ncp++ = mulaw(val >> 16);
/* [jart] 2x slower, bloated, and off by one 0.7% of the time */
/* *ncp++ = st_14linear2ulaw(val >> 18); */
}
return rv;
}
@ -1567,10 +1286,8 @@ audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
signed char *ncp;
Py_ssize_t i;
PyObject *rv;
if (!audioop_check_size(width))
return NULL;
if (fragment->len > PY_SSIZE_T_MAX/width) {
PyErr_SetString(PyExc_MemoryError,
"not enough memory for output buffer");
@ -1580,10 +1297,12 @@ audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
if (rv == NULL)
return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
cp = fragment->buf;
for (i = 0; i < fragment->len*width; i += width) {
int val = st_ulaw2linear16(*cp++) << 16;
/*
* [jart] fixed left shift undefined behavior
*/
int val = (unsigned)unmulaw(*cp++) << 16;
SETSAMPLE32(width, ncp, i, val);
}
return rv;
@ -1617,7 +1336,8 @@ audioop_lin2alaw_impl(PyObject *module, Py_buffer *fragment, int width)
for (i = 0; i < fragment->len; i += width) {
int val = GETSAMPLE32(width, fragment->buf, i);
*ncp++ = st_linear2alaw(val >> 19);
*ncp++ = alaw(val >> 16);
/* *ncp++ = st_linear2alaw(val >> 19); */
}
return rv;
}
@ -1636,15 +1356,13 @@ static PyObject *
audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
/*[clinic end generated code: output=85c365ec559df647 input=4140626046cd1772]*/
{
unsigned char *cp;
signed char *ncp;
Py_ssize_t i;
int val;
PyObject *rv;
Py_ssize_t i;
signed char *ncp;
unsigned char *cp;
if (!audioop_check_size(width))
return NULL;
if (fragment->len > PY_SSIZE_T_MAX/width) {
PyErr_SetString(PyExc_MemoryError,
"not enough memory for output buffer");
@ -1655,9 +1373,11 @@ audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
return NULL;
ncp = (signed char *)PyBytes_AsString(rv);
cp = fragment->buf;
for (i = 0; i < fragment->len*width; i += width) {
val = st_alaw2linear16(*cp++) << 16;
/*
* [jart] fixed undefined behavior
*/
val = (unsigned)unalaw(*cp++) << 16;
SETSAMPLE32(width, ncp, i, val);
}
return rv;

View file

@ -1,61 +0,0 @@
/* clang-format off */
/*[clinic input]
preserve
[clinic start generated code]*/
#if (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER))
PyDoc_STRVAR(_hashlib_scrypt__doc__,
"scrypt($module, /, password, *, salt=None, n=None, r=None, p=None,\n"
" maxmem=0, dklen=64)\n"
"--\n"
"\n"
"scrypt password-based key derivation function.");
#define _HASHLIB_SCRYPT_METHODDEF \
{"scrypt", (PyCFunction)_hashlib_scrypt, METH_FASTCALL, _hashlib_scrypt__doc__},
static PyObject *
_hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt,
PyObject *n_obj, PyObject *r_obj, PyObject *p_obj,
long maxmem, long dklen);
static PyObject *
_hashlib_scrypt(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"password", "salt", "n", "r", "p", "maxmem", "dklen", NULL};
static _PyArg_Parser _parser = {"y*|$y*O!O!O!ll:scrypt", _keywords, 0};
Py_buffer password = {NULL, NULL};
Py_buffer salt = {NULL, NULL};
PyObject *n_obj = Py_None;
PyObject *r_obj = Py_None;
PyObject *p_obj = Py_None;
long maxmem = 0;
long dklen = 64;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&password, &salt, &PyLong_Type, &n_obj, &PyLong_Type, &r_obj, &PyLong_Type, &p_obj, &maxmem, &dklen)) {
goto exit;
}
return_value = _hashlib_scrypt_impl(module, &password, &salt, n_obj, r_obj, p_obj, maxmem, dklen);
exit:
/* Cleanup for password */
if (password.obj) {
PyBuffer_Release(&password);
}
/* Cleanup for salt */
if (salt.obj) {
PyBuffer_Release(&salt);
}
return return_value;
}
#endif /* (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)) */
#ifndef _HASHLIB_SCRYPT_METHODDEF
#define _HASHLIB_SCRYPT_METHODDEF
#endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
/*[clinic end generated code: output=118cd7036fa0fb52 input=a9049054013a1b77]*/

View file

@ -843,19 +843,15 @@ audioop_alaw2lin(PyObject *module, PyObject *args)
PyObject *return_value = NULL;
Py_buffer fragment = {NULL, NULL};
int width;
if (!PyArg_ParseTuple(args, "y*i:alaw2lin",
&fragment, &width)) {
if (!PyArg_ParseTuple(args, "y*i:alaw2lin", &fragment, &width)) {
goto exit;
}
return_value = audioop_alaw2lin_impl(module, &fragment, width);
exit:
/* Cleanup for fragment */
if (fragment.obj) {
PyBuffer_Release(&fragment);
}
return return_value;
}

View file

@ -1,98 +0,0 @@
/* clang-format off */
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(MD5Type_copy__doc__,
"copy($self, /)\n"
"--\n"
"\n"
"Return a copy of the hash object.");
#define MD5TYPE_COPY_METHODDEF \
{"copy", (PyCFunction)MD5Type_copy, METH_NOARGS, MD5Type_copy__doc__},
static PyObject *
MD5Type_copy_impl(MD5object *self);
static PyObject *
MD5Type_copy(MD5object *self, PyObject *Py_UNUSED(ignored))
{
return MD5Type_copy_impl(self);
}
PyDoc_STRVAR(MD5Type_digest__doc__,
"digest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a bytes object.");
#define MD5TYPE_DIGEST_METHODDEF \
{"digest", (PyCFunction)MD5Type_digest, METH_NOARGS, MD5Type_digest__doc__},
static PyObject *
MD5Type_digest_impl(MD5object *self);
static PyObject *
MD5Type_digest(MD5object *self, PyObject *Py_UNUSED(ignored))
{
return MD5Type_digest_impl(self);
}
PyDoc_STRVAR(MD5Type_hexdigest__doc__,
"hexdigest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a string of hexadecimal digits.");
#define MD5TYPE_HEXDIGEST_METHODDEF \
{"hexdigest", (PyCFunction)MD5Type_hexdigest, METH_NOARGS, MD5Type_hexdigest__doc__},
static PyObject *
MD5Type_hexdigest_impl(MD5object *self);
static PyObject *
MD5Type_hexdigest(MD5object *self, PyObject *Py_UNUSED(ignored))
{
return MD5Type_hexdigest_impl(self);
}
PyDoc_STRVAR(MD5Type_update__doc__,
"update($self, obj, /)\n"
"--\n"
"\n"
"Update this hash object\'s state with the provided string.");
#define MD5TYPE_UPDATE_METHODDEF \
{"update", (PyCFunction)MD5Type_update, METH_O, MD5Type_update__doc__},
PyDoc_STRVAR(_md5_md5__doc__,
"md5($module, /, string=b\'\')\n"
"--\n"
"\n"
"Return a new MD5 hash object; optionally initialized with a string.");
#define _MD5_MD5_METHODDEF \
{"md5", (PyCFunction)_md5_md5, METH_FASTCALL, _md5_md5__doc__},
static PyObject *
_md5_md5_impl(PyObject *module, PyObject *string);
static PyObject *
_md5_md5(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", NULL};
static _PyArg_Parser _parser = {"|O:md5", _keywords, 0};
PyObject *string = NULL;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&string)) {
goto exit;
}
return_value = _md5_md5_impl(module, string);
exit:
return return_value;
}
/*[clinic end generated code: output=1761d10cec19a4c2 input=a9049054013a1b77]*/

View file

@ -967,8 +967,6 @@ exit:
#endif /* defined(MS_WINDOWS) */
#if defined(MS_WINDOWS)
PyDoc_STRVAR(os__getfinalpathname__doc__,
"_getfinalpathname($module, path, /)\n"
"--\n"
@ -986,18 +984,14 @@ os__getfinalpathname(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
PyObject *path;
if (!PyArg_Parse(arg, "U:_getfinalpathname", &path)) {
goto exit;
}
return_value = os__getfinalpathname_impl(module, path);
exit:
return return_value;
}
#endif /* defined(MS_WINDOWS) */
#if defined(MS_WINDOWS)
PyDoc_STRVAR(os__isdir__doc__,
@ -1017,23 +1011,18 @@ os__isdir(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
path_t path = PATH_T_INITIALIZE("_isdir", "path", 0, 0);
if (!PyArg_Parse(arg, "O&:_isdir", path_converter, &path)) {
goto exit;
}
return_value = os__isdir_impl(module, &path);
exit:
/* Cleanup for path */
path_cleanup(&path);
return return_value;
}
#endif /* defined(MS_WINDOWS) */
#if defined(MS_WINDOWS)
PyDoc_STRVAR(os__getvolumepathname__doc__,
"_getvolumepathname($module, /, path)\n"
"--\n"
@ -1053,19 +1042,15 @@ os__getvolumepathname(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObj
static const char * const _keywords[] = {"path", NULL};
static _PyArg_Parser _parser = {"U:_getvolumepathname", _keywords, 0};
PyObject *path;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&path)) {
goto exit;
}
return_value = os__getvolumepathname_impl(module, path);
exit:
return return_value;
}
#endif /* defined(MS_WINDOWS) */
PyDoc_STRVAR(os_mkdir__doc__,
"mkdir($module, /, path, mode=511, *, dir_fd=None)\n"
"--\n"

View file

@ -1,98 +0,0 @@
/* clang-format off */
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(SHA1Type_copy__doc__,
"copy($self, /)\n"
"--\n"
"\n"
"Return a copy of the hash object.");
#define SHA1TYPE_COPY_METHODDEF \
{"copy", (PyCFunction)SHA1Type_copy, METH_NOARGS, SHA1Type_copy__doc__},
static PyObject *
SHA1Type_copy_impl(SHA1object *self);
static PyObject *
SHA1Type_copy(SHA1object *self, PyObject *Py_UNUSED(ignored))
{
return SHA1Type_copy_impl(self);
}
PyDoc_STRVAR(SHA1Type_digest__doc__,
"digest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a bytes object.");
#define SHA1TYPE_DIGEST_METHODDEF \
{"digest", (PyCFunction)SHA1Type_digest, METH_NOARGS, SHA1Type_digest__doc__},
static PyObject *
SHA1Type_digest_impl(SHA1object *self);
static PyObject *
SHA1Type_digest(SHA1object *self, PyObject *Py_UNUSED(ignored))
{
return SHA1Type_digest_impl(self);
}
PyDoc_STRVAR(SHA1Type_hexdigest__doc__,
"hexdigest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a string of hexadecimal digits.");
#define SHA1TYPE_HEXDIGEST_METHODDEF \
{"hexdigest", (PyCFunction)SHA1Type_hexdigest, METH_NOARGS, SHA1Type_hexdigest__doc__},
static PyObject *
SHA1Type_hexdigest_impl(SHA1object *self);
static PyObject *
SHA1Type_hexdigest(SHA1object *self, PyObject *Py_UNUSED(ignored))
{
return SHA1Type_hexdigest_impl(self);
}
PyDoc_STRVAR(SHA1Type_update__doc__,
"update($self, obj, /)\n"
"--\n"
"\n"
"Update this hash object\'s state with the provided string.");
#define SHA1TYPE_UPDATE_METHODDEF \
{"update", (PyCFunction)SHA1Type_update, METH_O, SHA1Type_update__doc__},
PyDoc_STRVAR(_sha1_sha1__doc__,
"sha1($module, /, string=b\'\')\n"
"--\n"
"\n"
"Return a new SHA1 hash object; optionally initialized with a string.");
#define _SHA1_SHA1_METHODDEF \
{"sha1", (PyCFunction)_sha1_sha1, METH_FASTCALL, _sha1_sha1__doc__},
static PyObject *
_sha1_sha1_impl(PyObject *module, PyObject *string);
static PyObject *
_sha1_sha1(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", NULL};
static _PyArg_Parser _parser = {"|O:sha1", _keywords, 0};
PyObject *string = NULL;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&string)) {
goto exit;
}
return_value = _sha1_sha1_impl(module, string);
exit:
return return_value;
}
/*[clinic end generated code: output=34e9cee5761f2a36 input=a9049054013a1b77]*/

View file

@ -1,128 +0,0 @@
/* clang-format off */
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(SHA256Type_copy__doc__,
"copy($self, /)\n"
"--\n"
"\n"
"Return a copy of the hash object.");
#define SHA256TYPE_COPY_METHODDEF \
{"copy", (PyCFunction)SHA256Type_copy, METH_NOARGS, SHA256Type_copy__doc__},
static PyObject *
SHA256Type_copy_impl(SHAobject *self);
static PyObject *
SHA256Type_copy(SHAobject *self, PyObject *Py_UNUSED(ignored))
{
return SHA256Type_copy_impl(self);
}
PyDoc_STRVAR(SHA256Type_digest__doc__,
"digest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a bytes object.");
#define SHA256TYPE_DIGEST_METHODDEF \
{"digest", (PyCFunction)SHA256Type_digest, METH_NOARGS, SHA256Type_digest__doc__},
static PyObject *
SHA256Type_digest_impl(SHAobject *self);
static PyObject *
SHA256Type_digest(SHAobject *self, PyObject *Py_UNUSED(ignored))
{
return SHA256Type_digest_impl(self);
}
PyDoc_STRVAR(SHA256Type_hexdigest__doc__,
"hexdigest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a string of hexadecimal digits.");
#define SHA256TYPE_HEXDIGEST_METHODDEF \
{"hexdigest", (PyCFunction)SHA256Type_hexdigest, METH_NOARGS, SHA256Type_hexdigest__doc__},
static PyObject *
SHA256Type_hexdigest_impl(SHAobject *self);
static PyObject *
SHA256Type_hexdigest(SHAobject *self, PyObject *Py_UNUSED(ignored))
{
return SHA256Type_hexdigest_impl(self);
}
PyDoc_STRVAR(SHA256Type_update__doc__,
"update($self, obj, /)\n"
"--\n"
"\n"
"Update this hash object\'s state with the provided string.");
#define SHA256TYPE_UPDATE_METHODDEF \
{"update", (PyCFunction)SHA256Type_update, METH_O, SHA256Type_update__doc__},
PyDoc_STRVAR(_sha256_sha256__doc__,
"sha256($module, /, string=b\'\')\n"
"--\n"
"\n"
"Return a new SHA-256 hash object; optionally initialized with a string.");
#define _SHA256_SHA256_METHODDEF \
{"sha256", (PyCFunction)_sha256_sha256, METH_FASTCALL, _sha256_sha256__doc__},
static PyObject *
_sha256_sha256_impl(PyObject *module, PyObject *string);
static PyObject *
_sha256_sha256(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", NULL};
static _PyArg_Parser _parser = {"|O:sha256", _keywords, 0};
PyObject *string = NULL;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&string)) {
goto exit;
}
return_value = _sha256_sha256_impl(module, string);
exit:
return return_value;
}
PyDoc_STRVAR(_sha256_sha224__doc__,
"sha224($module, /, string=b\'\')\n"
"--\n"
"\n"
"Return a new SHA-224 hash object; optionally initialized with a string.");
#define _SHA256_SHA224_METHODDEF \
{"sha224", (PyCFunction)_sha256_sha224, METH_FASTCALL, _sha256_sha224__doc__},
static PyObject *
_sha256_sha224_impl(PyObject *module, PyObject *string);
static PyObject *
_sha256_sha224(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", NULL};
static _PyArg_Parser _parser = {"|O:sha224", _keywords, 0};
PyObject *string = NULL;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&string)) {
goto exit;
}
return_value = _sha256_sha224_impl(module, string);
exit:
return return_value;
}
/*[clinic end generated code: output=3babbe1e753c1a38 input=a9049054013a1b77]*/

View file

@ -1,128 +0,0 @@
/* clang-format off */
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(SHA512Type_copy__doc__,
"copy($self, /)\n"
"--\n"
"\n"
"Return a copy of the hash object.");
#define SHA512TYPE_COPY_METHODDEF \
{"copy", (PyCFunction)SHA512Type_copy, METH_NOARGS, SHA512Type_copy__doc__},
static PyObject *
SHA512Type_copy_impl(SHAobject *self);
static PyObject *
SHA512Type_copy(SHAobject *self, PyObject *Py_UNUSED(ignored))
{
return SHA512Type_copy_impl(self);
}
PyDoc_STRVAR(SHA512Type_digest__doc__,
"digest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a bytes object.");
#define SHA512TYPE_DIGEST_METHODDEF \
{"digest", (PyCFunction)SHA512Type_digest, METH_NOARGS, SHA512Type_digest__doc__},
static PyObject *
SHA512Type_digest_impl(SHAobject *self);
static PyObject *
SHA512Type_digest(SHAobject *self, PyObject *Py_UNUSED(ignored))
{
return SHA512Type_digest_impl(self);
}
PyDoc_STRVAR(SHA512Type_hexdigest__doc__,
"hexdigest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a string of hexadecimal digits.");
#define SHA512TYPE_HEXDIGEST_METHODDEF \
{"hexdigest", (PyCFunction)SHA512Type_hexdigest, METH_NOARGS, SHA512Type_hexdigest__doc__},
static PyObject *
SHA512Type_hexdigest_impl(SHAobject *self);
static PyObject *
SHA512Type_hexdigest(SHAobject *self, PyObject *Py_UNUSED(ignored))
{
return SHA512Type_hexdigest_impl(self);
}
PyDoc_STRVAR(SHA512Type_update__doc__,
"update($self, obj, /)\n"
"--\n"
"\n"
"Update this hash object\'s state with the provided string.");
#define SHA512TYPE_UPDATE_METHODDEF \
{"update", (PyCFunction)SHA512Type_update, METH_O, SHA512Type_update__doc__},
PyDoc_STRVAR(_sha512_sha512__doc__,
"sha512($module, /, string=b\'\')\n"
"--\n"
"\n"
"Return a new SHA-512 hash object; optionally initialized with a string.");
#define _SHA512_SHA512_METHODDEF \
{"sha512", (PyCFunction)_sha512_sha512, METH_FASTCALL, _sha512_sha512__doc__},
static PyObject *
_sha512_sha512_impl(PyObject *module, PyObject *string);
static PyObject *
_sha512_sha512(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", NULL};
static _PyArg_Parser _parser = {"|O:sha512", _keywords, 0};
PyObject *string = NULL;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&string)) {
goto exit;
}
return_value = _sha512_sha512_impl(module, string);
exit:
return return_value;
}
PyDoc_STRVAR(_sha512_sha384__doc__,
"sha384($module, /, string=b\'\')\n"
"--\n"
"\n"
"Return a new SHA-384 hash object; optionally initialized with a string.");
#define _SHA512_SHA384_METHODDEF \
{"sha384", (PyCFunction)_sha512_sha384, METH_FASTCALL, _sha512_sha384__doc__},
static PyObject *
_sha512_sha384_impl(PyObject *module, PyObject *string);
static PyObject *
_sha512_sha384(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", NULL};
static _PyArg_Parser _parser = {"|O:sha384", _keywords, 0};
PyObject *string = NULL;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&string)) {
goto exit;
}
return_value = _sha512_sha384_impl(module, string);
exit:
return return_value;
}
/*[clinic end generated code: output=59a43fa6eb3b5f4f input=a9049054013a1b77]*/

View file

@ -111,7 +111,8 @@ PyDoc_STRVAR(zlib_compressobj__doc__,
" usage, faster compression, and smaller output.\n"
" strategy\n"
" Used to tune the compression algorithm. Possible values are\n"
" Z_DEFAULT_STRATEGY, Z_FILTERED, and Z_HUFFMAN_ONLY.\n"
" Z_DEFAULT_STRATEGY, Z_RLE, Z_HUFFMAN_ONLY, Z_FILTERED, and\n"
" Z_FIXED.\n"
" zdict\n"
" The predefined compression dictionary - a sequence of bytes\n"
" containing subsequences that are likely to occur in the input data.");

View file

@ -4,110 +4,35 @@
Python 3
https://docs.python.org/3/license.html │
*/
#include "third_party/python/Include/Python.h"
#include "third_party/python/Include/cosmo.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/pyport.h"
#include "third_party/python/Include/object.h"
/* clang-format off */
PyObject *PyInit__ast(void);
PyObject *PyInit__bisect(void);
PyObject *PyInit__bz2(void);
PyObject *PyInit__codecs(void);
PyObject *PyInit__codecs_cn(void);
PyObject *PyInit__codecs_hk(void);
PyObject *PyInit__codecs_iso2022(void);
PyObject *PyInit__codecs_jp(void);
PyObject *PyInit__codecs_kr(void);
PyObject *PyInit__codecs_tw(void);
PyObject *PyInit__collections(void);
PyObject *PyInit__csv(void);
PyObject *PyInit__datetime(void);
PyObject *PyInit__decimal(void);
PyObject *PyInit__elementtree(void);
PyObject *PyInit__functools(void);
PyObject *PyInit__heapq(void);
PyObject *PyInit__io(void);
PyObject *PyInit__json(void);
PyObject *PyInit__locale(void);
PyObject *PyInit__lsprof(void);
PyObject *PyInit__md5(void);
PyObject *PyInit__multibytecodec(void);
PyObject *PyInit__multiprocessing(void);
PyObject *PyInit__opcode(void);
PyObject *PyInit__operator(void);
PyObject *PyInit__pickle(void);
PyObject *PyInit__posixsubprocess(void);
PyObject *PyInit__random(void);
PyObject *PyInit__sha1(void);
PyObject *PyInit__sha256(void);
PyObject *PyInit__sha3(void);
PyObject *PyInit__sha512(void);
PyObject *PyInit__signal(void);
PyObject *PyInit__socket(void);
PyObject *PyInit__sqlite3(void);
PyObject *PyInit__sre(void);
PyObject *PyInit__stat(void);
PyObject *PyInit__string(void);
PyObject *PyInit__struct(void);
PyObject *PyInit__symtable(void);
PyObject *PyInit__testcapi(void);
PyObject *PyInit__tracemalloc(void);
PyObject *PyInit__weakref(void);
PyObject *PyInit_array(void);
PyObject *PyInit_atexit(void);
PyObject *PyInit_audioop(void);
PyObject *PyInit_binascii(void);
PyObject *PyInit_cmath(void);
PyObject *PyInit_cosmo(void);
PyObject *PyInit_errno(void);
PyObject *PyInit_faulthandler(void);
PyObject *PyInit_fcntl(void);
PyObject *PyInit_fpectl(void);
PyObject *PyInit_gc(void);
PyObject *PyInit_grp(void);
PyObject *PyInit_imp(void);
PyObject *PyInit_itertools(void);
PyObject *PyInit_math(void);
PyObject *PyInit_mmap(void);
PyObject *PyInit_parser(void);
PyObject *PyInit_posix(void);
PyObject *PyInit_pwd(void);
PyObject *PyInit_pyexpat(void);
PyObject *PyInit_resource(void);
PyObject *PyInit_select(void);
PyObject *PyInit_syslog(void);
PyObject *PyInit_termios(void);
PyObject *PyInit_time(void);
PyObject *PyInit_unicodedata(void);
PyObject *PyInit_zipimport(void);
PyObject *PyInit_zlib(void);
PyObject *PyInit__codecs(void);
PyObject *PyInit_itertools(void);
PyObject *PyInit__io(void);
PyObject *PyInit__weakref(void);
PyObject *PyMarshal_Init(void);
PyObject *PyInit__ast(void);
PyObject *PyInit_gc(void);
PyObject *_PyWarnings_Init(void);
PyObject *PyInit__string(void);
_Alignas(16) _Section(".rodata.pytab.0") const struct _inittab _PyImport_Inittab[0];
_Alignas(16) _Section(".rodata.pytab.2") const struct _inittab _PyImport_Inittab2[] = {
{"posix", PyInit_posix},
{"errno", PyInit_errno},
{"_sre", PyInit__sre},
{"_codecs", PyInit__codecs},
{"_functools", PyInit__functools},
{"_operator", PyInit__operator},
{"_collections", PyInit__collections},
{"itertools", PyInit_itertools},
{"_signal", PyInit__signal},
{"_locale", PyInit__locale},
{"_io", PyInit__io},
{"_weakref", PyInit__weakref},
{"_heapq", PyInit__heapq},
{"marshal", PyMarshal_Init},
{"_imp", PyInit_imp},
{"_cosmo", PyInit_cosmo},
{"_ast", PyInit__ast},
{"builtins", NULL},
{"sys", NULL},
{"gc", PyInit_gc},
{"_warnings", _PyWarnings_Init},
{"_warnings", _PyWarnings_Init},
{"_string", PyInit__string},
{0, 0}
{0}
};

View file

@ -1,59 +0,0 @@
/* clang-format off */
/* -*- C -*- ***********************************************
Copyright (c) 2000, BeOpen.com.
Copyright (c) 1995-2000, Corporation for National Research Initiatives.
Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
All rights reserved.
See the file "Misc/COPYRIGHT" for information on usage and
redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
******************************************************************/
/* Module configuration */
/* !!! !!! !!! This file is edited by the makesetup script !!! !!! !!! */
/* This file contains the table of built-in modules.
See create_builtin() in import.c. */
#include "third_party/python/Include/Python.h"
/* -- ADDMODULE MARKER 1 -- */
extern PyObject* PyMarshal_Init(void);
extern PyObject* PyInit_imp(void);
extern PyObject* PyInit_gc(void);
extern PyObject* PyInit__ast(void);
extern PyObject* _PyWarnings_Init(void);
extern PyObject* PyInit__string(void);
struct _inittab _PyImport_Inittab[] = {
/* -- ADDMODULE MARKER 2 -- */
/* This module lives in marshal.c */
{"marshal", PyMarshal_Init},
/* This lives in import.c */
{"_imp", PyInit_imp},
/* This lives in Python/Python-ast.c */
{"_ast", PyInit__ast},
/* These entries are here for sys.builtin_module_names */
{"builtins", NULL},
{"sys", NULL},
/* This lives in gcmodule.c */
{"gc", PyInit_gc},
/* This lives in _warnings.c */
{"_warnings", _PyWarnings_Init},
/* This lives in Objects/unicodeobject.c */
{"_string", PyInit__string},
/* Sentinel */
{0, 0}
};

View file

@ -399,3 +399,8 @@ PyInit_errno(void)
Py_DECREF(de);
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab_errno = {
"errno",
PyInit_errno,
};

View file

@ -1,8 +1,11 @@
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/timeval.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
@ -593,11 +596,30 @@ static unsigned long get_hash_secret_salt(XML_Parser parser) {
return parser->m_hash_secret_salt;
}
static uint64_t getsome(void) {
int i;
char cf;
uint64_t x;
if (X86_HAVE(RDRND)) {
for (i = 0; i < 10; ++i) {
asm volatile(CFLAG_ASM("rdrand\t%1")
: CFLAG_CONSTRAINT(cf), "=r"(x)
: /* no inputs */
: "cc");
if (cf) return x;
asm volatile("pause");
}
}
if (getrandom(&x, 8, 0) != 8) abort();
return x;
}
static XML_Bool /* only valid for root parser */
startParsing(XML_Parser parser) {
/* hash functions must be initialized before setContext() is called */
if (parser->m_hash_secret_salt == 0)
parser->m_hash_secret_salt = rand64();
if (!parser->m_hash_secret_salt) {
parser->m_hash_secret_salt = getsome();
}
if (parser->m_ns) {
/* implicit context only set for root parser, since child
parsers (i.e. external entity parsers) will inherit it
@ -2421,7 +2443,7 @@ static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
rawName = s + enc->minBytesPerChar * 2;
len = XmlNameLength(enc, rawName);
if (len != tag->rawNameLength ||
memcmp(tag->rawName, rawName, len) != 0) {
bcmp(tag->rawName, rawName, len)) {
*eventPP = rawName;
return XML_ERROR_TAG_MISMATCH;
}

View file

@ -23,6 +23,7 @@
#include "third_party/python/Include/pyerrors.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/python/pyconfig.h"
/* clang-format off */
PYTHON_PROVIDE("fcntl");
@ -74,7 +75,6 @@ static int
conv_descriptor(PyObject *object, int *target)
{
int fd = PyObject_AsFileDescriptor(object);
if (fd < 0)
return 0;
*target = fd;
@ -337,7 +337,6 @@ fcntl_flock_impl(PyObject *module, int fd, int code)
{
int ret;
int async_err = 0;
#ifdef HAVE_FLOCK
do {
Py_BEGIN_ALLOW_THREADS
@ -345,13 +344,6 @@ fcntl_flock_impl(PyObject *module, int fd, int code)
Py_END_ALLOW_THREADS
} while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
#else
#ifndef LOCK_SH
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_NB 4 /* don't block when locking */
#define LOCK_UN 8 /* unlock */
#endif
{
struct flock l;
if (code == LOCK_UN)
@ -674,7 +666,6 @@ all_ins(PyObject* m)
return 0;
}
static struct PyModuleDef fcntlmodule = {
PyModuleDef_HEAD_INIT,
"fcntl",
@ -691,16 +682,13 @@ PyMODINIT_FUNC
PyInit_fcntl(void)
{
PyObject *m;
/* Create the module and add the functions and documentation */
m = PyModule_Create(&fcntlmodule);
if (m == NULL)
return NULL;
/* Add some symbolic constants to the module */
if (all_ins(m) < 0)
return NULL;
return m;
}

View file

@ -1728,14 +1728,6 @@ _PyGC_Dump(PyGC_Head *g)
_PyObject_Dump(FROM_GC(g));
}
/* extension modules might be compiled with GC support so these
functions must always be available */
#undef PyObject_GC_Track
#undef PyObject_GC_UnTrack
#undef PyObject_GC_Del
#undef _PyObject_GC_Malloc
void
PyObject_GC_Track(void *op)
{
@ -1743,7 +1735,7 @@ PyObject_GC_Track(void *op)
}
void
PyObject_GC_UnTrack(void *op)
(PyObject_GC_UnTrack)(void *op)
{
/* Obscure: the Py_TRASHCAN mechanism requires that we be able to
* call PyObject_GC_UnTrack twice on an object.
@ -1752,7 +1744,7 @@ PyObject_GC_UnTrack(void *op)
_PyObject_GC_UNTRACK(op);
}
static PyObject *
PyObject *
_PyObject_GC_Alloc(int use_calloc, size_t basicsize)
{
PyObject *op;
@ -1784,13 +1776,13 @@ _PyObject_GC_Alloc(int use_calloc, size_t basicsize)
}
PyObject *
_PyObject_GC_Malloc(size_t basicsize)
(_PyObject_GC_Malloc)(size_t basicsize)
{
return _PyObject_GC_Alloc(0, basicsize);
}
PyObject *
_PyObject_GC_Calloc(size_t basicsize)
(_PyObject_GC_Calloc)(size_t basicsize)
{
return _PyObject_GC_Alloc(1, basicsize);
}
@ -1809,7 +1801,6 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
{
size_t size;
PyVarObject *op;
if (nitems < 0) {
PyErr_BadInternalCall();
return NULL;

View file

@ -8,33 +8,6 @@
#include "third_party/python/Include/pylifecycle.h"
/* clang-format off */
#ifndef DATE
#ifdef __DATE__
#define DATE __DATE__
#else
#define DATE "xx/xx/xx"
#endif
#endif
#ifndef TIME
#ifdef __TIME__
#define TIME __TIME__
#else
#define TIME "xx:xx:xx"
#endif
#endif
/* XXX Only unix build process has been tested */
#ifndef GITVERSION
#define GITVERSION ""
#endif
#ifndef GITTAG
#define GITTAG ""
#endif
#ifndef GITBRANCH
#define GITBRANCH ""
#endif
const char *
Py_GetBuildInfo(void)
{

View file

@ -36,11 +36,11 @@ module grp
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cade63f2ed1bd9f8]*/
static PyStructSequence_Field struct_group_type_fields[] = {
{"gr_name", "group name"},
{"gr_passwd", "password"},
{"gr_gid", "group id"},
{"gr_mem", "group members"},
{0}
{"gr_name", PyDoc_STR("group name")},
{"gr_passwd", PyDoc_STR("password")},
{"gr_gid", PyDoc_STR("group id")},
{"gr_mem", PyDoc_STR("group members")},
{0}
};
PyDoc_STRVAR(struct_group__doc__,

View file

@ -132,7 +132,7 @@ _Py_hashtable_compare_direct(_Py_hashtable_t *ht, const void *pkey,
const _Py_hashtable_entry_t *entry)
{
const void *pkey2 = _Py_HASHTABLE_ENTRY_PKEY(entry);
return (memcmp(pkey, pkey2, ht->key_size) == 0);
return !bcmp(pkey, pkey2, ht->key_size);
}

View file

@ -5,6 +5,7 @@
https://docs.python.org/3/license.html │
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/stdio/stdio.h"
#include "libc/unicode/locale.h"
@ -24,12 +25,12 @@
#include "third_party/python/Include/pythonrun.h"
#include "third_party/python/Include/sysmodule.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/python/pyconfig.h"
/* clang-format off */
STATIC_YOINK("PyInit__codecs"); // for pylifecycle.o
STATIC_YOINK("PyInit__collections"); // for pylifecycle.o
STATIC_YOINK("PyInit__functools"); // for pylifecycle.o
STATIC_YOINK("PyInit__heapq"); // for pylifecycle.o
STATIC_YOINK("PyInit__locale"); // for pylifecycle.o
STATIC_YOINK("PyInit__operator"); // for pylifecycle.o
STATIC_YOINK("PyInit__signal"); // for pylifecycle.o
@ -50,7 +51,7 @@ PYTHON_YOINK("site");
PYTHON_YOINK("_sysconfigdata_m_cosmo_x86_64_cosmo");
PYTHON_YOINK("_bootlocale");
PYTHON_YOINK("warnings");
PYTHON_YOINK("_warnings");
PYTHON_YOINK("_locale");
PYTHON_YOINK("locale");
PYTHON_YOINK("runpy");
@ -655,7 +656,7 @@ Py_Main(int argc, wchar_t **argv)
_setmode(fileno(stderr), O_BINARY);
#endif
if (1 || Py_UnbufferedStdioFlag) {
if (Py_UnbufferedStdioFlag) {
#ifdef HAVE_SETVBUF
setvbuf(stdin, (char *)NULL, _IONBF, BUFSIZ);
setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
@ -680,57 +681,52 @@ Py_Main(int argc, wchar_t **argv)
/* Leave stderr alone - it should be unbuffered anyway. */
}
#ifdef __APPLE__
/* On MacOS X, when the Python interpreter is embedded in an
application bundle, it gets executed by a bootstrapping script
that does os.execve() with an argv[0] that's different from the
actual Python executable. This is needed to keep the Finder happy,
or rather, to work around Apple's overly strict requirements of
the process name. However, we still need a usable sys.executable,
so the actual executable path is passed in an environment variable.
See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
script. */
if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') {
wchar_t* buffer;
size_t len = strlen(p) + 1;
buffer = PyMem_RawMalloc(len * sizeof(wchar_t));
if (buffer == NULL) {
Py_FatalError(
"not enough memory to copy PYTHONEXECUTABLE");
}
mbstowcs(buffer, p, len);
Py_SetProgramName(buffer);
/* buffer is now handed off - do not free */
} else {
#ifdef WITH_NEXT_FRAMEWORK
char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__");
if (pyvenv_launcher && *pyvenv_launcher) {
/* Used by Mac/Tools/pythonw.c to forward
* the argv0 of the stub executable
*/
wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, NULL);
if (wbuf == NULL) {
Py_FatalError("Cannot decode __PYVENV_LAUNCHER__");
}
Py_SetProgramName(wbuf);
/* Don't free wbuf, the argument to Py_SetProgramName
* must remain valid until Py_FinalizeEx is called.
*/
} else {
Py_SetProgramName(argv[0]);
}
#else
if (!IsXnu()) {
Py_SetProgramName(argv[0]);
#endif
} else {
/* On MacOS X, when the Python interpreter is embedded in an
application bundle, it gets executed by a bootstrapping script
that does os.execve() with an argv[0] that's different from the
actual Python executable. This is needed to keep the Finder happy,
or rather, to work around Apple's overly strict requirements of
the process name. However, we still need a usable sys.executable,
so the actual executable path is passed in an environment variable.
See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
script. */
if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') {
wchar_t* buffer;
size_t len = strlen(p) + 1;
buffer = PyMem_RawMalloc(len * sizeof(wchar_t));
if (buffer == NULL) {
Py_FatalError(
"not enough memory to copy PYTHONEXECUTABLE");
}
mbstowcs(buffer, p, len);
Py_SetProgramName(buffer);
/* buffer is now handed off - do not free */
} else {
#ifdef WITH_NEXT_FRAMEWORK
char* pyvenv_launcher = getenv("__PYVENV_LAUNCHER__");
if (pyvenv_launcher && *pyvenv_launcher) {
/* Used by Mac/Tools/pythonw.c to forward
* the argv0 of the stub executable
*/
wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, NULL);
if (wbuf == NULL) {
Py_FatalError("Cannot decode __PYVENV_LAUNCHER__");
}
Py_SetProgramName(wbuf);
/* Don't free wbuf, the argument to Py_SetProgramName
* must remain valid until Py_FinalizeEx is called.
*/
} else {
Py_SetProgramName(argv[0]);
}
#else /* WITH_NEXT_FRAMEWORK */
Py_SetProgramName(argv[0]);
#endif /* WITH_NEXT_FRAMEWORK */
}
}
#else
Py_SetProgramName(argv[0]);
#endif
Py_Initialize();
Py_XDECREF(warning_options);

View file

@ -1,604 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "libc/assert.h"
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/bytesobject.h"
#include "third_party/python/Include/descrobject.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/longobject.h"
#include "third_party/python/Include/modsupport.h"
#include "third_party/python/Include/objimpl.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/pystrhex.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/python/Modules/hashlib.h"
/* clang-format off */
PYTHON_PROVIDE("_md5");
PYTHON_PROVIDE("_md5.MD5Type");
PYTHON_PROVIDE("_md5.md5");
/* See below for information about the original code this module was
based upon. Additional work performed by:
Andrew Kuchling (amk@amk.ca)
Greg Stein (gstein@lyra.org)
Trevor Perrin (trevp@trevp.net)
Copyright (C) 2005-2007 Gregory P. Smith (greg@krypto.org)
Licensed to PSF under a Contributor Agreement.
*/
/*[clinic input]
module _md5
class MD5Type "MD5object *" "&PyType_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6e5261719957a912]*/
/* Some useful types */
#if SIZEOF_INT == 4
typedef unsigned int MD5_INT32; /* 32-bit integer */
typedef long long MD5_INT64; /* 64-bit integer */
#else
/* not defined. compilation will die. */
#endif
/* The MD5 block size and message digest sizes, in bytes */
#define MD5_BLOCKSIZE 64
#define MD5_DIGESTSIZE 16
/* The structure for storing MD5 info */
struct md5_state {
MD5_INT64 length;
MD5_INT32 state[4], curlen;
unsigned char buf[MD5_BLOCKSIZE];
};
typedef struct {
PyObject_HEAD
struct md5_state hash_state;
} MD5object;
#include "third_party/python/Modules/clinic/md5module.inc"
/* ------------------------------------------------------------------------
*
* This code for the MD5 algorithm was noted as public domain. The
* original headers are pasted below.
*
* Several changes have been made to make it more compatible with the
* Python environment and desired interface.
*
*/
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
/* rotate the hard way (platform optimizations could be done) */
#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
/* Endian Neutral macros that work on all platforms */
#define STORE32L(x, y) \
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD32L(x, y) \
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
((unsigned long)((y)[2] & 255)<<16) | \
((unsigned long)((y)[1] & 255)<<8) | \
((unsigned long)((y)[0] & 255)); }
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
/* MD5 macros */
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define G(x,y,z) (y ^ (z & (y ^ x)))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y^(x|(~z)))
#define FF(a,b,c,d,M,s,t) \
a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b;
#define GG(a,b,c,d,M,s,t) \
a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b;
#define HH(a,b,c,d,M,s,t) \
a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b;
#define II(a,b,c,d,M,s,t) \
a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b;
static void md5_compress(struct md5_state *md5, unsigned char *buf)
{
MD5_INT32 i, W[16], a, b, c, d;
assert(md5 != NULL);
assert(buf != NULL);
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32L(W[i], buf + (4*i));
}
/* copy state */
a = md5->state[0];
b = md5->state[1];
c = md5->state[2];
d = md5->state[3];
FF(a,b,c,d,W[0],7,0xd76aa478UL)
FF(d,a,b,c,W[1],12,0xe8c7b756UL)
FF(c,d,a,b,W[2],17,0x242070dbUL)
FF(b,c,d,a,W[3],22,0xc1bdceeeUL)
FF(a,b,c,d,W[4],7,0xf57c0fafUL)
FF(d,a,b,c,W[5],12,0x4787c62aUL)
FF(c,d,a,b,W[6],17,0xa8304613UL)
FF(b,c,d,a,W[7],22,0xfd469501UL)
FF(a,b,c,d,W[8],7,0x698098d8UL)
FF(d,a,b,c,W[9],12,0x8b44f7afUL)
FF(c,d,a,b,W[10],17,0xffff5bb1UL)
FF(b,c,d,a,W[11],22,0x895cd7beUL)
FF(a,b,c,d,W[12],7,0x6b901122UL)
FF(d,a,b,c,W[13],12,0xfd987193UL)
FF(c,d,a,b,W[14],17,0xa679438eUL)
FF(b,c,d,a,W[15],22,0x49b40821UL)
GG(a,b,c,d,W[1],5,0xf61e2562UL)
GG(d,a,b,c,W[6],9,0xc040b340UL)
GG(c,d,a,b,W[11],14,0x265e5a51UL)
GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)
GG(a,b,c,d,W[5],5,0xd62f105dUL)
GG(d,a,b,c,W[10],9,0x02441453UL)
GG(c,d,a,b,W[15],14,0xd8a1e681UL)
GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)
GG(a,b,c,d,W[9],5,0x21e1cde6UL)
GG(d,a,b,c,W[14],9,0xc33707d6UL)
GG(c,d,a,b,W[3],14,0xf4d50d87UL)
GG(b,c,d,a,W[8],20,0x455a14edUL)
GG(a,b,c,d,W[13],5,0xa9e3e905UL)
GG(d,a,b,c,W[2],9,0xfcefa3f8UL)
GG(c,d,a,b,W[7],14,0x676f02d9UL)
GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
HH(a,b,c,d,W[5],4,0xfffa3942UL)
HH(d,a,b,c,W[8],11,0x8771f681UL)
HH(c,d,a,b,W[11],16,0x6d9d6122UL)
HH(b,c,d,a,W[14],23,0xfde5380cUL)
HH(a,b,c,d,W[1],4,0xa4beea44UL)
HH(d,a,b,c,W[4],11,0x4bdecfa9UL)
HH(c,d,a,b,W[7],16,0xf6bb4b60UL)
HH(b,c,d,a,W[10],23,0xbebfbc70UL)
HH(a,b,c,d,W[13],4,0x289b7ec6UL)
HH(d,a,b,c,W[0],11,0xeaa127faUL)
HH(c,d,a,b,W[3],16,0xd4ef3085UL)
HH(b,c,d,a,W[6],23,0x04881d05UL)
HH(a,b,c,d,W[9],4,0xd9d4d039UL)
HH(d,a,b,c,W[12],11,0xe6db99e5UL)
HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
HH(b,c,d,a,W[2],23,0xc4ac5665UL)
II(a,b,c,d,W[0],6,0xf4292244UL)
II(d,a,b,c,W[7],10,0x432aff97UL)
II(c,d,a,b,W[14],15,0xab9423a7UL)
II(b,c,d,a,W[5],21,0xfc93a039UL)
II(a,b,c,d,W[12],6,0x655b59c3UL)
II(d,a,b,c,W[3],10,0x8f0ccc92UL)
II(c,d,a,b,W[10],15,0xffeff47dUL)
II(b,c,d,a,W[1],21,0x85845dd1UL)
II(a,b,c,d,W[8],6,0x6fa87e4fUL)
II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
II(c,d,a,b,W[6],15,0xa3014314UL)
II(b,c,d,a,W[13],21,0x4e0811a1UL)
II(a,b,c,d,W[4],6,0xf7537e82UL)
II(d,a,b,c,W[11],10,0xbd3af235UL)
II(c,d,a,b,W[2],15,0x2ad7d2bbUL)
II(b,c,d,a,W[9],21,0xeb86d391UL)
md5->state[0] = md5->state[0] + a;
md5->state[1] = md5->state[1] + b;
md5->state[2] = md5->state[2] + c;
md5->state[3] = md5->state[3] + d;
}
/**
Initialize the hash state
@param sha1 The hash state you wish to initialize
*/
static void
md5_init(struct md5_state *md5)
{
assert(md5 != NULL);
md5->state[0] = 0x67452301UL;
md5->state[1] = 0xefcdab89UL;
md5->state[2] = 0x98badcfeUL;
md5->state[3] = 0x10325476UL;
md5->curlen = 0;
md5->length = 0;
}
/**
Process a block of memory though the hash
@param sha1 The hash state
@param in The data to hash
@param inlen The length of the data (octets)
*/
static void
md5_process(struct md5_state *md5, const unsigned char *in, Py_ssize_t inlen)
{
Py_ssize_t n;
assert(md5 != NULL);
assert(in != NULL);
assert(md5->curlen <= sizeof(md5->buf));
while (inlen > 0) {
if (md5->curlen == 0 && inlen >= MD5_BLOCKSIZE) {
md5_compress(md5, (unsigned char *)in);
md5->length += MD5_BLOCKSIZE * 8;
in += MD5_BLOCKSIZE;
inlen -= MD5_BLOCKSIZE;
} else {
n = Py_MIN(inlen, (Py_ssize_t)(MD5_BLOCKSIZE - md5->curlen));
memcpy(md5->buf + md5->curlen, in, (size_t)n);
md5->curlen += (MD5_INT32)n;
in += n;
inlen -= n;
if (md5->curlen == MD5_BLOCKSIZE) {
md5_compress(md5, md5->buf);
md5->length += 8*MD5_BLOCKSIZE;
md5->curlen = 0;
}
}
}
}
/**
Terminate the hash to get the digest
@param sha1 The hash state
@param out [out] The destination of the hash (16 bytes)
*/
static void
md5_done(struct md5_state *md5, unsigned char *out)
{
int i;
assert(md5 != NULL);
assert(out != NULL);
assert(md5->curlen < sizeof(md5->buf));
/* increase the length of the message */
md5->length += md5->curlen * 8;
/* append the '1' bit */
md5->buf[md5->curlen++] = (unsigned char)0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md5->curlen > 56) {
while (md5->curlen < 64) {
md5->buf[md5->curlen++] = (unsigned char)0;
}
md5_compress(md5, md5->buf);
md5->curlen = 0;
}
/* pad up to 56 bytes of zeroes */
while (md5->curlen < 56) {
md5->buf[md5->curlen++] = (unsigned char)0;
}
/* store length */
STORE64L(md5->length, md5->buf+56);
md5_compress(md5, md5->buf);
/* copy output */
for (i = 0; i < 4; i++) {
STORE32L(md5->state[i], out+(4*i));
}
}
/* .Source: /cvs/libtom/libtomcrypt/src/hashes/md5.c,v $ */
/* .Revision: 1.10 $ */
/* .Date: 2007/05/12 14:25:28 $ */
/*
* End of copied MD5 code.
*
* ------------------------------------------------------------------------
*/
static PyTypeObject MD5type;
static MD5object *
newMD5object(void)
{
return (MD5object *)PyObject_New(MD5object, &MD5type);
}
/* Internal methods for a hash object */
static void
MD5_dealloc(PyObject *ptr)
{
PyObject_Del(ptr);
}
/* External methods for a hash object */
/*[clinic input]
MD5Type.copy
Return a copy of the hash object.
[clinic start generated code]*/
static PyObject *
MD5Type_copy_impl(MD5object *self)
/*[clinic end generated code: output=596eb36852f02071 input=2c09e6d2493f3079]*/
{
MD5object *newobj;
if ((newobj = newMD5object())==NULL)
return NULL;
newobj->hash_state = self->hash_state;
return (PyObject *)newobj;
}
/*[clinic input]
MD5Type.digest
Return the digest value as a bytes object.
[clinic start generated code]*/
static PyObject *
MD5Type_digest_impl(MD5object *self)
/*[clinic end generated code: output=eb691dc4190a07ec input=bc0c4397c2994be6]*/
{
unsigned char digest[MD5_DIGESTSIZE];
struct md5_state temp;
temp = self->hash_state;
md5_done(&temp, digest);
return PyBytes_FromStringAndSize((const char *)digest, MD5_DIGESTSIZE);
}
/*[clinic input]
MD5Type.hexdigest
Return the digest value as a string of hexadecimal digits.
[clinic start generated code]*/
static PyObject *
MD5Type_hexdigest_impl(MD5object *self)
/*[clinic end generated code: output=17badced1f3ac932 input=b60b19de644798dd]*/
{
unsigned char digest[MD5_DIGESTSIZE];
struct md5_state temp;
/* Get the raw (binary) digest value */
temp = self->hash_state;
md5_done(&temp, digest);
return _Py_strhex((const char*)digest, MD5_DIGESTSIZE);
}
/*[clinic input]
MD5Type.update
obj: object
/
Update this hash object's state with the provided string.
[clinic start generated code]*/
static PyObject *
MD5Type_update(MD5object *self, PyObject *obj)
/*[clinic end generated code: output=f6ad168416338423 input=6e1efcd9ecf17032]*/
{
Py_buffer buf;
GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
md5_process(&self->hash_state, buf.buf, buf.len);
PyBuffer_Release(&buf);
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef MD5_methods[] = {
MD5TYPE_COPY_METHODDEF
MD5TYPE_DIGEST_METHODDEF
MD5TYPE_HEXDIGEST_METHODDEF
MD5TYPE_UPDATE_METHODDEF
{NULL, NULL} /* sentinel */
};
static PyObject *
MD5_get_block_size(PyObject *self, void *closure)
{
return PyLong_FromLong(MD5_BLOCKSIZE);
}
static PyObject *
MD5_get_name(PyObject *self, void *closure)
{
return PyUnicode_FromStringAndSize("md5", 3);
}
static PyObject *
md5_get_digest_size(PyObject *self, void *closure)
{
return PyLong_FromLong(MD5_DIGESTSIZE);
}
static PyGetSetDef MD5_getseters[] = {
{"block_size",
(getter)MD5_get_block_size, NULL,
NULL,
NULL},
{"name",
(getter)MD5_get_name, NULL,
NULL,
NULL},
{"digest_size",
(getter)md5_get_digest_size, NULL,
NULL,
NULL},
{NULL} /* Sentinel */
};
static PyTypeObject MD5type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_md5.md5", /*tp_name*/
sizeof(MD5object), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
MD5_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
MD5_methods, /* tp_methods */
NULL, /* tp_members */
MD5_getseters, /* tp_getset */
};
/* The single module-level function: new() */
/*[clinic input]
_md5.md5
string: object(c_default="NULL") = b''
Return a new MD5 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
_md5_md5_impl(PyObject *module, PyObject *string)
/*[clinic end generated code: output=2cfd0f8c091b97e6 input=d12ef8f72d684f7b]*/
{
MD5object *new;
Py_buffer buf;
if (string)
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
if ((new = newMD5object()) == NULL) {
if (string)
PyBuffer_Release(&buf);
return NULL;
}
md5_init(&new->hash_state);
if (PyErr_Occurred()) {
Py_DECREF(new);
if (string)
PyBuffer_Release(&buf);
return NULL;
}
if (string) {
md5_process(&new->hash_state, buf.buf, buf.len);
PyBuffer_Release(&buf);
}
return (PyObject *)new;
}
/* List of functions exported by this module */
static struct PyMethodDef MD5_functions[] = {
_MD5_MD5_METHODDEF
{NULL, NULL} /* Sentinel */
};
/* Initialize this module. */
#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
static struct PyModuleDef _md5module = {
PyModuleDef_HEAD_INIT,
"_md5",
NULL,
-1,
MD5_functions,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit__md5(void)
{
PyObject *m;
Py_TYPE(&MD5type) = &PyType_Type;
if (PyType_Ready(&MD5type) < 0)
return NULL;
m = PyModule_Create(&_md5module);
if (m == NULL)
return NULL;
Py_INCREF((PyObject *)&MD5type);
PyModule_AddObject(m, "MD5Type", (PyObject *)&MD5type);
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__md5 = {
"_md5",
PyInit__md5,
};

View file

@ -41,6 +41,18 @@ PYTHON_PROVIDE("parser.st2tuple");
PYTHON_PROVIDE("parser.suite");
PYTHON_PROVIDE("parser.tuple2st");
asm(".ident\t\"\\n\\n\
parsermodule (Python license)\\n\
Copyright 1995-1996 by Virginia Polytechnic Institute & State\\n\
University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\\n\
Virginia, USA. Portions copyright 1991-1995 by Stichting Mathematisch\\n\
Centrum, Amsterdam, The Netherlands.\"");
static const char parser_copyright_string[] =
"Copyright 1995-1996 by Virginia Polytechnic Institute & State\n\
University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\n\
Virginia, USA. Portions copyright 1991-1995 by Stichting Mathematisch\n\
Centrum, Amsterdam, The Netherlands.";
/* parsermodule.c
*
* Copyright 1995-1996 by Fred L. Drake, Jr. and Virginia Polytechnic
@ -77,22 +89,11 @@ extern grammar _PyParser_Grammar; /* From graminit.c */
#define NOTE(x)
/* String constants used to initialize module attributes.
*
*/
static const char parser_copyright_string[] =
"Copyright 1995-1996 by Virginia Polytechnic Institute & State\n\
University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\n\
Virginia, USA. Portions copyright 1991-1995 by Stichting Mathematisch\n\
Centrum, Amsterdam, The Netherlands.";
PyDoc_STRVAR(parser_doc_string,
"This is an interface to Python's internal parser.");
static const char parser_version_string[] = "0.5";
typedef PyObject* (*SeqMaker) (Py_ssize_t length);
typedef int (*SeqInserter) (PyObject* sequence,
Py_ssize_t index,
@ -106,8 +107,6 @@ typedef int (*SeqInserter) (PyObject* sequence,
* new naming conventions. Added arguments to provide support for creating
* lists as well as tuples, and optionally including the line numbers.
*/
static PyObject*
node2tuple(node *n, /* node to convert */
SeqMaker mkseq, /* create sequence */
@ -116,31 +115,25 @@ node2tuple(node *n, /* node to convert */
int col_offset) /* include column offsets? */
{
PyObject *result = NULL, *w;
if (n == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
if (ISNONTERMINAL(TYPE(n))) {
int i;
result = mkseq(1 + NCH(n) + (TYPE(n) == encoding_decl));
if (result == NULL)
goto error;
w = PyLong_FromLong(TYPE(n));
if (w == NULL)
goto error;
(void) addelem(result, 0, w);
for (i = 0; i < NCH(n); i++) {
w = node2tuple(CHILD(n, i), mkseq, addelem, lineno, col_offset);
if (w == NULL)
goto error;
(void) addelem(result, i+1, w);
}
if (TYPE(n) == encoding_decl) {
w = PyUnicode_FromString(STR(n));
if (w == NULL)
@ -152,24 +145,20 @@ node2tuple(node *n, /* node to convert */
result = mkseq(2 + lineno + col_offset);
if (result == NULL)
goto error;
w = PyLong_FromLong(TYPE(n));
if (w == NULL)
goto error;
(void) addelem(result, 0, w);
w = PyUnicode_FromString(STR(n));
if (w == NULL)
goto error;
(void) addelem(result, 1, w);
if (lineno) {
w = PyLong_FromLong(n->n_lineno);
if (w == NULL)
goto error;
(void) addelem(result, 2, w);
}
if (col_offset) {
w = PyLong_FromLong(n->n_col_offset);
if (w == NULL)
@ -183,7 +172,6 @@ node2tuple(node *n, /* node to convert */
return ((PyObject*) NULL);
}
return result;
error:
Py_XDECREF(result);
return NULL;
@ -1171,8 +1159,6 @@ static PyMethodDef parser_functions[] = {
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef parsermodule = {
PyModuleDef_HEAD_INIT,
"parser",

View file

@ -19,9 +19,15 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/log/log.h"
#include "libc/nt/createfile.h"
#include "libc/nt/dll.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/sw.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/dlfcn.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/sysconf.h"
#include "libc/sock/sock.h"
#include "libc/stdio/stdio.h"
@ -41,6 +47,7 @@
#include "libc/sysv/consts/waitid.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "third_party/musl/passwd.h"
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/boolobject.h"
@ -64,11 +71,13 @@
#include "third_party/python/Include/structseq.h"
#include "third_party/python/Include/warnings.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/python/Modules/_multiprocessing/multiprocessing.h"
#include "third_party/python/Modules/posixmodule.h"
#include "third_party/python/pyconfig.h"
/* clang-format off */
PYTHON_PROVIDE("posix");
PYTHON_PROVIDE("posix._getfinalpathname");
/* POSIX module implementation */
@ -156,7 +165,7 @@ module os
/* defined in fileutils.c */
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
ULONG, struct _Py_stat_struct *);
ULONG, struct _Py_stat_struct *);
#endif
#ifdef MS_WINDOWS
@ -938,14 +947,12 @@ PyLong_FromPy_off_t(Py_off_t offset)
}
#ifdef MS_WINDOWS
static int
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
{
char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
_Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
DWORD n_bytes_returned;
if (0 == DeviceIoControl(
reparse_point_handle,
FSCTL_GET_REPARSE_POINT,
@ -954,13 +961,10 @@ win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
&n_bytes_returned,
NULL)) /* we're not using OVERLAPPED_IO */
return FALSE;
if (reparse_tag)
*reparse_tag = rdb->ReparseTag;
return TRUE;
}
#endif /* MS_WINDOWS */
static PyObject *
@ -972,7 +976,6 @@ convertenviron(void)
#else
char **e;
#endif
d = PyDict_New();
if (d == NULL)
return NULL;
@ -1051,7 +1054,6 @@ posix_error(void)
return PyErr_SetFromErrno(PyExc_OSError);
}
#ifdef MS_WINDOWS
static PyObject *
win32_error(const char* function, const char* filename)
{
@ -1081,8 +1083,6 @@ win32_error_object(const char* function, PyObject* filename)
return PyErr_SetFromWindowsErr(errno);
}
#endif /* MS_WINDOWS */
static PyObject *
posix_path_object_error(PyObject *path)
{
@ -1255,8 +1255,7 @@ get_target_path(HANDLE hdl, wchar_t **target_path)
/* We have a good handle to the target, use it to determine
the target path name (then we'll call lstat on it). */
buf_size = GetFinalPathNameByHandleW(hdl, 0, 0,
VOLUME_NAME_DOS);
buf_size = GetFinalPathNameByHandle(hdl, 0, 0, kNtVolumeNameDos);
if(!buf_size)
return FALSE;
@ -1423,43 +1422,43 @@ or st_flags, they are available as attributes only.\n\
See os.stat for more information.");
static PyStructSequence_Field stat_result_fields[] = {
{"st_mode", "protection bits"},
{"st_ino", "inode"},
{"st_dev", "device"},
{"st_nlink", "number of hard links"},
{"st_uid", "user ID of owner"},
{"st_gid", "group ID of owner"},
{"st_size", "total size, in bytes"},
{"st_mode", PyDoc_STR("protection bits")},
{"st_ino", PyDoc_STR("inode")},
{"st_dev", PyDoc_STR("device")},
{"st_nlink", PyDoc_STR("number of hard links")},
{"st_uid", PyDoc_STR("user ID of owner")},
{"st_gid", PyDoc_STR("group ID of owner")},
{"st_size", PyDoc_STR("total size, in bytes")},
/* The NULL is replaced with PyStructSequence_UnnamedField later. */
{NULL, "integer time of last access"},
{NULL, "integer time of last modification"},
{NULL, "integer time of last change"},
{"st_atime", "time of last access"},
{"st_mtime", "time of last modification"},
{"st_ctime", "time of last change"},
{"st_atime_ns", "time of last access in nanoseconds"},
{"st_mtime_ns", "time of last modification in nanoseconds"},
{"st_ctime_ns", "time of last change in nanoseconds"},
{NULL, PyDoc_STR("integer time of last access")},
{NULL, PyDoc_STR("integer time of last modification")},
{NULL, PyDoc_STR("integer time of last change")},
{"st_atime", PyDoc_STR("time of last access")},
{"st_mtime", PyDoc_STR("time of last modification")},
{"st_ctime", PyDoc_STR("time of last change")},
{"st_atime_ns", PyDoc_STR("time of last access in nanoseconds")},
{"st_mtime_ns", PyDoc_STR("time of last modification in nanoseconds")},
{"st_ctime_ns", PyDoc_STR("time of last change in nanoseconds")},
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
{"st_blksize", "blocksize for filesystem I/O"},
{"st_blksize", PyDoc_STR("blocksize for filesystem I/O")},
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
{"st_blocks", "number of blocks allocated"},
{"st_blocks", PyDoc_STR("number of blocks allocated")},
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
{"st_rdev", "device type (if inode device)"},
{"st_rdev", PyDoc_STR("device type (if inode device)")},
#endif
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
{"st_flags", "user defined flags for file"},
{"st_flags", PyDoc_STR("user defined flags for file")},
#endif
#ifdef HAVE_STRUCT_STAT_ST_GEN
{"st_gen", "generation number"},
{"st_gen", PyDoc_STR("generation number")},
#endif
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
{"st_birthtime", "time of creation"},
{"st_birthtime", PyDoc_STR("time of creation")},
#endif
#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
{"st_file_attributes", "Windows file attribute bits"},
{"st_file_attributes", PyDoc_STR("Windows file attribute bits")},
#endif
{0}
};
@ -1777,9 +1776,6 @@ _pystat_fromstructstat(STRUCT_STAT *st)
return v;
}
/* POSIX methods */
static PyObject *
posix_do_stat(const char *function_name, path_t *path,
int dir_fd, int follow_symlinks)
@ -3368,6 +3364,79 @@ os_listdir_impl(PyObject *module, path_t *path)
#endif
}
/*[clinic input]
os._getfinalpathname
path: unicode
/
A helper function for samepath on windows.
[clinic start generated code]*/
static PyObject *
os__getfinalpathname_impl(PyObject *module, PyObject *path)
/*[clinic end generated code: output=9bd78d0e52782e75 input=71d5e89334891bf4]*/
{
char *final8;
int64_t hFile;
size_t final8z;
PyObject *path_utf8;
char16_t *path_utf16;
char16_t buf[PATH_MAX], *target_path = buf;
int buf_size = Py_ARRAY_LENGTH(buf);
int result_length;
PyObject *result;
if (!(path_utf8 = PyUnicode_AsUTF8String(path))) return 0;
path_utf16 = gc(utf8toutf16(PyBytes_AS_STRING(path_utf8), PyBytes_GET_SIZE(path_utf8), 0));
Py_DECREF(path_utf8);
if (!path_utf16) return PyErr_NoMemory();
Py_BEGIN_ALLOW_THREADS
hFile = CreateFile(
path_utf16,
0, /* desired access */
0, /* share mode */
NULL, /* security attributes */
kNtOpenExisting,
/* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
kNtFileFlagBackupSemantics,
0);
Py_END_ALLOW_THREADS
if(hFile == kNtInvalidHandleValue)
return win32_error_object("CreateFile", path);
/* We have a good handle to the target, use it to determine the
target path name. */
while (1) {
Py_BEGIN_ALLOW_THREADS
result_length = GetFinalPathNameByHandle(hFile, target_path,
buf_size, kNtVolumeNameDos);
Py_END_ALLOW_THREADS
if (!result_length) {
result = win32_error_object("GetFinalPathNameByHandle", path);
goto cleanup;
}
if (result_length < buf_size) {
break;
}
char16_t *tmp;
tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
result_length * sizeof(*tmp));
if (!tmp) {
result = PyErr_NoMemory();
goto cleanup;
}
buf_size = result_length;
target_path = tmp;
}
final8 = gc(utf16toutf8(target_path, result_length, &final8z));
result = PyUnicode_FromStringAndSize(final8, final8z);
cleanup:
if (target_path != buf) {
PyMem_Free(target_path);
}
CloseHandle(hFile);
return result;
}
#ifdef MS_WINDOWS
/* A helper function for abspath on win32 */
/*[clinic input]
@ -3407,85 +3476,6 @@ os__getfullpathname_impl(PyObject *module, path_t *path)
return v;
}
/*[clinic input]
os._getfinalpathname
path: unicode
/
A helper function for samepath on windows.
[clinic start generated code]*/
static PyObject *
os__getfinalpathname_impl(PyObject *module, PyObject *path)
/*[clinic end generated code: output=9bd78d0e52782e75 input=71d5e89334891bf4]*/
{
HANDLE hFile;
wchar_t buf[MAXPATHLEN], *target_path = buf;
int buf_size = Py_ARRAY_LENGTH(buf);
int result_length;
PyObject *result;
const wchar_t *path_wchar;
path_wchar = _PyUnicode_AsUnicode(path);
if (path_wchar == NULL)
return NULL;
Py_BEGIN_ALLOW_THREADS
hFile = CreateFileW(
path_wchar,
0, /* desired access */
0, /* share mode */
NULL, /* security attributes */
OPEN_EXISTING,
/* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
Py_END_ALLOW_THREADS
if(hFile == INVALID_HANDLE_VALUE)
return win32_error_object("CreateFileW", path);
/* We have a good handle to the target, use it to determine the
target path name. */
while (1) {
Py_BEGIN_ALLOW_THREADS
result_length = GetFinalPathNameByHandleW(hFile, target_path,
buf_size, VOLUME_NAME_DOS);
Py_END_ALLOW_THREADS
if (!result_length) {
result = win32_error_object("GetFinalPathNameByHandleW", path);
goto cleanup;
}
if (result_length < buf_size) {
break;
}
wchar_t *tmp;
tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
result_length * sizeof(*tmp));
if (!tmp) {
result = PyErr_NoMemory();
goto cleanup;
}
buf_size = result_length;
target_path = tmp;
}
result = PyUnicode_FromWideChar(target_path, result_length);
cleanup:
if (target_path != buf) {
PyMem_Free(target_path);
}
CloseHandle(hFile);
return result;
}
/*[clinic input]
os._isdir
@ -3504,10 +3494,8 @@ os__isdir_impl(PyObject *module, path_t *path)
Py_BEGIN_ALLOW_THREADS
attributes = GetFileAttributesW(path->wide);
Py_END_ALLOW_THREADS
if (attributes == INVALID_FILE_ATTRIBUTES)
Py_RETURN_FALSE;
if (attributes & FILE_ATTRIBUTE_DIRECTORY)
Py_RETURN_TRUE;
else
@ -3515,6 +3503,8 @@ os__isdir_impl(PyObject *module, path_t *path)
}
#endif /* MS_WINDOWS */
/*[clinic input]
os._getvolumepathname
@ -3528,46 +3518,75 @@ os__getvolumepathname_impl(PyObject *module, PyObject *path)
/*[clinic end generated code: output=cbdcbd1059ceef4c input=7eacadc40acbda6b]*/
{
PyObject *result;
const wchar_t *path_wchar;
wchar_t *mountpath=NULL;
PyObject *path_utf8;
char16_t *path_utf16;
char16_t *mountpath;
char *mountpath8;
size_t buflen;
BOOL ret;
path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen);
if (path_wchar == NULL)
return NULL;
bool32 ret;
if (!(path_utf8 = PyUnicode_AsUTF8String(path))) return 0;
path_utf16 = gc(utf8toutf16(PyBytes_AS_STRING(path_utf8), PyBytes_GET_SIZE(path_utf8), &buflen));
Py_DECREF(path_utf8);
if (!path_utf16) return PyErr_NoMemory();
buflen += 1;
/* Volume path should be shorter than entire path */
buflen = Py_MAX(buflen, MAX_PATH);
buflen = Py_MAX(buflen, PATH_MAX);
if (buflen > DWORD_MAX) {
PyErr_SetString(PyExc_OverflowError, "path too long");
return NULL;
}
mountpath = PyMem_New(wchar_t, buflen);
if (mountpath == NULL)
if (!(mountpath = PyMem_New(char16_t, buflen)))
return PyErr_NoMemory();
Py_BEGIN_ALLOW_THREADS
ret = GetVolumePathNameW(path_wchar, mountpath,
Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
ret = GetVolumePathName(path_utf16, mountpath,
Py_SAFE_DOWNCAST(buflen, size_t, uint32_t));
Py_END_ALLOW_THREADS
if (!ret) {
if (ret) {
mountpath8 = gc(utf16toutf8(mountpath, -1, &buflen));
result = PyUnicode_FromStringAndSize(mountpath8, buflen);
} else {
result = win32_error_object("_getvolumepathname", path);
goto exit;
}
result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
exit:
PyMem_Free(mountpath);
return result;
}
#endif /* MS_WINDOWS */
/* static PyObject * */
/* os__getvolumepathname_impl(PyObject *module, PyObject *path) */
/* /\*[clinic end generated code: output=cbdcbd1059ceef4c input=7eacadc40acbda6b]*\/ */
/* { */
/* PyObject *result; */
/* const utf8_t *path_utf8; */
/* const wchar_t *path_wchar; */
/* char16_t *mountpath=NULL; */
/* size_t buflen; */
/* bool32 ret; */
/* path_wchar = PyUnicode_AsUTF8String(path, &buflen); */
/* if (path_wchar == NULL) */
/* return NULL; */
/* buflen += 1; */
/* /\* Volume path should be shorter than entire path *\/ */
/* buflen = Py_MAX(buflen, MAX_PATH); */
/* if (buflen > DWORD_MAX) { */
/* PyErr_SetString(PyExc_OverflowError, "path too long"); */
/* return NULL; */
/* } */
/* mountpath = PyMem_New(char16_t, buflen); */
/* if (mountpath == NULL) */
/* return PyErr_NoMemory(); */
/* Py_BEGIN_ALLOW_THREADS */
/* ret = GetVolumePathNameW(path_wchar, mountpath, */
/* Py_SAFE_DOWNCAST(buflen, size_t, uint32_t)); */
/* Py_END_ALLOW_THREADS */
/* if (!ret) { */
/* result = win32_error_object("_getvolumepathname", path); */
/* goto exit; */
/* } */
/* result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); */
/* exit: */
/* PyMem_Free(mountpath); */
/* return result; */
/* } */
/*[clinic input]
os.mkdir
@ -3922,45 +3941,6 @@ os_umask_impl(PyObject *module, int mask)
return PyLong_FromLong((long)i);
}
#ifdef MS_WINDOWS
/* override the default DeleteFileW behavior so that directory
symlinks can be removed with this function, the same as with
Unix symlinks */
BOOL WINAPI Py_DeleteFileW(const char16_t * lpFileName)
{
WIN32_FILE_ATTRIBUTE_DATA info;
WIN32_FIND_DATAW find_data;
HANDLE find_data_handle;
int is_directory = 0;
int is_link = 0;
if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
/* Get WIN32_FIND_DATA structure for the path to determine if
it is a symlink */
if(is_directory &&
info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
find_data_handle = FindFirstFileW(lpFileName, &find_data);
if(find_data_handle != INVALID_HANDLE_VALUE) {
/* IO_REPARSE_TAG_SYMLINK if it is a symlink and
IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
FindClose(find_data_handle);
}
}
}
if (is_directory && is_link)
return RemoveDirectoryW(lpFileName);
return DeleteFileW(lpFileName);
}
#endif /* MS_WINDOWS */
/*[clinic input]
os.unlink
@ -4025,13 +4005,12 @@ os_remove_impl(PyObject *module, path_t *path, int dir_fd)
return os_unlink_impl(module, path, dir_fd);
}
static PyStructSequence_Field uname_result_fields[] = {
{"sysname", "operating system name"},
{"nodename", "name of machine on network (implementation-defined)"},
{"release", "operating system release"},
{"version", "operating system version"},
{"machine", "hardware identifier"},
{"sysname", PyDoc_STR("operating system name")},
{"nodename", PyDoc_STR("name of machine on network (implementation-defined)")},
{"release", PyDoc_STR("operating system release")},
{"version", PyDoc_STR("operating system version")},
{"machine", PyDoc_STR("hardware identifier")},
{NULL}
};
@ -5170,7 +5149,7 @@ os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
PyDoc_VAR(os_sched_param__doc__);
static PyStructSequence_Field sched_param_fields[] = {
{"sched_priority", "the scheduling priority"},
{"sched_priority", PyDoc_STR("the scheduling priority")},
{0}
};
@ -5650,7 +5629,6 @@ os_forkpty_impl(PyObject *module)
}
#endif /* HAVE_FORKPTY */
#ifdef HAVE_GETEGID
/*[clinic input]
os.getegid
@ -6918,15 +6896,12 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
}
#endif /* HAVE_SYMLINK */
static PyStructSequence_Field times_result_fields[] = {
{"user", "user time"},
{"system", "system time"},
{"children_user", "user time of children"},
{"children_system", "system time of children"},
{"elapsed", "elapsed time since an arbitrary point in the past"},
{"user", PyDoc_STR("user time")},
{"system", PyDoc_STR("system time")},
{"children_user", PyDoc_STR("user time of children")},
{"children_system", PyDoc_STR("system time of children")},
{"elapsed", PyDoc_STR("elapsed time since an arbitrary point in the past")},
{NULL}
};
@ -8745,46 +8720,34 @@ os_WSTOPSIG_impl(PyObject *module, int status)
#define _SVID3
#endif
static PyObject*
static PyObject *
_pystatvfs_fromstructstatvfs(struct statvfs st) {
PyObject *v = PyStructSequence_New(&StatVFSResultType);
if (v == NULL)
return NULL;
#if !defined(HAVE_LARGEFILE_SUPPORT)
PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
#if !defined(HAVE_LARGEFILE_SUPPORT)
PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
#else
PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
PyStructSequence_SET_ITEM(v, 2,
PyLong_FromLongLong((long long) st.f_blocks));
PyStructSequence_SET_ITEM(v, 3,
PyLong_FromLongLong((long long) st.f_bfree));
PyStructSequence_SET_ITEM(v, 4,
PyLong_FromLongLong((long long) st.f_bavail));
PyStructSequence_SET_ITEM(v, 5,
PyLong_FromLongLong((long long) st.f_files));
PyStructSequence_SET_ITEM(v, 6,
PyLong_FromLongLong((long long) st.f_ffree));
PyStructSequence_SET_ITEM(v, 7,
PyLong_FromLongLong((long long) st.f_favail));
PyStructSequence_SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks));
PyStructSequence_SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree));
PyStructSequence_SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail));
PyStructSequence_SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files));
PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree));
PyStructSequence_SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_favail));
#endif
PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
#endif
if (PyErr_Occurred()) {
Py_DECREF(v);
return NULL;
}
return v;
}
@ -10461,8 +10424,8 @@ PyDoc_STRVAR(TerminalSize_docstring,
"A tuple of (columns, lines) for holding terminal window size");
static PyStructSequence_Field TerminalSize_fields[] = {
{"columns", "width of the terminal window in characters"},
{"lines", "height of the terminal window in characters"},
{"columns", PyDoc_STR("width of the terminal window in characters")},
{"lines", PyDoc_STR("height of the terminal window in characters")},
{NULL, NULL}
};
@ -10982,31 +10945,25 @@ DirEntry_fspath(DirEntry *self)
static PyMemberDef DirEntry_members[] = {
{"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
"the entry's base filename, relative to scandir() \"path\" argument"},
PyDoc_STR("the entry's base filename, relative to scandir() \"path\" argument")},
{"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
"the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
PyDoc_STR("the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)")},
{NULL}
};
static PyMethodDef DirEntry_methods[] = {
{"is_dir", (PyCFunction)DirEntry_is_dir, METH_VARARGS | METH_KEYWORDS,
"return True if the entry is a directory; cached per entry"
},
PyDoc_STR("is_dir($self)\n--\n\nreturn True if entry is a directory; cached per entry")},
{"is_file", (PyCFunction)DirEntry_is_file, METH_VARARGS | METH_KEYWORDS,
"return True if the entry is a file; cached per entry"
},
PyDoc_STR("is_file($self)\n--\n\nreturn True if the entry is a file; cached per entry")},
{"is_symlink", (PyCFunction)DirEntry_py_is_symlink, METH_NOARGS,
"return True if the entry is a symbolic link; cached per entry"
},
PyDoc_STR("is_symlink($self)\n--\n\nreturn True if the entry is a symbolic link; cached per entry")},
{"stat", (PyCFunction)DirEntry_stat, METH_VARARGS | METH_KEYWORDS,
"return stat_result object for the entry; cached per entry"
},
PyDoc_STR("is_stat($self)\n--\n\nreturn stat_result object for the entry; cached per entry")},
{"inode", (PyCFunction)DirEntry_inode, METH_NOARGS,
"return inode of the entry; cached per entry",
},
PyDoc_STR("inode($self)\n--\n\nreturn inode of the entry; cached per entry")},
{"__fspath__", (PyCFunction)DirEntry_fspath, METH_NOARGS,
"returns the path for the entry",
},
PyDoc_STR("__fspath__($self)\n--\n\nreturns the path for the entry")},
{NULL}
};
@ -11599,9 +11556,7 @@ dump buffer
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/
static PyMethodDef posix_methods[] = {
OS_STAT_METHODDEF
OS_ACCESS_METHODDEF
OS_TTYNAME_METHODDEF
@ -11844,6 +11799,8 @@ all_ins(PyObject *m)
if (O_NOFOLLOW_ANY && PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
if (O_NOATIME && PyModule_AddIntMacro(m, O_NOATIME)) return -1;
if (O_VERIFY && PyModule_AddIntMacro(m, O_VERIFY)) return -1;
if (IsWindows() && PyModule_AddIntConstant(m, "O_SHORT_LIVED", kNtFileAttributeTemporary)) return -1;
if (IsWindows() && PyModule_AddIntConstant(m, "O_TEMPORARY", kNtFileFlagDeleteOnClose)) return -1;
#ifdef O_BINARY
if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
#endif
@ -11856,12 +11813,6 @@ all_ins(PyObject *m)
#ifdef O_NOINHERIT
if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
#endif
#ifdef _O_SHORT_LIVED
if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
#endif
#ifdef O_TEMPORARY
if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
#endif
if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
@ -12012,13 +11963,10 @@ all_ins(PyObject *m)
if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
if (PyModule_AddIntMacro(m, GRND_NORDRND)) return -1;
if (PyModule_AddIntMacro(m, GRND_NOSYSTEM)) return -1;
return 0;
}
static struct PyModuleDef posixmodule = {
PyModuleDef_HEAD_INIT,
MODNAME,
@ -12031,133 +11979,100 @@ static struct PyModuleDef posixmodule = {
NULL
};
static const char * const have_functions[] = {
#ifdef HAVE_FACCESSAT
"HAVE_FACCESSAT",
#endif
#ifdef HAVE_FCHDIR
"HAVE_FCHDIR",
#endif
#ifdef HAVE_FCHMOD
"HAVE_FCHMOD",
#endif
#ifdef HAVE_FCHMODAT
"HAVE_FCHMODAT",
#endif
#ifdef HAVE_FCHOWN
"HAVE_FCHOWN",
#endif
#ifdef HAVE_FCHOWNAT
"HAVE_FCHOWNAT",
#endif
#ifdef HAVE_FEXECVE
"HAVE_FEXECVE",
#endif
#ifdef HAVE_FDOPENDIR
"HAVE_FDOPENDIR",
#endif
#ifdef HAVE_FPATHCONF
"HAVE_FPATHCONF",
#endif
#ifdef HAVE_FSTATAT
"HAVE_FSTATAT",
#endif
#ifdef HAVE_FSTATVFS
"HAVE_FSTATVFS",
#endif
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
"HAVE_FTRUNCATE",
#endif
#ifdef HAVE_FUTIMENS
"HAVE_FUTIMENS",
#endif
#ifdef HAVE_FUTIMES
"HAVE_FUTIMES",
#endif
#ifdef HAVE_FUTIMESAT
"HAVE_FUTIMESAT",
#endif
#ifdef HAVE_LINKAT
"HAVE_LINKAT",
#endif
#ifdef HAVE_LCHFLAGS
"HAVE_LCHFLAGS",
#endif
#ifdef HAVE_LCHMOD
"HAVE_LCHMOD",
#endif
#ifdef HAVE_LCHOWN
"HAVE_LCHOWN",
#endif
#ifdef HAVE_LSTAT
"HAVE_LSTAT",
#endif
#ifdef HAVE_LUTIMES
"HAVE_LUTIMES",
#endif
#ifdef HAVE_MKDIRAT
"HAVE_MKDIRAT",
#endif
#ifdef HAVE_MKFIFOAT
"HAVE_MKFIFOAT",
#endif
#ifdef HAVE_MKNODAT
"HAVE_MKNODAT",
#endif
#ifdef HAVE_OPENAT
"HAVE_OPENAT",
#endif
#ifdef HAVE_READLINKAT
"HAVE_READLINKAT",
#endif
#ifdef HAVE_RENAMEAT
"HAVE_RENAMEAT",
#endif
#ifdef HAVE_SYMLINKAT
"HAVE_SYMLINKAT",
#endif
#ifdef HAVE_UNLINKAT
"HAVE_UNLINKAT",
#endif
#ifdef HAVE_UTIMENSAT
"HAVE_UTIMENSAT",
#endif
#ifdef MS_WINDOWS
"MS_WINDOWS",
#endif
NULL
};

View file

@ -13,13 +13,5 @@ int _Py_Gid_Converter(PyObject *, void *);
#endif /* MS_WINDOWS */
#endif
#undef HAVE_SETGROUPS
#undef HAVE_FORKPTY
#undef HAVE_SCHED_SETPARAM
#undef HAVE_SCHED_SETSCHEDULER
#undef HAVE_FCHMODAT
#undef HAVE_LINKAT
#undef HAVE_READLINKAT
COSMOPOLITAN_C_END_
#endif /* !Py_POSIXMODULE_H */

View file

@ -33,13 +33,13 @@ module pwd
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=60f628ef356b97b6]*/
static PyStructSequence_Field struct_pwd_type_fields[] = {
{"pw_name", "user name"},
{"pw_passwd", "password"},
{"pw_uid", "user id"},
{"pw_gid", "group id"},
{"pw_gecos", "real name"},
{"pw_dir", "home directory"},
{"pw_shell", "shell program"},
{"pw_name", PyDoc_STR("user name")},
{"pw_passwd", PyDoc_STR("password")},
{"pw_uid", PyDoc_STR("user id")},
{"pw_gid", PyDoc_STR("group id")},
{"pw_gecos", PyDoc_STR("real name")},
{"pw_dir", PyDoc_STR("home directory")},
{"pw_shell", PyDoc_STR("shell program")},
{0}
};

View file

@ -70,22 +70,22 @@ PyDoc_STRVAR(struct_rusage__doc__,
"or via the attributes ru_utime, ru_stime, ru_maxrss, and so on.");
static PyStructSequence_Field struct_rusage_fields[] = {
{"ru_utime", "user time used"},
{"ru_stime", "system time used"},
{"ru_maxrss", "max. resident set size"},
{"ru_ixrss", "shared memory size"},
{"ru_idrss", "unshared data size"},
{"ru_isrss", "unshared stack size"},
{"ru_minflt", "page faults not requiring I/O"},
{"ru_majflt", "page faults requiring I/O"},
{"ru_nswap", "number of swap outs"},
{"ru_inblock", "block input operations"},
{"ru_oublock", "block output operations"},
{"ru_msgsnd", "IPC messages sent"},
{"ru_msgrcv", "IPC messages received"},
{"ru_nsignals", "signals received"},
{"ru_nvcsw", "voluntary context switches"},
{"ru_nivcsw", "involuntary context switches"},
{"ru_utime", PyDoc_STR("user time used")},
{"ru_stime", PyDoc_STR("system time used")},
{"ru_maxrss", PyDoc_STR("max. resident set size")},
{"ru_ixrss", PyDoc_STR("shared memory size")},
{"ru_idrss", PyDoc_STR("unshared data size")},
{"ru_isrss", PyDoc_STR("unshared stack size")},
{"ru_minflt", PyDoc_STR("page faults not requiring I/O")},
{"ru_majflt", PyDoc_STR("page faults requiring I/O")},
{"ru_nswap", PyDoc_STR("number of swap outs")},
{"ru_inblock", PyDoc_STR("block input operations")},
{"ru_oublock", PyDoc_STR("block output operations")},
{"ru_msgsnd", PyDoc_STR("IPC messages sent")},
{"ru_msgrcv", PyDoc_STR("IPC messages received")},
{"ru_nsignals", PyDoc_STR("signals received")},
{"ru_nvcsw", PyDoc_STR("voluntary context switches")},
{"ru_nivcsw", PyDoc_STR("involuntary context switches")},
{0}
};
@ -104,11 +104,9 @@ resource_getrusage(PyObject *self, PyObject *args)
{
int who;
struct rusage ru;
PyObject *result;
PyObject *r;
if (!PyArg_ParseTuple(args, "i:getrusage", &who))
return NULL;
if (getrusage(who, &ru) == -1) {
if (errno == EINVAL) {
PyErr_SetString(PyExc_ValueError,
@ -118,36 +116,30 @@ resource_getrusage(PyObject *self, PyObject *args)
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
result = PyStructSequence_New(&StructRUsageType);
if (!result)
r = PyStructSequence_New(&StructRUsageType);
if (!r)
return NULL;
PyStructSequence_SET_ITEM(result, 0,
PyFloat_FromDouble(doubletime(ru.ru_utime)));
PyStructSequence_SET_ITEM(result, 1,
PyFloat_FromDouble(doubletime(ru.ru_stime)));
PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss));
PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss));
PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss));
PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(ru.ru_isrss));
PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(ru.ru_minflt));
PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(ru.ru_majflt));
PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(ru.ru_nswap));
PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(ru.ru_inblock));
PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(ru.ru_oublock));
PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(ru.ru_msgsnd));
PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(ru.ru_msgrcv));
PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals));
PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw));
PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw));
PyStructSequence_SET_ITEM(r, 0, PyFloat_FromDouble(doubletime(ru.ru_utime)));
PyStructSequence_SET_ITEM(r, 1, PyFloat_FromDouble(doubletime(ru.ru_stime)));
PyStructSequence_SET_ITEM(r, 2, PyLong_FromLong(ru.ru_maxrss));
PyStructSequence_SET_ITEM(r, 3, PyLong_FromLong(ru.ru_ixrss));
PyStructSequence_SET_ITEM(r, 4, PyLong_FromLong(ru.ru_idrss));
PyStructSequence_SET_ITEM(r, 5, PyLong_FromLong(ru.ru_isrss));
PyStructSequence_SET_ITEM(r, 6, PyLong_FromLong(ru.ru_minflt));
PyStructSequence_SET_ITEM(r, 7, PyLong_FromLong(ru.ru_majflt));
PyStructSequence_SET_ITEM(r, 8, PyLong_FromLong(ru.ru_nswap));
PyStructSequence_SET_ITEM(r, 9, PyLong_FromLong(ru.ru_inblock));
PyStructSequence_SET_ITEM(r, 10, PyLong_FromLong(ru.ru_oublock));
PyStructSequence_SET_ITEM(r, 11, PyLong_FromLong(ru.ru_msgsnd));
PyStructSequence_SET_ITEM(r, 12, PyLong_FromLong(ru.ru_msgrcv));
PyStructSequence_SET_ITEM(r, 13, PyLong_FromLong(ru.ru_nsignals));
PyStructSequence_SET_ITEM(r, 14, PyLong_FromLong(ru.ru_nvcsw));
PyStructSequence_SET_ITEM(r, 15, PyLong_FromLong(ru.ru_nivcsw));
if (PyErr_Occurred()) {
Py_DECREF(result);
Py_DECREF(r);
return NULL;
}
return result;
return r;
}
static int
@ -158,7 +150,6 @@ py2rlimit(PyObject *limits, struct rlimit *rl_out)
if (!limits)
/* Here limits is a borrowed reference */
return -1;
if (PyTuple_GET_SIZE(limits) != 2) {
PyErr_SetString(PyExc_ValueError,
"expected a tuple of 2 integers");
@ -182,12 +173,10 @@ py2rlimit(PyObject *limits, struct rlimit *rl_out)
if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred())
goto error;
#endif
Py_DECREF(limits);
rl_out->rlim_cur = rl_out->rlim_cur & RLIM_INFINITY;
rl_out->rlim_max = rl_out->rlim_max & RLIM_INFINITY;
return 0;
error:
Py_DECREF(limits);
return -1;
@ -209,16 +198,13 @@ resource_getrlimit(PyObject *self, PyObject *args)
{
struct rlimit rl;
int resource;
if (!PyArg_ParseTuple(args, "i:getrlimit", &resource))
return NULL;
if (resource < 0 || resource >= RLIM_NLIMITS) {
PyErr_SetString(PyExc_ValueError,
"invalid resource specified");
return NULL;
}
if (getrlimit(resource, &rl) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
@ -232,20 +218,16 @@ resource_setrlimit(PyObject *self, PyObject *args)
struct rlimit rl;
int resource;
PyObject *limits;
if (!PyArg_ParseTuple(args, "iO:setrlimit", &resource, &limits))
return NULL;
if (resource < 0 || resource >= RLIM_NLIMITS) {
PyErr_SetString(PyExc_ValueError,
"invalid resource specified");
return NULL;
}
if (py2rlimit(limits, &rl) < 0) {
return NULL;
}
if (setrlimit(resource, &rl) == -1) {
if (errno == EINVAL)
PyErr_SetString(PyExc_ValueError,
@ -268,17 +250,14 @@ resource_prlimit(PyObject *self, PyObject *args)
int resource, retval;
pid_t pid;
PyObject *limits = NULL;
if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i|O:prlimit",
&pid, &resource, &limits))
return NULL;
if (resource < 0 || resource >= RLIM_NLIMITS) {
PyErr_SetString(PyExc_ValueError,
"invalid resource specified");
return NULL;
}
if (limits != NULL) {
if (py2rlimit(limits, &new_limit) < 0) {
return NULL;
@ -288,7 +267,6 @@ resource_prlimit(PyObject *self, PyObject *args)
else {
retval = prlimit(pid, resource, NULL, &old_limit);
}
if (retval == -1) {
if (errno == EINVAL) {
PyErr_SetString(PyExc_ValueError,
@ -317,11 +295,8 @@ resource_getpagesize(PyObject *self, PyObject *unused)
#endif
#endif
return Py_BuildValue("i", pagesize);
}
/* List of functions */
static struct PyMethodDef
resource_methods[] = {
{"getrusage", resource_getrusage, METH_VARARGS},
@ -334,10 +309,6 @@ resource_methods[] = {
{NULL, NULL} /* sentinel */
};
/* Module initialization */
static struct PyModuleDef resourcemodule = {
PyModuleDef_HEAD_INIT,
"resource",

View file

@ -1187,9 +1187,7 @@ static int select_have_broken_poll(void)
{
int poll_test;
int filedes[2];
struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 };
/* Create a file descriptor to make invalid */
if (pipe(filedes) < 0) {
return 1;

View file

@ -1,587 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "libc/assert.h"
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/bytesobject.h"
#include "third_party/python/Include/descrobject.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/longobject.h"
#include "third_party/python/Include/modsupport.h"
#include "third_party/python/Include/objimpl.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/pystrhex.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/python/Modules/hashlib.h"
/* clang-format off */
PYTHON_PROVIDE("_sha1");
PYTHON_PROVIDE("_sha1.SHA1Type");
PYTHON_PROVIDE("_sha1.sha1");
/* SHA1 module */
/* This module provides an interface to the SHA1 algorithm */
/* See below for information about the original code this module was
based upon. Additional work performed by:
Andrew Kuchling (amk@amk.ca)
Greg Stein (gstein@lyra.org)
Trevor Perrin (trevp@trevp.net)
Copyright (C) 2005-2007 Gregory P. Smith (greg@krypto.org)
Licensed to PSF under a Contributor Agreement.
*/
/* SHA1 objects */
/*[clinic input]
module _sha1
class SHA1Type "SHA1object *" "&PyType_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3dc9a20d1becb759]*/
/* Some useful types */
#if SIZEOF_INT == 4
typedef unsigned int SHA1_INT32; /* 32-bit integer */
typedef long long SHA1_INT64; /* 64-bit integer */
#else
/* not defined. compilation will die. */
#endif
/* The SHA1 block size and message digest sizes, in bytes */
#define SHA1_BLOCKSIZE 64
#define SHA1_DIGESTSIZE 20
/* The structure for storing SHA1 info */
struct sha1_state {
SHA1_INT64 length;
SHA1_INT32 state[5], curlen;
unsigned char buf[SHA1_BLOCKSIZE];
};
typedef struct {
PyObject_HEAD
struct sha1_state hash_state;
} SHA1object;
#include "third_party/python/Modules/clinic/sha1module.inc"
/* ------------------------------------------------------------------------
*
* This code for the SHA1 algorithm was noted as public domain. The
* original headers are pasted below.
*
* Several changes have been made to make it more compatible with the
* Python environment and desired interface.
*
*/
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
/* rotate the hard way (platform optimizations could be done) */
#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
/* Endian Neutral macros that work on all platforms */
#define STORE32H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
#define LOAD32H(x, y) \
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
((unsigned long)((y)[1] & 255)<<16) | \
((unsigned long)((y)[2] & 255)<<8) | \
((unsigned long)((y)[3] & 255)); }
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
/* SHA1 macros */
#define F0(x,y,z) (z ^ (x & (y ^ z)))
#define F1(x,y,z) (x ^ y ^ z)
#define F2(x,y,z) ((x & y) | (z & (x | y)))
#define F3(x,y,z) (x ^ y ^ z)
static void sha1_compress(struct sha1_state *sha1, unsigned char *buf)
{
SHA1_INT32 a,b,c,d,e,W[80],i;
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32H(W[i], buf + (4*i));
}
/* copy state */
a = sha1->state[0];
b = sha1->state[1];
c = sha1->state[2];
d = sha1->state[3];
e = sha1->state[4];
/* expand it */
for (i = 16; i < 80; i++) {
W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
}
/* compress */
/* round one */
#define FF_0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
#define FF_1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
#define FF_2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
#define FF_3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
for (i = 0; i < 20; ) {
FF_0(a,b,c,d,e,i++);
FF_0(e,a,b,c,d,i++);
FF_0(d,e,a,b,c,i++);
FF_0(c,d,e,a,b,i++);
FF_0(b,c,d,e,a,i++);
}
/* round two */
for (; i < 40; ) {
FF_1(a,b,c,d,e,i++);
FF_1(e,a,b,c,d,i++);
FF_1(d,e,a,b,c,i++);
FF_1(c,d,e,a,b,i++);
FF_1(b,c,d,e,a,i++);
}
/* round three */
for (; i < 60; ) {
FF_2(a,b,c,d,e,i++);
FF_2(e,a,b,c,d,i++);
FF_2(d,e,a,b,c,i++);
FF_2(c,d,e,a,b,i++);
FF_2(b,c,d,e,a,i++);
}
/* round four */
for (; i < 80; ) {
FF_3(a,b,c,d,e,i++);
FF_3(e,a,b,c,d,i++);
FF_3(d,e,a,b,c,i++);
FF_3(c,d,e,a,b,i++);
FF_3(b,c,d,e,a,i++);
}
#undef FF_0
#undef FF_1
#undef FF_2
#undef FF_3
/* store */
sha1->state[0] = sha1->state[0] + a;
sha1->state[1] = sha1->state[1] + b;
sha1->state[2] = sha1->state[2] + c;
sha1->state[3] = sha1->state[3] + d;
sha1->state[4] = sha1->state[4] + e;
}
/**
Initialize the hash state
@param sha1 The hash state you wish to initialize
*/
static void
sha1_init(struct sha1_state *sha1)
{
assert(sha1 != NULL);
sha1->state[0] = 0x67452301UL;
sha1->state[1] = 0xefcdab89UL;
sha1->state[2] = 0x98badcfeUL;
sha1->state[3] = 0x10325476UL;
sha1->state[4] = 0xc3d2e1f0UL;
sha1->curlen = 0;
sha1->length = 0;
}
/**
Process a block of memory though the hash
@param sha1 The hash state
@param in The data to hash
@param inlen The length of the data (octets)
*/
static void
sha1_process(struct sha1_state *sha1,
const unsigned char *in, Py_ssize_t inlen)
{
Py_ssize_t n;
assert(sha1 != NULL);
assert(in != NULL);
assert(sha1->curlen <= sizeof(sha1->buf));
while (inlen > 0) {
if (sha1->curlen == 0 && inlen >= SHA1_BLOCKSIZE) {
sha1_compress(sha1, (unsigned char *)in);
sha1->length += SHA1_BLOCKSIZE * 8;
in += SHA1_BLOCKSIZE;
inlen -= SHA1_BLOCKSIZE;
} else {
n = Py_MIN(inlen, (Py_ssize_t)(SHA1_BLOCKSIZE - sha1->curlen));
memcpy(sha1->buf + sha1->curlen, in, (size_t)n);
sha1->curlen += (SHA1_INT32)n;
in += n;
inlen -= n;
if (sha1->curlen == SHA1_BLOCKSIZE) {
sha1_compress(sha1, sha1->buf);
sha1->length += 8*SHA1_BLOCKSIZE;
sha1->curlen = 0;
}
}
}
}
/**
Terminate the hash to get the digest
@param sha1 The hash state
@param out [out] The destination of the hash (20 bytes)
*/
static void
sha1_done(struct sha1_state *sha1, unsigned char *out)
{
int i;
assert(sha1 != NULL);
assert(out != NULL);
assert(sha1->curlen < sizeof(sha1->buf));
/* increase the length of the message */
sha1->length += sha1->curlen * 8;
/* append the '1' bit */
sha1->buf[sha1->curlen++] = (unsigned char)0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (sha1->curlen > 56) {
while (sha1->curlen < 64) {
sha1->buf[sha1->curlen++] = (unsigned char)0;
}
sha1_compress(sha1, sha1->buf);
sha1->curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (sha1->curlen < 56) {
sha1->buf[sha1->curlen++] = (unsigned char)0;
}
/* store length */
STORE64H(sha1->length, sha1->buf+56);
sha1_compress(sha1, sha1->buf);
/* copy output */
for (i = 0; i < 5; i++) {
STORE32H(sha1->state[i], out+(4*i));
}
}
/* .Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */
/* .Revision: 1.10 $ */
/* .Date: 2007/05/12 14:25:28 $ */
/*
* End of copied SHA1 code.
*
* ------------------------------------------------------------------------
*/
static PyTypeObject SHA1type;
static SHA1object *
newSHA1object(void)
{
return (SHA1object *)PyObject_New(SHA1object, &SHA1type);
}
/* Internal methods for a hash object */
static void
SHA1_dealloc(PyObject *ptr)
{
PyObject_Del(ptr);
}
/* External methods for a hash object */
/*[clinic input]
SHA1Type.copy
Return a copy of the hash object.
[clinic start generated code]*/
static PyObject *
SHA1Type_copy_impl(SHA1object *self)
/*[clinic end generated code: output=b4e001264620f02a input=b7eae10df6f89b36]*/
{
SHA1object *newobj;
if ((newobj = newSHA1object()) == NULL)
return NULL;
newobj->hash_state = self->hash_state;
return (PyObject *)newobj;
}
/*[clinic input]
SHA1Type.digest
Return the digest value as a bytes object.
[clinic start generated code]*/
static PyObject *
SHA1Type_digest_impl(SHA1object *self)
/*[clinic end generated code: output=2f05302a7aa2b5cb input=13824b35407444bd]*/
{
unsigned char digest[SHA1_DIGESTSIZE];
struct sha1_state temp;
temp = self->hash_state;
sha1_done(&temp, digest);
return PyBytes_FromStringAndSize((const char *)digest, SHA1_DIGESTSIZE);
}
/*[clinic input]
SHA1Type.hexdigest
Return the digest value as a string of hexadecimal digits.
[clinic start generated code]*/
static PyObject *
SHA1Type_hexdigest_impl(SHA1object *self)
/*[clinic end generated code: output=4161fd71e68c6659 input=97691055c0c74ab0]*/
{
unsigned char digest[SHA1_DIGESTSIZE];
struct sha1_state temp;
/* Get the raw (binary) digest value */
temp = self->hash_state;
sha1_done(&temp, digest);
return _Py_strhex((const char *)digest, SHA1_DIGESTSIZE);
}
/*[clinic input]
SHA1Type.update
obj: object
/
Update this hash object's state with the provided string.
[clinic start generated code]*/
static PyObject *
SHA1Type_update(SHA1object *self, PyObject *obj)
/*[clinic end generated code: output=d9902f0e5015e9ae input=aad8e07812edbba3]*/
{
Py_buffer buf;
GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
sha1_process(&self->hash_state, buf.buf, buf.len);
PyBuffer_Release(&buf);
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef SHA1_methods[] = {
SHA1TYPE_COPY_METHODDEF
SHA1TYPE_DIGEST_METHODDEF
SHA1TYPE_HEXDIGEST_METHODDEF
SHA1TYPE_UPDATE_METHODDEF
{NULL, NULL} /* sentinel */
};
static PyObject *
SHA1_get_block_size(PyObject *self, void *closure)
{
return PyLong_FromLong(SHA1_BLOCKSIZE);
}
static PyObject *
SHA1_get_name(PyObject *self, void *closure)
{
return PyUnicode_FromStringAndSize("sha1", 4);
}
static PyObject *
sha1_get_digest_size(PyObject *self, void *closure)
{
return PyLong_FromLong(SHA1_DIGESTSIZE);
}
static PyGetSetDef SHA1_getseters[] = {
{"block_size",
(getter)SHA1_get_block_size, NULL,
NULL,
NULL},
{"name",
(getter)SHA1_get_name, NULL,
NULL,
NULL},
{"digest_size",
(getter)sha1_get_digest_size, NULL,
NULL,
NULL},
{NULL} /* Sentinel */
};
static PyTypeObject SHA1type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_sha1.sha1", /*tp_name*/
sizeof(SHA1object), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
SHA1_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
SHA1_methods, /* tp_methods */
NULL, /* tp_members */
SHA1_getseters, /* tp_getset */
};
/* The single module-level function: new() */
/*[clinic input]
_sha1.sha1
string: object(c_default="NULL") = b''
Return a new SHA1 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
_sha1_sha1_impl(PyObject *module, PyObject *string)
/*[clinic end generated code: output=e5982830d1dece51 input=27ea54281d995ec2]*/
{
SHA1object *new;
Py_buffer buf;
if (string)
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
if ((new = newSHA1object()) == NULL) {
if (string)
PyBuffer_Release(&buf);
return NULL;
}
sha1_init(&new->hash_state);
if (PyErr_Occurred()) {
Py_DECREF(new);
if (string)
PyBuffer_Release(&buf);
return NULL;
}
if (string) {
sha1_process(&new->hash_state, buf.buf, buf.len);
PyBuffer_Release(&buf);
}
return (PyObject *)new;
}
/* List of functions exported by this module */
static struct PyMethodDef SHA1_functions[] = {
_SHA1_SHA1_METHODDEF
{NULL, NULL} /* Sentinel */
};
/* Initialize this module. */
#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
static struct PyModuleDef _sha1module = {
PyModuleDef_HEAD_INIT,
"_sha1",
NULL,
-1,
SHA1_functions,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit__sha1(void)
{
PyObject *m;
Py_TYPE(&SHA1type) = &PyType_Type;
if (PyType_Ready(&SHA1type) < 0)
return NULL;
m = PyModule_Create(&_sha1module);
if (m == NULL)
return NULL;
Py_INCREF((PyObject *)&SHA1type);
PyModule_AddObject(m, "SHA1Type", (PyObject *)&SHA1type);
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__sha1 = {
"_sha1",
PyInit__sha1,
};

View file

@ -1,752 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/bytesobject.h"
#include "third_party/python/Include/descrobject.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/longobject.h"
#include "third_party/python/Include/modsupport.h"
#include "third_party/python/Include/objimpl.h"
#include "third_party/python/Include/pyerrors.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/pystrhex.h"
#include "third_party/python/Include/structmember.h"
#include "third_party/python/Include/unicodeobject.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/python/Modules/hashlib.h"
/* clang-format off */
PYTHON_PROVIDE("_sha256");
PYTHON_PROVIDE("_sha256.SHA224Type");
PYTHON_PROVIDE("_sha256.SHA256Type");
PYTHON_PROVIDE("_sha256.sha224");
PYTHON_PROVIDE("_sha256.sha256");
/* This module provides an interface to NIST's SHA-256 and SHA-224 Algorithms */
/* See below for information about the original code this module was
based upon. Additional work performed by:
Andrew Kuchling (amk@amk.ca)
Greg Stein (gstein@lyra.org)
Trevor Perrin (trevp@trevp.net)
Copyright (C) 2005-2007 Gregory P. Smith (greg@krypto.org)
Licensed to PSF under a Contributor Agreement.
*/
/*[clinic input]
module _sha256
class SHA256Type "SHAobject *" "&PyType_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=71a39174d4f0a744]*/
/* Some useful types */
typedef unsigned char SHA_BYTE;
#if SIZEOF_INT == 4
typedef unsigned int SHA_INT32; /* 32-bit integer */
#else
/* not defined. compilation will die. */
#endif
/* The SHA block size and message digest sizes, in bytes */
#define SHA_BLOCKSIZE 64
#define SHA_DIGESTSIZE 32
/* The structure for storing SHA info */
typedef struct {
PyObject_HEAD
SHA_INT32 digest[8]; /* Message digest */
SHA_INT32 count_lo, count_hi; /* 64-bit bit count */
SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
int local; /* unprocessed amount in data */
int digestsize;
} SHAobject;
#include "third_party/python/Modules/clinic/sha256module.inc"
/* When run on a little-endian CPU we need to perform byte reversal on an
array of longwords. */
#if PY_LITTLE_ENDIAN
static void longReverse(SHA_INT32 *buffer, int byteCount)
{
SHA_INT32 value;
byteCount /= sizeof(*buffer);
while (byteCount--) {
value = *buffer;
value = ( ( value & 0xFF00FF00L ) >> 8 ) | \
( ( value & 0x00FF00FFL ) << 8 );
*buffer++ = ( value << 16 ) | ( value >> 16 );
}
}
#endif
static void SHAcopy(SHAobject *src, SHAobject *dest)
{
dest->local = src->local;
dest->digestsize = src->digestsize;
dest->count_lo = src->count_lo;
dest->count_hi = src->count_hi;
memcpy(dest->digest, src->digest, sizeof(src->digest));
memcpy(dest->data, src->data, sizeof(src->data));
}
/* ------------------------------------------------------------------------
*
* This code for the SHA-256 algorithm was noted as public domain. The
* original headers are pasted below.
*
* Several changes have been made to make it more compatible with the
* Python environment and desired interface.
*
*/
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtom.org
*/
/* SHA256 by Tom St Denis */
/* Various logical functions */
#define ROR(x, y)\
( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \
((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
#define Maj(x,y,z) (((x | y) & z) | (x & y))
#define S(x, n) ROR((x),(n))
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
static void
sha_transform(SHAobject *sha_info)
{
int i;
SHA_INT32 S[8], W[64], t0, t1;
memcpy(W, sha_info->data, sizeof(sha_info->data));
#if PY_LITTLE_ENDIAN
longReverse(W, (int)sizeof(sha_info->data));
#endif
for (i = 16; i < 64; ++i) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
for (i = 0; i < 8; ++i) {
S[i] = sha_info->digest[i];
}
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i,ki) \
t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
#undef RND
/* feedback */
for (i = 0; i < 8; i++) {
sha_info->digest[i] = sha_info->digest[i] + S[i];
}
}
/* initialize the SHA digest */
static void
sha_init(SHAobject *sha_info)
{
sha_info->digest[0] = 0x6A09E667L;
sha_info->digest[1] = 0xBB67AE85L;
sha_info->digest[2] = 0x3C6EF372L;
sha_info->digest[3] = 0xA54FF53AL;
sha_info->digest[4] = 0x510E527FL;
sha_info->digest[5] = 0x9B05688CL;
sha_info->digest[6] = 0x1F83D9ABL;
sha_info->digest[7] = 0x5BE0CD19L;
sha_info->count_lo = 0L;
sha_info->count_hi = 0L;
sha_info->local = 0;
sha_info->digestsize = 32;
}
static void
sha224_init(SHAobject *sha_info)
{
sha_info->digest[0] = 0xc1059ed8L;
sha_info->digest[1] = 0x367cd507L;
sha_info->digest[2] = 0x3070dd17L;
sha_info->digest[3] = 0xf70e5939L;
sha_info->digest[4] = 0xffc00b31L;
sha_info->digest[5] = 0x68581511L;
sha_info->digest[6] = 0x64f98fa7L;
sha_info->digest[7] = 0xbefa4fa4L;
sha_info->count_lo = 0L;
sha_info->count_hi = 0L;
sha_info->local = 0;
sha_info->digestsize = 28;
}
/* update the SHA digest */
static void
sha_update(SHAobject *sha_info, SHA_BYTE *buffer, Py_ssize_t count)
{
Py_ssize_t i;
SHA_INT32 clo;
clo = sha_info->count_lo + ((SHA_INT32) count << 3);
if (clo < sha_info->count_lo) {
++sha_info->count_hi;
}
sha_info->count_lo = clo;
sha_info->count_hi += (SHA_INT32) count >> 29;
if (sha_info->local) {
i = SHA_BLOCKSIZE - sha_info->local;
if (i > count) {
i = count;
}
memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
count -= i;
buffer += i;
sha_info->local += (int)i;
if (sha_info->local == SHA_BLOCKSIZE) {
sha_transform(sha_info);
}
else {
return;
}
}
while (count >= SHA_BLOCKSIZE) {
memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
buffer += SHA_BLOCKSIZE;
count -= SHA_BLOCKSIZE;
sha_transform(sha_info);
}
memcpy(sha_info->data, buffer, count);
sha_info->local = (int)count;
}
/* finish computing the SHA digest */
static void
sha_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info)
{
int count;
SHA_INT32 lo_bit_count, hi_bit_count;
lo_bit_count = sha_info->count_lo;
hi_bit_count = sha_info->count_hi;
count = (int) ((lo_bit_count >> 3) & 0x3f);
((SHA_BYTE *) sha_info->data)[count++] = 0x80;
if (count > SHA_BLOCKSIZE - 8) {
bzero(((SHA_BYTE *) sha_info->data) + count, SHA_BLOCKSIZE - count);
sha_transform(sha_info);
bzero((SHA_BYTE *) sha_info->data, SHA_BLOCKSIZE - 8);
}
else {
bzero(((SHA_BYTE *)sha_info->data) + count, SHA_BLOCKSIZE - 8 - count);
}
/* GJS: note that we add the hi/lo in big-endian. sha_transform will
swap these values into host-order. */
sha_info->data[56] = (hi_bit_count >> 24) & 0xff;
sha_info->data[57] = (hi_bit_count >> 16) & 0xff;
sha_info->data[58] = (hi_bit_count >> 8) & 0xff;
sha_info->data[59] = (hi_bit_count >> 0) & 0xff;
sha_info->data[60] = (lo_bit_count >> 24) & 0xff;
sha_info->data[61] = (lo_bit_count >> 16) & 0xff;
sha_info->data[62] = (lo_bit_count >> 8) & 0xff;
sha_info->data[63] = (lo_bit_count >> 0) & 0xff;
sha_transform(sha_info);
digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
digest[20] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff);
digest[21] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff);
digest[22] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff);
digest[23] = (unsigned char) ((sha_info->digest[5] ) & 0xff);
digest[24] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff);
digest[25] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff);
digest[26] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff);
digest[27] = (unsigned char) ((sha_info->digest[6] ) & 0xff);
digest[28] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff);
digest[29] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff);
digest[30] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff);
digest[31] = (unsigned char) ((sha_info->digest[7] ) & 0xff);
}
/*
* End of copied SHA code.
*
* ------------------------------------------------------------------------
*/
static PyTypeObject SHA224type;
static PyTypeObject SHA256type;
static SHAobject *
newSHA224object(void)
{
return (SHAobject *)PyObject_New(SHAobject, &SHA224type);
}
static SHAobject *
newSHA256object(void)
{
return (SHAobject *)PyObject_New(SHAobject, &SHA256type);
}
/* Internal methods for a hash object */
static void
SHA_dealloc(PyObject *ptr)
{
PyObject_Del(ptr);
}
/* External methods for a hash object */
/*[clinic input]
SHA256Type.copy
Return a copy of the hash object.
[clinic start generated code]*/
static PyObject *
SHA256Type_copy_impl(SHAobject *self)
/*[clinic end generated code: output=1a8bbd66a0c9c168 input=f58840a618d4f2a7]*/
{
SHAobject *newobj;
if (Py_TYPE(self) == &SHA256type) {
if ( (newobj = newSHA256object())==NULL)
return NULL;
} else {
if ( (newobj = newSHA224object())==NULL)
return NULL;
}
SHAcopy(self, newobj);
return (PyObject *)newobj;
}
/*[clinic input]
SHA256Type.digest
Return the digest value as a bytes object.
[clinic start generated code]*/
static PyObject *
SHA256Type_digest_impl(SHAobject *self)
/*[clinic end generated code: output=46616a5e909fbc3d input=f1f4cfea5cbde35c]*/
{
unsigned char digest[SHA_DIGESTSIZE];
SHAobject temp;
SHAcopy(self, &temp);
sha_final(digest, &temp);
return PyBytes_FromStringAndSize((const char *)digest, self->digestsize);
}
/*[clinic input]
SHA256Type.hexdigest
Return the digest value as a string of hexadecimal digits.
[clinic start generated code]*/
static PyObject *
SHA256Type_hexdigest_impl(SHAobject *self)
/*[clinic end generated code: output=725f8a7041ae97f3 input=0cc4c714693010d1]*/
{
unsigned char digest[SHA_DIGESTSIZE];
SHAobject temp;
/* Get the raw (binary) digest value */
SHAcopy(self, &temp);
sha_final(digest, &temp);
return _Py_strhex((const char *)digest, self->digestsize);
}
/*[clinic input]
SHA256Type.update
obj: object
/
Update this hash object's state with the provided string.
[clinic start generated code]*/
static PyObject *
SHA256Type_update(SHAobject *self, PyObject *obj)
/*[clinic end generated code: output=0967fb2860c66af7 input=b2d449d5b30f0f5a]*/
{
Py_buffer buf;
GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
sha_update(self, buf.buf, buf.len);
PyBuffer_Release(&buf);
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef SHA_methods[] = {
SHA256TYPE_COPY_METHODDEF
SHA256TYPE_DIGEST_METHODDEF
SHA256TYPE_HEXDIGEST_METHODDEF
SHA256TYPE_UPDATE_METHODDEF
{NULL, NULL} /* sentinel */
};
static PyObject *
SHA256_get_block_size(PyObject *self, void *closure)
{
return PyLong_FromLong(SHA_BLOCKSIZE);
}
static PyObject *
SHA256_get_name(PyObject *self, void *closure)
{
if (((SHAobject *)self)->digestsize == 32)
return PyUnicode_FromStringAndSize("sha256", 6);
else
return PyUnicode_FromStringAndSize("sha224", 6);
}
static PyGetSetDef SHA_getseters[] = {
{"block_size",
(getter)SHA256_get_block_size, NULL,
NULL,
NULL},
{"name",
(getter)SHA256_get_name, NULL,
NULL,
NULL},
{NULL} /* Sentinel */
};
static PyMemberDef SHA_members[] = {
{"digest_size", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
{NULL} /* Sentinel */
};
static PyTypeObject SHA224type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_sha256.sha224", /*tp_name*/
sizeof(SHAobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
SHA_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
SHA_methods, /* tp_methods */
SHA_members, /* tp_members */
SHA_getseters, /* tp_getset */
};
static PyTypeObject SHA256type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_sha256.sha256", /*tp_name*/
sizeof(SHAobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
SHA_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
SHA_methods, /* tp_methods */
SHA_members, /* tp_members */
SHA_getseters, /* tp_getset */
};
/* The single module-level function: new() */
/*[clinic input]
_sha256.sha256
string: object(c_default="NULL") = b''
Return a new SHA-256 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
_sha256_sha256_impl(PyObject *module, PyObject *string)
/*[clinic end generated code: output=fa644436dcea5c31 input=09cce3fb855056b2]*/
{
SHAobject *new;
Py_buffer buf;
if (string)
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
if ((new = newSHA256object()) == NULL) {
if (string)
PyBuffer_Release(&buf);
return NULL;
}
sha_init(new);
if (PyErr_Occurred()) {
Py_DECREF(new);
if (string)
PyBuffer_Release(&buf);
return NULL;
}
if (string) {
sha_update(new, buf.buf, buf.len);
PyBuffer_Release(&buf);
}
return (PyObject *)new;
}
/*[clinic input]
_sha256.sha224
string: object(c_default="NULL") = b''
Return a new SHA-224 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
_sha256_sha224_impl(PyObject *module, PyObject *string)
/*[clinic end generated code: output=21e3ba22c3404f93 input=27a04ba24c353a73]*/
{
SHAobject *new;
Py_buffer buf;
if (string)
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
if ((new = newSHA224object()) == NULL) {
if (string)
PyBuffer_Release(&buf);
return NULL;
}
sha224_init(new);
if (PyErr_Occurred()) {
Py_DECREF(new);
if (string)
PyBuffer_Release(&buf);
return NULL;
}
if (string) {
sha_update(new, buf.buf, buf.len);
PyBuffer_Release(&buf);
}
return (PyObject *)new;
}
/* List of functions exported by this module */
static struct PyMethodDef SHA_functions[] = {
_SHA256_SHA256_METHODDEF
_SHA256_SHA224_METHODDEF
{NULL, NULL} /* Sentinel */
};
/* Initialize this module. */
#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
static struct PyModuleDef _sha256module = {
PyModuleDef_HEAD_INIT,
"_sha256",
NULL,
-1,
SHA_functions,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit__sha256(void)
{
PyObject *m;
Py_TYPE(&SHA224type) = &PyType_Type;
if (PyType_Ready(&SHA224type) < 0)
return NULL;
Py_TYPE(&SHA256type) = &PyType_Type;
if (PyType_Ready(&SHA256type) < 0)
return NULL;
m = PyModule_Create(&_sha256module);
if (m == NULL)
return NULL;
Py_INCREF((PyObject *)&SHA224type);
PyModule_AddObject(m, "SHA224Type", (PyObject *)&SHA224type);
Py_INCREF((PyObject *)&SHA256type);
PyModule_AddObject(m, "SHA256Type", (PyObject *)&SHA256type);
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__sha256 = {
"_sha256",
PyInit__sha256,
};

View file

@ -1,826 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/bytesobject.h"
#include "third_party/python/Include/descrobject.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/longobject.h"
#include "third_party/python/Include/modsupport.h"
#include "third_party/python/Include/object.h"
#include "third_party/python/Include/objimpl.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/pystrhex.h"
#include "third_party/python/Include/structmember.h"
#include "third_party/python/Include/yoink.h"
#include "third_party/python/Modules/hashlib.h"
/* clang-format off */
PYTHON_PROVIDE("_sha512");
PYTHON_PROVIDE("_sha512.SHA384Type");
PYTHON_PROVIDE("_sha512.SHA512Type");
PYTHON_PROVIDE("_sha512.sha384");
PYTHON_PROVIDE("_sha512.sha512");
/* This module provides an interface to NIST's SHA-512 and SHA-384 Algorithms */
/* See below for information about the original code this module was
based upon. Additional work performed by:
Andrew Kuchling (amk@amk.ca)
Greg Stein (gstein@lyra.org)
Trevor Perrin (trevp@trevp.net)
Copyright (C) 2005-2007 Gregory P. Smith (greg@krypto.org)
Licensed to PSF under a Contributor Agreement.
*/
/* SHA objects */
/*[clinic input]
module _sha512
class SHA512Type "SHAobject *" "&PyType_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81a3ccde92bcfe8d]*/
/* Some useful types */
typedef unsigned char SHA_BYTE;
#if SIZEOF_INT == 4
typedef unsigned int SHA_INT32; /* 32-bit integer */
typedef unsigned long long SHA_INT64; /* 64-bit integer */
#else
/* not defined. compilation will die. */
#endif
/* The SHA block size and message digest sizes, in bytes */
#define SHA_BLOCKSIZE 128
#define SHA_DIGESTSIZE 64
/* The structure for storing SHA info */
typedef struct {
PyObject_HEAD
SHA_INT64 digest[8]; /* Message digest */
SHA_INT32 count_lo, count_hi; /* 64-bit bit count */
SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
int local; /* unprocessed amount in data */
int digestsize;
} SHAobject;
#include "third_party/python/Modules/clinic/sha512module.inc"
/* When run on a little-endian CPU we need to perform byte reversal on an
array of longwords. */
#if PY_LITTLE_ENDIAN
static void longReverse(SHA_INT64 *buffer, int byteCount)
{
SHA_INT64 value;
byteCount /= sizeof(*buffer);
while (byteCount--) {
value = *buffer;
((unsigned char*)buffer)[0] = (unsigned char)(value >> 56) & 0xff;
((unsigned char*)buffer)[1] = (unsigned char)(value >> 48) & 0xff;
((unsigned char*)buffer)[2] = (unsigned char)(value >> 40) & 0xff;
((unsigned char*)buffer)[3] = (unsigned char)(value >> 32) & 0xff;
((unsigned char*)buffer)[4] = (unsigned char)(value >> 24) & 0xff;
((unsigned char*)buffer)[5] = (unsigned char)(value >> 16) & 0xff;
((unsigned char*)buffer)[6] = (unsigned char)(value >> 8) & 0xff;
((unsigned char*)buffer)[7] = (unsigned char)(value ) & 0xff;
buffer++;
}
}
#endif
static void SHAcopy(SHAobject *src, SHAobject *dest)
{
dest->local = src->local;
dest->digestsize = src->digestsize;
dest->count_lo = src->count_lo;
dest->count_hi = src->count_hi;
memcpy(dest->digest, src->digest, sizeof(src->digest));
memcpy(dest->data, src->data, sizeof(src->data));
}
/* ------------------------------------------------------------------------
*
* This code for the SHA-512 algorithm was noted as public domain. The
* original headers are pasted below.
*
* Several changes have been made to make it more compatible with the
* Python environment and desired interface.
*
*/
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtom.org
*/
/* SHA512 by Tom St Denis */
/* Various logical functions */
#define ROR64(x, y) \
( ((((x) & 0xFFFFFFFFFFFFFFFFULL)>>((unsigned long long)(y) & 63)) | \
((x)<<((unsigned long long)(64-((y) & 63))))) & 0xFFFFFFFFFFFFFFFFULL)
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
#define Maj(x,y,z) (((x | y) & z) | (x & y))
#define S(x, n) ROR64((x),(n))
#define R(x, n) (((x) & 0xFFFFFFFFFFFFFFFFULL) >> ((unsigned long long)n))
#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
static void
sha512_transform(SHAobject *sha_info)
{
int i;
SHA_INT64 S[8], W[80], t0, t1;
memcpy(W, sha_info->data, sizeof(sha_info->data));
#if PY_LITTLE_ENDIAN
longReverse(W, (int)sizeof(sha_info->data));
#endif
for (i = 16; i < 80; ++i) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
}
for (i = 0; i < 8; ++i) {
S[i] = sha_info->digest[i];
}
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i,ki) \
t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98d728ae22ULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x7137449123ef65cdULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcfec4d3b2fULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba58189dbbcULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25bf348b538ULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1b605d019ULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4af194f9bULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5da6d8118ULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98a3030242ULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b0145706fbeULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be4ee4b28cULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3d5ffb4e2ULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74f27b896fULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe3b1696b1ULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a725c71235ULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174cf692694ULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c19ef14ad2ULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786384f25e3ULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc68b8cd5b5ULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc77ac9c65ULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f592b0275ULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa6ea6e483ULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dcbd41fbd4ULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da831153b5ULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152ee66dfabULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d2db43210ULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c898fb213fULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7beef0ee4ULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf33da88fc2ULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147930aa725ULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351e003826fULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x142929670a0e6e70ULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a8546d22ffcULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b21385c26c926ULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc5ac42aedULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d139d95b3dfULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a73548baf63deULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb3c77b2a8ULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e47edaee6ULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c851482353bULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a14cf10364ULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664bbc423001ULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70d0f89791ULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a30654be30ULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819d6ef5218ULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd69906245565a910ULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e35855771202aULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa07032bbd1b8ULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116b8d2d0c8ULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c085141ab53ULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774cdf8eeb99ULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5e19b48a8ULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3c5c95a63ULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4ae3418acbULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f7763e373ULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3d6b2b8a3ULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee5defb2fcULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f43172f60ULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814a1f0ab72ULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc702081a6439ecULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa23631e28ULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506cebde82bde9ULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7b2c67915ULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2e372532bULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],64,0xca273eceea26619cULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],65,0xd186b8c721c0c207ULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],66,0xeada7dd6cde0eb1eULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],67,0xf57d4f7fee6ed178ULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],68,0x06f067aa72176fbaULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],69,0x0a637dc5a2c898a6ULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],70,0x113f9804bef90daeULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],71,0x1b710b35131c471bULL);
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],72,0x28db77f523047d84ULL);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],73,0x32caab7b40c72493ULL);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],74,0x3c9ebe0a15c9bebcULL);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],75,0x431d67c49c100d4cULL);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],76,0x4cc5d4becb3e42b6ULL);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],77,0x597f299cfc657e2aULL);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],78,0x5fcb6fab3ad6faecULL);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],79,0x6c44198c4a475817ULL);
#undef RND
/* feedback */
for (i = 0; i < 8; i++) {
sha_info->digest[i] = sha_info->digest[i] + S[i];
}
}
/* initialize the SHA digest */
static void
sha512_init(SHAobject *sha_info)
{
sha_info->digest[0] = Py_ULL(0x6a09e667f3bcc908);
sha_info->digest[1] = Py_ULL(0xbb67ae8584caa73b);
sha_info->digest[2] = Py_ULL(0x3c6ef372fe94f82b);
sha_info->digest[3] = Py_ULL(0xa54ff53a5f1d36f1);
sha_info->digest[4] = Py_ULL(0x510e527fade682d1);
sha_info->digest[5] = Py_ULL(0x9b05688c2b3e6c1f);
sha_info->digest[6] = Py_ULL(0x1f83d9abfb41bd6b);
sha_info->digest[7] = Py_ULL(0x5be0cd19137e2179);
sha_info->count_lo = 0L;
sha_info->count_hi = 0L;
sha_info->local = 0;
sha_info->digestsize = 64;
}
static void
sha384_init(SHAobject *sha_info)
{
sha_info->digest[0] = Py_ULL(0xcbbb9d5dc1059ed8);
sha_info->digest[1] = Py_ULL(0x629a292a367cd507);
sha_info->digest[2] = Py_ULL(0x9159015a3070dd17);
sha_info->digest[3] = Py_ULL(0x152fecd8f70e5939);
sha_info->digest[4] = Py_ULL(0x67332667ffc00b31);
sha_info->digest[5] = Py_ULL(0x8eb44a8768581511);
sha_info->digest[6] = Py_ULL(0xdb0c2e0d64f98fa7);
sha_info->digest[7] = Py_ULL(0x47b5481dbefa4fa4);
sha_info->count_lo = 0L;
sha_info->count_hi = 0L;
sha_info->local = 0;
sha_info->digestsize = 48;
}
/* update the SHA digest */
static void
sha512_update(SHAobject *sha_info, SHA_BYTE *buffer, Py_ssize_t count)
{
Py_ssize_t i;
SHA_INT32 clo;
clo = sha_info->count_lo + ((SHA_INT32) count << 3);
if (clo < sha_info->count_lo) {
++sha_info->count_hi;
}
sha_info->count_lo = clo;
sha_info->count_hi += (SHA_INT32) count >> 29;
if (sha_info->local) {
i = SHA_BLOCKSIZE - sha_info->local;
if (i > count) {
i = count;
}
memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
count -= i;
buffer += i;
sha_info->local += (int)i;
if (sha_info->local == SHA_BLOCKSIZE) {
sha512_transform(sha_info);
}
else {
return;
}
}
while (count >= SHA_BLOCKSIZE) {
memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
buffer += SHA_BLOCKSIZE;
count -= SHA_BLOCKSIZE;
sha512_transform(sha_info);
}
memcpy(sha_info->data, buffer, count);
sha_info->local = (int)count;
}
/* finish computing the SHA digest */
static void
sha512_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info)
{
int count;
SHA_INT32 lo_bit_count, hi_bit_count;
lo_bit_count = sha_info->count_lo;
hi_bit_count = sha_info->count_hi;
count = (int) ((lo_bit_count >> 3) & 0x7f);
((SHA_BYTE *) sha_info->data)[count++] = 0x80;
if (count > SHA_BLOCKSIZE - 16) {
bzero(((SHA_BYTE *) sha_info->data) + count, SHA_BLOCKSIZE - count);
sha512_transform(sha_info);
bzero((SHA_BYTE *) sha_info->data, SHA_BLOCKSIZE - 16);
}
else {
bzero(((SHA_BYTE *)sha_info->data) + count, SHA_BLOCKSIZE - 16 - count);
}
/* GJS: note that we add the hi/lo in big-endian. sha512_transform will
swap these values into host-order. */
sha_info->data[112] = 0;
sha_info->data[113] = 0;
sha_info->data[114] = 0;
sha_info->data[115] = 0;
sha_info->data[116] = 0;
sha_info->data[117] = 0;
sha_info->data[118] = 0;
sha_info->data[119] = 0;
sha_info->data[120] = (hi_bit_count >> 24) & 0xff;
sha_info->data[121] = (hi_bit_count >> 16) & 0xff;
sha_info->data[122] = (hi_bit_count >> 8) & 0xff;
sha_info->data[123] = (hi_bit_count >> 0) & 0xff;
sha_info->data[124] = (lo_bit_count >> 24) & 0xff;
sha_info->data[125] = (lo_bit_count >> 16) & 0xff;
sha_info->data[126] = (lo_bit_count >> 8) & 0xff;
sha_info->data[127] = (lo_bit_count >> 0) & 0xff;
sha512_transform(sha_info);
digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 56) & 0xff);
digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 48) & 0xff);
digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 40) & 0xff);
digest[ 3] = (unsigned char) ((sha_info->digest[0] >> 32) & 0xff);
digest[ 4] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
digest[ 5] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
digest[ 6] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
digest[ 7] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
digest[ 8] = (unsigned char) ((sha_info->digest[1] >> 56) & 0xff);
digest[ 9] = (unsigned char) ((sha_info->digest[1] >> 48) & 0xff);
digest[10] = (unsigned char) ((sha_info->digest[1] >> 40) & 0xff);
digest[11] = (unsigned char) ((sha_info->digest[1] >> 32) & 0xff);
digest[12] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
digest[13] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
digest[14] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
digest[15] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
digest[16] = (unsigned char) ((sha_info->digest[2] >> 56) & 0xff);
digest[17] = (unsigned char) ((sha_info->digest[2] >> 48) & 0xff);
digest[18] = (unsigned char) ((sha_info->digest[2] >> 40) & 0xff);
digest[19] = (unsigned char) ((sha_info->digest[2] >> 32) & 0xff);
digest[20] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
digest[21] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
digest[22] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
digest[23] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
digest[24] = (unsigned char) ((sha_info->digest[3] >> 56) & 0xff);
digest[25] = (unsigned char) ((sha_info->digest[3] >> 48) & 0xff);
digest[26] = (unsigned char) ((sha_info->digest[3] >> 40) & 0xff);
digest[27] = (unsigned char) ((sha_info->digest[3] >> 32) & 0xff);
digest[28] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
digest[29] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
digest[30] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
digest[31] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
digest[32] = (unsigned char) ((sha_info->digest[4] >> 56) & 0xff);
digest[33] = (unsigned char) ((sha_info->digest[4] >> 48) & 0xff);
digest[34] = (unsigned char) ((sha_info->digest[4] >> 40) & 0xff);
digest[35] = (unsigned char) ((sha_info->digest[4] >> 32) & 0xff);
digest[36] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
digest[37] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
digest[38] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
digest[39] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
digest[40] = (unsigned char) ((sha_info->digest[5] >> 56) & 0xff);
digest[41] = (unsigned char) ((sha_info->digest[5] >> 48) & 0xff);
digest[42] = (unsigned char) ((sha_info->digest[5] >> 40) & 0xff);
digest[43] = (unsigned char) ((sha_info->digest[5] >> 32) & 0xff);
digest[44] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff);
digest[45] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff);
digest[46] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff);
digest[47] = (unsigned char) ((sha_info->digest[5] ) & 0xff);
digest[48] = (unsigned char) ((sha_info->digest[6] >> 56) & 0xff);
digest[49] = (unsigned char) ((sha_info->digest[6] >> 48) & 0xff);
digest[50] = (unsigned char) ((sha_info->digest[6] >> 40) & 0xff);
digest[51] = (unsigned char) ((sha_info->digest[6] >> 32) & 0xff);
digest[52] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff);
digest[53] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff);
digest[54] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff);
digest[55] = (unsigned char) ((sha_info->digest[6] ) & 0xff);
digest[56] = (unsigned char) ((sha_info->digest[7] >> 56) & 0xff);
digest[57] = (unsigned char) ((sha_info->digest[7] >> 48) & 0xff);
digest[58] = (unsigned char) ((sha_info->digest[7] >> 40) & 0xff);
digest[59] = (unsigned char) ((sha_info->digest[7] >> 32) & 0xff);
digest[60] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff);
digest[61] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff);
digest[62] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff);
digest[63] = (unsigned char) ((sha_info->digest[7] ) & 0xff);
}
/*
* End of copied SHA code.
*
* ------------------------------------------------------------------------
*/
static PyTypeObject SHA384type;
static PyTypeObject SHA512type;
static SHAobject *
newSHA384object(void)
{
return (SHAobject *)PyObject_New(SHAobject, &SHA384type);
}
static SHAobject *
newSHA512object(void)
{
return (SHAobject *)PyObject_New(SHAobject, &SHA512type);
}
/* Internal methods for a hash object */
static void
SHA512_dealloc(PyObject *ptr)
{
PyObject_Del(ptr);
}
/* External methods for a hash object */
/*[clinic input]
SHA512Type.copy
Return a copy of the hash object.
[clinic start generated code]*/
static PyObject *
SHA512Type_copy_impl(SHAobject *self)
/*[clinic end generated code: output=adea896ed3164821 input=9f5f31e6c457776a]*/
{
SHAobject *newobj;
if (((PyObject*)self)->ob_type == &SHA512type) {
if ( (newobj = newSHA512object())==NULL)
return NULL;
} else {
if ( (newobj = newSHA384object())==NULL)
return NULL;
}
SHAcopy(self, newobj);
return (PyObject *)newobj;
}
/*[clinic input]
SHA512Type.digest
Return the digest value as a bytes object.
[clinic start generated code]*/
static PyObject *
SHA512Type_digest_impl(SHAobject *self)
/*[clinic end generated code: output=1080bbeeef7dde1b input=f6470dd359071f4b]*/
{
unsigned char digest[SHA_DIGESTSIZE];
SHAobject temp;
SHAcopy(self, &temp);
sha512_final(digest, &temp);
return PyBytes_FromStringAndSize((const char *)digest, self->digestsize);
}
/*[clinic input]
SHA512Type.hexdigest
Return the digest value as a string of hexadecimal digits.
[clinic start generated code]*/
static PyObject *
SHA512Type_hexdigest_impl(SHAobject *self)
/*[clinic end generated code: output=7373305b8601e18b input=498b877b25cbe0a2]*/
{
unsigned char digest[SHA_DIGESTSIZE];
SHAobject temp;
/* Get the raw (binary) digest value */
SHAcopy(self, &temp);
sha512_final(digest, &temp);
return _Py_strhex((const char *)digest, self->digestsize);
}
/*[clinic input]
SHA512Type.update
obj: object
/
Update this hash object's state with the provided string.
[clinic start generated code]*/
static PyObject *
SHA512Type_update(SHAobject *self, PyObject *obj)
/*[clinic end generated code: output=1cf333e73995a79e input=ded2b46656566283]*/
{
Py_buffer buf;
GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
sha512_update(self, buf.buf, buf.len);
PyBuffer_Release(&buf);
Py_INCREF(Py_None);
return Py_None;
}
/*[clinic input]
dump buffer
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/
static PyMethodDef SHA_methods[] = {
SHA512TYPE_COPY_METHODDEF
SHA512TYPE_DIGEST_METHODDEF
SHA512TYPE_HEXDIGEST_METHODDEF
SHA512TYPE_UPDATE_METHODDEF
{NULL, NULL} /* sentinel */
};
static PyObject *
SHA512_get_block_size(PyObject *self, void *closure)
{
return PyLong_FromLong(SHA_BLOCKSIZE);
}
static PyObject *
SHA512_get_name(PyObject *self, void *closure)
{
if (((SHAobject *)self)->digestsize == 64)
return PyUnicode_FromStringAndSize("sha512", 6);
else
return PyUnicode_FromStringAndSize("sha384", 6);
}
static PyGetSetDef SHA_getseters[] = {
{"block_size",
(getter)SHA512_get_block_size, NULL,
NULL,
NULL},
{"name",
(getter)SHA512_get_name, NULL,
NULL,
NULL},
{NULL} /* Sentinel */
};
static PyMemberDef SHA_members[] = {
{"digest_size", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL},
{NULL} /* Sentinel */
};
static PyTypeObject SHA384type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_sha512.sha384", /*tp_name*/
sizeof(SHAobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
SHA512_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
SHA_methods, /* tp_methods */
SHA_members, /* tp_members */
SHA_getseters, /* tp_getset */
};
static PyTypeObject SHA512type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_sha512.sha512", /*tp_name*/
sizeof(SHAobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
SHA512_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
SHA_methods, /* tp_methods */
SHA_members, /* tp_members */
SHA_getseters, /* tp_getset */
};
/* The single module-level function: new() */
/*[clinic input]
_sha512.sha512
string: object(c_default="NULL") = b''
Return a new SHA-512 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
_sha512_sha512_impl(PyObject *module, PyObject *string)
/*[clinic end generated code: output=8b865a2df73bd387 input=e69bad9ae9b6a308]*/
{
SHAobject *new;
Py_buffer buf;
if (string)
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
if ((new = newSHA512object()) == NULL) {
if (string)
PyBuffer_Release(&buf);
return NULL;
}
sha512_init(new);
if (PyErr_Occurred()) {
Py_DECREF(new);
if (string)
PyBuffer_Release(&buf);
return NULL;
}
if (string) {
sha512_update(new, buf.buf, buf.len);
PyBuffer_Release(&buf);
}
return (PyObject *)new;
}
/*[clinic input]
_sha512.sha384
string: object(c_default="NULL") = b''
Return a new SHA-384 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
_sha512_sha384_impl(PyObject *module, PyObject *string)
/*[clinic end generated code: output=ae4b2e26decf81e8 input=c9327788d4ea4545]*/
{
SHAobject *new;
Py_buffer buf;
if (string)
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
if ((new = newSHA384object()) == NULL) {
if (string)
PyBuffer_Release(&buf);
return NULL;
}
sha384_init(new);
if (PyErr_Occurred()) {
Py_DECREF(new);
if (string)
PyBuffer_Release(&buf);
return NULL;
}
if (string) {
sha512_update(new, buf.buf, buf.len);
PyBuffer_Release(&buf);
}
return (PyObject *)new;
}
/*[clinic input]
dump buffer
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/
/* List of functions exported by this module */
static struct PyMethodDef SHA_functions[] = {
_SHA512_SHA512_METHODDEF
_SHA512_SHA384_METHODDEF
{NULL, NULL} /* Sentinel */
};
/* Initialize this module. */
#define insint(n,v) { PyModule_AddIntConstant(m,n,v); }
static struct PyModuleDef _sha512module = {
PyModuleDef_HEAD_INIT,
"_sha512",
NULL,
-1,
SHA_functions,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC
PyInit__sha512(void)
{
PyObject *m;
Py_TYPE(&SHA384type) = &PyType_Type;
if (PyType_Ready(&SHA384type) < 0)
return NULL;
Py_TYPE(&SHA512type) = &PyType_Type;
if (PyType_Ready(&SHA512type) < 0)
return NULL;
m = PyModule_Create(&_sha512module);
if (m == NULL)
return NULL;
Py_INCREF((PyObject *)&SHA384type);
PyModule_AddObject(m, "SHA384Type", (PyObject *)&SHA384type);
Py_INCREF((PyObject *)&SHA512type);
PyModule_AddObject(m, "SHA512Type", (PyObject *)&SHA512type);
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__sha512 = {
"_sha512",
PyInit__sha512,
};

View file

@ -985,13 +985,13 @@ signal_sigwait(PyObject *module, PyObject *sigset)
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
static int initialized;
static PyStructSequence_Field struct_siginfo_fields[] = {
{"si_signo", "signal number"},
{"si_code", "signal code"},
{"si_errno", "errno associated with this signal"},
{"si_pid", "sending process ID"},
{"si_uid", "real user ID of sending process"},
{"si_status", "exit value or signal"},
{"si_band", "band event for SIGPOLL"},
{"si_signo", PyDoc_STR("signal number")},
{"si_code", PyDoc_STR("signal code")},
{"si_errno", PyDoc_STR("errno associated with this signal")},
{"si_pid", PyDoc_STR("sending process ID")},
{"si_uid", PyDoc_STR("real user ID of sending process")},
{"si_status", PyDoc_STR("exit value or signal")},
{"si_band", PyDoc_STR("band event for SIGPOLL")},
{0}
};
@ -1564,3 +1564,8 @@ void *_PyOS_SigintEvent(void)
return sigint_event;
}
#endif
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab__signal = {
"_signal",
PyInit__signal,
};

View file

@ -1027,8 +1027,7 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int
{
struct addrinfo hints, *res;
int error;
memset((void *) addr_ret, '\0', sizeof(*addr_ret));
bzero(addr_ret, sizeof(*addr_ret));
if (name[0] == '\0') {
int siz;
bzero(&hints, sizeof(hints));
@ -1086,7 +1085,7 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int
return -1;
}
sin = (struct sockaddr_in *)addr_ret;
memset((void *) sin, '\0', sizeof(*sin));
bzero(sin, sizeof(*sin));
sin->sin_family = AF_INET;
#ifdef HAVE_SOCKADDR_SA_LEN
sin->sin_len = sizeof(*sin);
@ -5147,7 +5146,7 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args)
#elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
h = gethostbyname_r(name, &hp_allocated, buf, buf_len, &errnop);
#else /* HAVE_GETHOSTBYNAME_R_3_ARG */
memset((void *) &data, '\0', sizeof(data));
bzero(&data, sizeof(data));
result = gethostbyname_r(name, &hp_allocated, &data);
h = (result != 0) ? NULL : &hp_allocated;
#endif
@ -5245,7 +5244,7 @@ socket_gethostbyaddr(PyObject *self, PyObject *args)
h = gethostbyaddr_r(ap, al, af,
&hp_allocated, buf, buf_len, &errnop);
#else /* HAVE_GETHOSTBYNAME_R_3_ARG */
memset((void *) &data, '\0', sizeof(data));
bzero(&data, sizeof(data));
result = gethostbyaddr_r(ap, al, af, &hp_allocated, &data);
h = (result != 0) ? NULL : &hp_allocated;
#endif
@ -5838,7 +5837,7 @@ socket_inet_ntop(PyObject *self, PyObject *args)
#endif
/* Guarantee NUL-termination for PyUnicode_FromString() below */
memset((void *) &ip[0], '\0', sizeof(ip));
bzero(&ip[0], sizeof(ip));
if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) {
return NULL;
@ -5893,7 +5892,7 @@ socket_inet_ntop(PyObject *self, PyObject *args)
#endif
/* Guarantee NUL-termination for PyUnicode_FromString() below */
memset((void *) &ip[0], '\0', sizeof(ip));
bzero(&ip[0], sizeof(ip));
if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) {
return NULL;

View file

@ -41,17 +41,17 @@ You have to be root to be able to use this module.");
#if defined(HAVE_GETSPNAM) || defined(HAVE_GETSPENT)
static PyStructSequence_Field struct_spwd_type_fields[] = {
{"sp_namp", "login name"},
{"sp_pwdp", "encrypted password"},
{"sp_lstchg", "date of last change"},
{"sp_min", "min #days between changes"},
{"sp_max", "max #days between changes"},
{"sp_warn", "#days before pw expires to warn user about it"},
{"sp_inact", "#days after pw expires until account is disabled"},
{"sp_expire", "#days since 1970-01-01 when account expires"},
{"sp_flag", "reserved"},
{"sp_nam", "login name; deprecated"}, /* Backward compatibility */
{"sp_pwd", "encrypted password; deprecated"}, /* Backward compatibility */
{"sp_namp", PyDoc_STR("login name")},
{"sp_pwdp", PyDoc_STR("encrypted password")},
{"sp_lstchg", PyDoc_STR("date of last change")},
{"sp_min", PyDoc_STR("min #days between changes")},
{"sp_max", PyDoc_STR("max #days between changes")},
{"sp_warn", PyDoc_STR("#days before pw expires to warn user about it")},
{"sp_inact", PyDoc_STR("#days after pw expires until account is disabled")},
{"sp_expire", PyDoc_STR("#days since 1970-01-01 when account expires")},
{"sp_flag", PyDoc_STR("reserved")},
{"sp_nam", PyDoc_STR("login name; deprecated")}, /* Backward compatibility */
{"sp_pwd", PyDoc_STR("encrypted password; deprecated")}, /* Backward compatibility */
{0}
};
@ -206,8 +206,6 @@ static PyMethodDef spwd_methods[] = {
{NULL, NULL} /* sentinel */
};
static struct PyModuleDef spwdmodule = {
PyModuleDef_HEAD_INIT,
"spwd",

View file

@ -82,4 +82,4 @@ typedef struct {
SRE_STATE state;
} ScannerObject;
#endif
#endif /* SRE_INCLUDED */

View file

@ -1,15 +1,8 @@
/*
* Secret Labs' Regular Expression Engine
*
* regular expression matching engine
*
* NOTE: This file is generated by sre_constants.py. If you need
* to change anything in here, edit sre_constants.py and run it.
*
* Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved.
*
* See the _sre.c file for information on usage and redistribution.
*/
#ifndef COSMOPOLITAN_THIRD_PARTY_PYTHON_MODULES_SRE_CONSTANTS_H_
#define COSMOPOLITAN_THIRD_PARTY_PYTHON_MODULES_SRE_CONSTANTS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */
#define SRE_MAGIC 20140917
#define SRE_OP_FAILURE 0
@ -87,3 +80,7 @@
#define SRE_INFO_PREFIX 1
#define SRE_INFO_LITERAL 2
#define SRE_INFO_CHARSET 4
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_PYTHON_MODULES_SRE_CONSTANTS_H_ */

View file

@ -274,17 +274,17 @@ Delay execution for a given number of seconds. The argument may be\n\
a floating point number for subsecond precision.");
static PyStructSequence_Field struct_time_type_fields[] = {
{"tm_year", "year, for example, 1993"},
{"tm_mon", "month of year, range [1, 12]"},
{"tm_mday", "day of month, range [1, 31]"},
{"tm_hour", "hours, range [0, 23]"},
{"tm_min", "minutes, range [0, 59]"},
{"tm_sec", "seconds, range [0, 61])"},
{"tm_wday", "day of week, range [0, 6], Monday is 0"},
{"tm_yday", "day of year, range [1, 366]"},
{"tm_isdst", "1 if summer time is in effect, 0 if not, and -1 if unknown"},
{"tm_zone", "abbreviation of timezone name"},
{"tm_gmtoff", "offset from UTC in seconds"},
{"tm_year", PyDoc_STR("year, for example, 1993")},
{"tm_mon", PyDoc_STR("month of year, range [1, 12]")},
{"tm_mday", PyDoc_STR("day of month, range [1, 31]")},
{"tm_hour", PyDoc_STR("hours, range [0, 23]")},
{"tm_min", PyDoc_STR("minutes, range [0, 59]")},
{"tm_sec", PyDoc_STR("seconds, range [0, 61])")},
{"tm_wday", PyDoc_STR("day of week, range [0, 6], Monday is 0")},
{"tm_yday", PyDoc_STR("day of year, range [1, 366]")},
{"tm_isdst", PyDoc_STR("1 if summer time is in effect, 0 if not, and -1 if unknown")},
{"tm_zone", PyDoc_STR("abbreviation of timezone name")},
{"tm_gmtoff", PyDoc_STR("offset from UTC in seconds")},
{0}
};
@ -345,6 +345,14 @@ tmtotuple(struct tm *p
return v;
}
static int64_t
Time(int64_t *tp) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
if (tp) *tp = ts.tv_sec;
return ts.tv_sec;
}
/* Parse arg tuple that can contain an optional float-or-None value;
format needs to be "|O:name".
Returns non-zero on success (parallels PyArg_ParseTuple).
@ -357,7 +365,7 @@ parse_time_t_args(PyObject *args, const char *format, time_t *pwhen)
if (!PyArg_ParseTuple(args, format, &ot))
return 0;
if (ot == NULL || ot == Py_None) {
whent = time(NULL);
whent = Time(NULL);
}
else {
if (_PyTime_ObjectToTime_t(ot, &whent, _PyTime_ROUND_FLOOR) == -1)
@ -445,7 +453,7 @@ gettmarg(PyObject *args, struct tm *p)
{
int y;
memset((void *) p, '\0', sizeof(struct tm));
bzero(p, sizeof(struct tm));
if (!PyTuple_Check(args)) {
PyErr_SetString(PyExc_TypeError,
@ -605,7 +613,7 @@ time_strftime(PyObject *self, PyObject *args)
size_t i;
PyObject *ret = NULL;
memset((void *) &buf, '\0', sizeof(buf));
bzero(&buf, sizeof(buf));
/* Will always expect a unicode string to be passed as format.
Given that there's no str type anymore in py3k this seems safe.
@ -614,7 +622,7 @@ time_strftime(PyObject *self, PyObject *args)
return NULL;
if (tup == NULL) {
time_t tt = time(NULL);
time_t tt = Time(NULL);
if (_PyTime_localtime(tt, &buf) != 0)
return NULL;
}
@ -797,7 +805,7 @@ time_asctime(PyObject *self, PyObject *args)
if (!PyArg_UnpackTuple(args, "asctime", 0, 1, &tup))
return NULL;
if (tup == NULL) {
time_t tt = time(NULL);
time_t tt = Time(NULL);
if (_PyTime_localtime(tt, &buf) != 0)
return NULL;
} else if (!gettmarg(tup, &buf) || !checktm(&buf))
@ -1217,7 +1225,7 @@ init_timezone(PyObject *m)
struct tm p;
time_t janzone_t, julyzone_t;
char janname[10], julyname[10];
t = (time((time_t *)0) / YEAR) * YEAR;
t = (Time((time_t *)0) / YEAR) * YEAR;
_PyTime_localtime(t, &p);
get_zone(janname, 9, &p);
janzone_t = -get_gmtoff(t, &p);
@ -1410,6 +1418,7 @@ pysleep(_PyTime_t secs)
_PyTime_t deadline, monotonic;
#ifndef MS_WINDOWS
struct timeval timeout;
struct timespec timeout2;
int err = 0;
#else
_PyTime_t millisecs;
@ -1422,11 +1431,16 @@ pysleep(_PyTime_t secs)
do {
#ifndef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
#ifdef __COSMOPOLITAN__
if (_PyTime_AsTimespec(secs, &timeout2) < 0)
return -1;
err = nanosleep(&timeout2, 0);
#else /* b/c xnu */
if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0)
return -1;
Py_BEGIN_ALLOW_THREADS
err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);
#endif
Py_END_ALLOW_THREADS
if (err == 0)

504
third_party/python/Modules/tlsmodule.c vendored Normal file
View file

@ -0,0 +1,504 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Copying of this file is authorized only if (1) you are Justine Tunney,
or (2) you make absolutely no changes to your copy.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#define PY_SSIZE_T_CLEAN
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/runtime/gc.internal.h"
#include "libc/str/str.h"
#include "net/https/https.h"
#include "third_party/mbedtls/ctr_drbg.h"
#include "third_party/mbedtls/debug.h"
#include "third_party/mbedtls/error.h"
#include "third_party/mbedtls/ssl.h"
#include "third_party/python/Include/abstract.h"
#include "third_party/python/Include/import.h"
#include "third_party/python/Include/longobject.h"
#include "third_party/python/Include/modsupport.h"
#include "third_party/python/Include/object.h"
#include "third_party/python/Include/objimpl.h"
#include "third_party/python/Include/pyerrors.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/structmember.h"
#include "third_party/python/Include/yoink.h"
/* clang-format off */
/**
* @fileoverview Enough TLS support for HttpsClient so far.
*/
PYTHON_PROVIDE("tls");
#if 0
#define LOG(...) __printf(__VA_ARGS__)
#else
#define LOG(...) (void)0
#endif
struct Tls {
PyObject_HEAD
int fd;
PyObject *todo;
mbedtls_ssl_config conf;
mbedtls_ssl_context ssl;
mbedtls_ctr_drbg_context rng;
};
static PyObject *TlsError;
static PyTypeObject tls_type;
static mbedtls_x509_crt *roots;
static PyObject *
SetTlsError(int rc)
{
char b[128];
mbedtls_strerror(rc, b, sizeof(b));
PyErr_SetString(TlsError, b);
return NULL;
}
static int
TlsSend(void *c, const unsigned char *p, size_t n)
{
int rc;
struct Tls *self = c;
for (;;) {
rc = write(self->fd, p, n);
if (rc != -1) {
return rc;
} else if (errno == EINTR) {
if (PyErr_CheckSignals()) {
return -1;
}
} else {
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
}
}
static int
TlsRecv(void *c, unsigned char *p, size_t n, uint32_t t)
{
int rc;
struct Tls *self = c;
for (;;) {
rc = read(self->fd, p, n);
if (rc != -1) {
return rc;
} else if (errno == EINTR) {
if (PyErr_CheckSignals()) {
return -1;
}
} else {
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
}
}
static struct Tls *
tls_new(int fd, const char *host, PyObject *todo)
{
struct Tls *self;
LOG("TLS.new\n");
if ((self = PyObject_New(struct Tls, &tls_type))) {
self->fd = fd;
self->todo = todo;
Py_INCREF(todo);
InitializeRng(&self->rng);
mbedtls_ssl_init(&self->ssl);
mbedtls_ssl_config_init(&self->conf);
mbedtls_ssl_config_defaults(&self->conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
mbedtls_ssl_conf_rng(&self->conf, mbedtls_ctr_drbg_random, &self->rng);
mbedtls_ssl_conf_ca_chain(&self->conf, roots, 0);
/* mbedtls_ssl_conf_dbg(&self->conf, TlsDebug, 0); */
/* mbedtls_debug_threshold = 5; */
if (host && *host) {
mbedtls_ssl_conf_authmode(&self->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_set_hostname(&self->ssl, host);
} else {
mbedtls_ssl_conf_authmode(&self->conf, MBEDTLS_SSL_VERIFY_NONE);
}
mbedtls_ssl_set_bio(&self->ssl, self, TlsSend, 0, TlsRecv);
mbedtls_ssl_setup(&self->ssl, &self->conf);
self->conf.disable_compression = true;
}
return self;
}
static void
tls_dealloc(struct Tls *self)
{
LOG("TLS.dealloc\n");
if (self->fd != -1) {
LOG("TLS CLOSING\n");
close(self->fd);
}
Py_DECREF(self->todo);
if (PyErr_Occurred()) {
PyErr_Clear();
}
mbedtls_ssl_free(&self->ssl);
mbedtls_ctr_drbg_free(&self->rng);
mbedtls_ssl_config_free(&self->conf);
PyObject_Del(self);
}
PyDoc_STRVAR(tls_send__doc__, "\
send($self, bytes, /)\n\
--\n\n\
Sends bytes as ciphertext to file descriptor, returning number\n\
of bytes from buffer transmitted, or raising OSError/TlsError.");
static PyObject *
tls_send(struct Tls *self, PyObject *args)
{
int rc;
PyObject *res;
Py_buffer data;
LOG("TLS.send\n");
if (!PyArg_ParseTuple(args, "y*:send", &data)) return 0;
rc = mbedtls_ssl_write(&self->ssl, data.buf, data.len);
if (rc != -1) {
if (rc >= 0) {
res = PyLong_FromLong(rc);
} else {
SetTlsError(rc);
LOG("TLS CLOSING\n");
close(self->fd);
self->fd = -1;
res = 0;
}
} else {
res = 0;
}
PyBuffer_Release(&data);
return res;
}
PyDoc_STRVAR(tls_sendall__doc__, "\
sendall($self, bytes, /)\n\
--\n\n\
Sends all bytes to file descriptor as ciphertext, returning number\n\
of bytes from buffer transmitted, or raising OSError / TlsError.");
static PyObject *
tls_sendall(struct Tls *self, PyObject *args)
{
LOG("TLS.sendall\n");
int rc;
Py_ssize_t i;
PyObject *res;
Py_buffer data;
if (!PyArg_ParseTuple(args, "y*:sendall", &data)) return 0;
for (i = 0;;) {
rc = mbedtls_ssl_write(&self->ssl, (char *)data.buf + i, data.len - i);
if (rc > 0) {
if ((i += rc) == data.len) {
res = Py_None;
Py_INCREF(res);
break;
}
} else {
if (rc != -1) {
SetTlsError(rc);
LOG("TLS CLOSING\n");
close(self->fd);
self->fd = -1;
}
res = 0;
break;
}
}
PyBuffer_Release(&data);
return res;
}
PyDoc_STRVAR(tls_recv__doc__, "\
recv($self, nbytes, /)\n\
--\n\n\
Receives deciphered bytes from file descriptor, returning bytes\n\
or raising OSError / TlsError.");
static PyObject *
tls_recv(struct Tls *self, PyObject *args)
{
LOG("TLS.recv\n");
int rc;
Py_ssize_t n;
PyObject *res, *buf;
if (!PyArg_ParseTuple(args, "n:recv", &n)) return 0;
if (n < 0) {
PyErr_SetString(PyExc_ValueError,
"negative buffersize in recv");
return NULL;
}
if (!(buf = PyBytes_FromStringAndSize(0, n))) return 0;
rc = mbedtls_ssl_read(&self->ssl, PyBytes_AS_STRING(buf), n);
if (rc != -1) {
if (rc >= 0) {
if (rc != n) {
_PyBytes_Resize(&buf, rc);
}
res = buf;
} else {
Py_DECREF(buf);
SetTlsError(rc);
LOG("TLS CLOSING\n");
close(self->fd);
self->fd = -1;
res = 0;
}
} else {
Py_DECREF(buf);
res = 0;
}
return res;
}
PyDoc_STRVAR(tls_recv_into__doc__, "\
recv_into($self, buf, /)\n\
--\n\n\
Reads into an existing buffer...");
static PyObject *
tls_recv_into(struct Tls *self, PyObject *args)
{
LOG("TLS.recv_into\n");
int rc;
Py_ssize_t n;
PyObject *res;
Py_buffer buf;
if (!PyArg_ParseTuple(args, "w*:recv_into", &buf)) return 0;
rc = mbedtls_ssl_read(&self->ssl, buf.buf, buf.len);
if (rc != -1) {
if (rc >= 0) {
res = PyLong_FromLong(rc);
LOG("got %d\n", rc);
} else {
SetTlsError(rc);
LOG("TLS CLOSING\n");
close(self->fd);
self->fd = -1;
res = 0;
}
} else {
res = 0;
}
PyBuffer_Release(&buf);
return res;
}
PyDoc_STRVAR(tls_fileno__doc__, "\
fileno($self, /)\n\
--\n\n\
Returns file descriptor passed to constructor.");
static PyObject *
tls_fileno(struct Tls *self, PyObject *unused)
{
LOG("TLS.fileno\n");
return PyLong_FromLong(self->fd);
}
PyDoc_STRVAR(tls_shutdown__doc__, "\
shutdown($self, how, /)\n\
--\n\n\
Does nothing currently.");
static PyObject *
tls_shutdown(struct Tls *self, PyObject *unused)
{
LOG("TLS.shutdown\n");
Py_RETURN_NONE;
}
PyDoc_STRVAR(tls_close__doc__, "\
close($self, /)\n\
--\n\n\
Closes SSL connection and file descriptor.");
static PyObject *
tls_close(struct Tls *self, PyObject *unused)
{
int rc, fd;
/* TODO(jart): do nothing until we can figure out how to own fd */
Py_RETURN_NONE;
fd = self->fd;
if (fd != -1) {
self->fd = -1;
rc = mbedtls_ssl_close_notify(&self->ssl);
if (rc) {
LOG("TLS CLOSING\n");
close(fd);
if (rc != -1) {
SetTlsError(rc);
}
return 0;
}
LOG("TLS CLOSING\n");
rc = close(fd);
if (rc == -1) {
return PyErr_SetFromErrno(PyExc_OSError);
}
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(tls_handshake__doc__, "\
handshake($self, /)\n\
--\n\n\
Handshakes SSL connection and file descriptor.");
static PyObject *
tls_handshake(struct Tls *self, PyObject *unused)
{
int rc;
LOG("TLS.handshake\n");
rc = mbedtls_ssl_handshake(&self->ssl);
if (rc) {
LOG("TLS CLOSING\n");
close(self->fd);
self->fd = -1;
if (rc != -1) {
if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
PyErr_SetString(TlsError, gc(DescribeSslVerifyFailure(self->ssl.session_negotiate->verify_result)));
} else {
SetTlsError(rc);
}
}
return 0;
}
Py_RETURN_NONE;
}
static PyMethodDef tls_methods[] = {
{"handshake", (PyCFunction)tls_handshake, METH_NOARGS, tls_handshake__doc__},
{"recv", (PyCFunction)tls_recv, METH_VARARGS, tls_recv__doc__},
{"recv_into", (PyCFunction)tls_recv_into, METH_VARARGS, tls_recv_into__doc__},
{"send", (PyCFunction)tls_send, METH_VARARGS, tls_send__doc__},
{"sendall", (PyCFunction)tls_sendall, METH_VARARGS, tls_sendall__doc__},
{"fileno", (PyCFunction)tls_fileno, METH_NOARGS, tls_fileno__doc__},
{"shutdown", (PyCFunction)tls_shutdown, METH_VARARGS, tls_shutdown__doc__},
{"close", (PyCFunction)tls_close, METH_NOARGS, tls_close__doc__},
{0}
};
static PyObject *
tls_repr(struct Tls *self)
{
return PyUnicode_FromFormat("<TLS object @ %p>", self);
}
PyDoc_STRVAR(tls_doc,
"An MbedTLS object.");
static PyTypeObject tls_type = {
PyVarObject_HEAD_INIT(NULL, 0)
/*tp_name*/ "tls.TLS",
/*tp_basicsize*/ sizeof(struct Tls),
/*tp_itemsize*/ 0,
/*tp_dealloc*/ (destructor)tls_dealloc,
/*tp_print*/ 0,
/*tp_getattr*/ 0,
/*tp_setattr*/ 0,
/*tp_reserved*/ 0,
/*tp_repr*/ (reprfunc)tls_repr,
/*tp_as_number*/ 0,
/*tp_as_sequence*/ 0,
/*tp_as_mapping*/ 0,
/*tp_hash*/ 0,
/*tp_call*/ 0,
/*tp_str*/ 0,
/*tp_getattro*/ 0,
/*tp_setattro*/ 0,
/*tp_as_buffer*/ 0,
/*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
/*tp_doc*/ tls_doc,
/*tp_traverse*/ 0,
/*tp_clear*/ 0,
/*tp_richcompare*/ 0,
/*tp_weaklistoffset*/ 0,
/*tp_iter*/ 0,
/*tp_iternext*/ 0,
/*tp_methods*/ tls_methods,
/*tp_members*/ 0,
/*tp_getset*/ 0,
/*tp_base*/ 0,
/*tp_dict*/ 0,
/*tp_descr_get*/ 0,
/*tp_descr_set*/ 0,
/*tp_dictoffset*/ 0,
};
PyDoc_STRVAR(newclient__doc__,
"newclient($module, fd, host)\n\
--\n\n\
Creates TLS client.");
static PyObject *
newclient(PyObject *self, PyObject *args)
{
int rc, fd;
PyObject *todo;
struct Tls *tls;
const char *host;
if (!PyArg_ParseTuple(args, "isO:newclient", &fd, &host, &todo)) return 0;
tls = tls_new(fd, host, todo);
return (PyObject *)tls;
}
static struct PyMethodDef mbedtls_functions[] = {
{"newclient", (PyCFunction)newclient, METH_VARARGS, newclient__doc__},
{0}
};
static struct PyModuleDef mbedtls_module = {
PyModuleDef_HEAD_INIT,
"tls",
NULL,
-1,
mbedtls_functions
};
PyMODINIT_FUNC
PyInit_tls(void)
{
PyObject *m, *mbedtls_md_meth_names;
Py_TYPE(&tls_type) = &PyType_Type;
if (PyType_Ready(&tls_type) < 0) return 0;
if (!(m = PyModule_Create(&mbedtls_module))) return 0;
Py_INCREF((PyObject *)&tls_type);
PyModule_AddObject(m, "TLS", (PyObject *)&tls_type);
TlsError = PyErr_NewException("tls.TlsError", NULL, NULL);
Py_INCREF(TlsError);
PyModule_AddObject(m, "TlsError", TlsError);
roots = GetSslRoots();
return m;
}
_Section(".rodata.pytab.1") const struct _inittab _PyImport_Inittab_tls = {
"tls",
PyInit_tls,
};

File diff suppressed because it is too large Load diff

120
third_party/python/Modules/unicodedata.h vendored Normal file
View file

@ -0,0 +1,120 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_PYTHON_MODULES_UNICODEDATA_H_
#define COSMOPOLITAN_THIRD_PARTY_PYTHON_MODULES_UNICODEDATA_H_
#include "libc/assert.h"
#include "third_party/python/Include/object.h"
#include "third_party/python/Include/unicodeobject.h"
#define _Hanghoul_SBase 0xAC00
#define _Hanghoul_LBase 0x1100
#define _Hanghoul_VBase 0x1161
#define _Hanghoul_TBase 0x11A7
#define _Hanghoul_LCount 19
#define _Hanghoul_VCount 21
#define _Hanghoul_TCount 28
#define _Hanghoul_NCount (_Hanghoul_VCount * _Hanghoul_TCount)
#define _Hanghoul_SCount (_Hanghoul_LCount * _Hanghoul_NCount)
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* clang-format off */
/*
* [jart] if it adds 1.2megs to each binary then it should have an api
* breaking this up into separate files allows ld to do its job
*/
#define UCD_Check(o) (Py_TYPE(o)==&UCD_Type)
#define get_old_record(self, v) ((((PreviousDBVersion*)self)->getrecord)(v))
typedef struct {
const unsigned char category; /* index into _PyUnicode_CategoryNames */
const unsigned char combining; /* combining class value 0 - 255 */
const unsigned char bidirectional; /* index into _PyUnicode_BidirectionalNames */
const unsigned char mirrored; /* true if mirrored in bidir mode */
const unsigned char east_asian_width; /* index into _PyUnicode_EastAsianWidth */
const unsigned char normalization_quick_check; /* see is_normalized() */
} _PyUnicode_Record;
typedef struct {
/* sequence of fields should be the same as in merge_old_version */
const unsigned char bidir_changed;
const unsigned char category_changed;
const unsigned char decimal_changed;
const unsigned char mirrored_changed;
const unsigned char east_asian_width_changed;
const double numeric_changed;
} _PyUnicode_ChangeRecord;
typedef struct {
PyObject_HEAD
const char *name;
const _PyUnicode_ChangeRecord *(*getrecord)(Py_UCS4);
Py_UCS4 (*normalization)(Py_UCS4);
} PreviousDBVersion;
typedef struct {
int start;
short count;
short index;
} _PyUnicode_Reindex;
typedef struct {
/*
These are either deltas to the character or offsets in
_PyUnicode_ExtendedCase.
*/
int upper;
int lower;
int title;
/* Note if more flag space is needed, decimal and digit could be unified. */
unsigned char decimal;
unsigned char digit;
unsigned short flags;
} _PyUnicode_TypeRecord;
/*
* In Unicode 6.0.0, the sequences contain at most 4 BMP chars,
* so we are using Py_UCS2 seq[4]. This needs to be updated if longer
* sequences or sequences with non-BMP chars are added.
* unicodedata_lookup should be adapted too.
*/
typedef struct{
int seqlen;
Py_UCS2 seq[4];
} _PyUnicode_NamedSequence;
extern PyTypeObject UCD_Type;
int _PyUnicode_IsUnifiedIdeograph(Py_UCS4);
const _PyUnicode_Record *_PyUnicode_GetRecord(Py_UCS4);
PyObject *_PyUnicode_NfcNfkc(PyObject *, PyObject *, int);
PyObject *_PyUnicode_NfdNfkd(PyObject *, PyObject *, int);
int _PyUnicode_IsNormalized(PyObject *, PyObject *, int, int);
int _PyUnicode_GetUcName(PyObject *, Py_UCS4, char *, int, int);
int _PyUnicode_FindNfcIndex(const _PyUnicode_Reindex *, Py_UCS4);
void _PyUnicode_FindSyllable(const char *, int *, int *, int, int);
int _PyUnicode_GetCode(PyObject *, const char *, int, Py_UCS4 *, int);
void _PyUnicode_GetDecompRecord(PyObject *, Py_UCS4, int *, int *, int *);
static inline unsigned _PyUnicode_Bextr(const unsigned *p, unsigned i, char b) {
size_t j;
unsigned k, r, w;
w = sizeof(unsigned) * CHAR_BIT;
assert(0 <= b && b < w);
j = i;
j *= b;
k = j & (w - 1);
j /= w;
if (k <= w - b) {
return (p[j] >> k) & ((1ul << b) - 1);
} else {
r = p[j] >> k;
r |= p[j + 1] << (w - k);
r &= (1ul << b) - 1;
return r;
}
}
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_PYTHON_MODULES_UNICODEDATA_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,475 @@
#include "libc/nexgen32e/kompressor.h"
#include "third_party/python/Modules/unicodedata.h"
/* clang-format off */
/* GENERATED BY third_party/python/Tools/unicode/makeunicodedata.py 3.2 */
const unsigned int _PyUnicode_NameAliases[468] = {
0x0000,
0x0000,
0x0001,
0x0001,
0x0002,
0x0002,
0x0003,
0x0003,
0x0004,
0x0004,
0x0005,
0x0005,
0x0006,
0x0006,
0x0007,
0x0007,
0x0008,
0x0008,
0x0009,
0x0009,
0x0009,
0x0009,
0x000A,
0x000A,
0x000A,
0x000A,
0x000A,
0x000A,
0x000B,
0x000B,
0x000B,
0x000C,
0x000C,
0x000D,
0x000D,
0x000E,
0x000E,
0x000E,
0x000F,
0x000F,
0x000F,
0x0010,
0x0010,
0x0011,
0x0011,
0x0012,
0x0012,
0x0013,
0x0013,
0x0014,
0x0014,
0x0015,
0x0015,
0x0016,
0x0016,
0x0017,
0x0017,
0x0018,
0x0018,
0x0019,
0x0019,
0x001A,
0x001A,
0x001B,
0x001B,
0x001C,
0x001C,
0x001C,
0x001D,
0x001D,
0x001D,
0x001E,
0x001E,
0x001E,
0x001F,
0x001F,
0x001F,
0x0020,
0x007F,
0x007F,
0x0080,
0x0080,
0x0081,
0x0081,
0x0082,
0x0082,
0x0083,
0x0083,
0x0084,
0x0084,
0x0085,
0x0085,
0x0086,
0x0086,
0x0087,
0x0087,
0x0088,
0x0088,
0x0088,
0x0089,
0x0089,
0x0089,
0x008A,
0x008A,
0x008A,
0x008B,
0x008B,
0x008B,
0x008C,
0x008C,
0x008C,
0x008D,
0x008D,
0x008D,
0x008E,
0x008E,
0x008E,
0x008F,
0x008F,
0x008F,
0x0090,
0x0090,
0x0091,
0x0091,
0x0091,
0x0092,
0x0092,
0x0092,
0x0093,
0x0093,
0x0094,
0x0094,
0x0095,
0x0095,
0x0096,
0x0096,
0x0096,
0x0097,
0x0097,
0x0097,
0x0098,
0x0098,
0x0099,
0x0099,
0x009A,
0x009A,
0x009B,
0x009B,
0x009C,
0x009C,
0x009D,
0x009D,
0x009E,
0x009E,
0x009F,
0x009F,
0x00A0,
0x00AD,
0x01A2,
0x01A3,
0x034F,
0x061C,
0x0709,
0x0CDE,
0x0E9D,
0x0E9F,
0x0EA3,
0x0EA5,
0x0FD0,
0x11EC,
0x11ED,
0x11EE,
0x11EF,
0x180B,
0x180C,
0x180D,
0x180E,
0x200B,
0x200C,
0x200D,
0x200E,
0x200F,
0x202A,
0x202B,
0x202C,
0x202D,
0x202E,
0x202F,
0x205F,
0x2060,
0x2066,
0x2067,
0x2068,
0x2069,
0x2118,
0x2448,
0x2449,
0x2B7A,
0x2B7C,
0xA015,
0xFE00,
0xFE01,
0xFE02,
0xFE03,
0xFE04,
0xFE05,
0xFE06,
0xFE07,
0xFE08,
0xFE09,
0xFE0A,
0xFE0B,
0xFE0C,
0xFE0D,
0xFE0E,
0xFE0F,
0xFE18,
0xFEFF,
0xFEFF,
0xFEFF,
0x122D4,
0x122D5,
0x16E56,
0x16E57,
0x16E76,
0x16E77,
0x1B001,
0x1D0C5,
0xE0100,
0xE0101,
0xE0102,
0xE0103,
0xE0104,
0xE0105,
0xE0106,
0xE0107,
0xE0108,
0xE0109,
0xE010A,
0xE010B,
0xE010C,
0xE010D,
0xE010E,
0xE010F,
0xE0110,
0xE0111,
0xE0112,
0xE0113,
0xE0114,
0xE0115,
0xE0116,
0xE0117,
0xE0118,
0xE0119,
0xE011A,
0xE011B,
0xE011C,
0xE011D,
0xE011E,
0xE011F,
0xE0120,
0xE0121,
0xE0122,
0xE0123,
0xE0124,
0xE0125,
0xE0126,
0xE0127,
0xE0128,
0xE0129,
0xE012A,
0xE012B,
0xE012C,
0xE012D,
0xE012E,
0xE012F,
0xE0130,
0xE0131,
0xE0132,
0xE0133,
0xE0134,
0xE0135,
0xE0136,
0xE0137,
0xE0138,
0xE0139,
0xE013A,
0xE013B,
0xE013C,
0xE013D,
0xE013E,
0xE013F,
0xE0140,
0xE0141,
0xE0142,
0xE0143,
0xE0144,
0xE0145,
0xE0146,
0xE0147,
0xE0148,
0xE0149,
0xE014A,
0xE014B,
0xE014C,
0xE014D,
0xE014E,
0xE014F,
0xE0150,
0xE0151,
0xE0152,
0xE0153,
0xE0154,
0xE0155,
0xE0156,
0xE0157,
0xE0158,
0xE0159,
0xE015A,
0xE015B,
0xE015C,
0xE015D,
0xE015E,
0xE015F,
0xE0160,
0xE0161,
0xE0162,
0xE0163,
0xE0164,
0xE0165,
0xE0166,
0xE0167,
0xE0168,
0xE0169,
0xE016A,
0xE016B,
0xE016C,
0xE016D,
0xE016E,
0xE016F,
0xE0170,
0xE0171,
0xE0172,
0xE0173,
0xE0174,
0xE0175,
0xE0176,
0xE0177,
0xE0178,
0xE0179,
0xE017A,
0xE017B,
0xE017C,
0xE017D,
0xE017E,
0xE017F,
0xE0180,
0xE0181,
0xE0182,
0xE0183,
0xE0184,
0xE0185,
0xE0186,
0xE0187,
0xE0188,
0xE0189,
0xE018A,
0xE018B,
0xE018C,
0xE018D,
0xE018E,
0xE018F,
0xE0190,
0xE0191,
0xE0192,
0xE0193,
0xE0194,
0xE0195,
0xE0196,
0xE0197,
0xE0198,
0xE0199,
0xE019A,
0xE019B,
0xE019C,
0xE019D,
0xE019E,
0xE019F,
0xE01A0,
0xE01A1,
0xE01A2,
0xE01A3,
0xE01A4,
0xE01A5,
0xE01A6,
0xE01A7,
0xE01A8,
0xE01A9,
0xE01AA,
0xE01AB,
0xE01AC,
0xE01AD,
0xE01AE,
0xE01AF,
0xE01B0,
0xE01B1,
0xE01B2,
0xE01B3,
0xE01B4,
0xE01B5,
0xE01B6,
0xE01B7,
0xE01B8,
0xE01B9,
0xE01BA,
0xE01BB,
0xE01BC,
0xE01BD,
0xE01BE,
0xE01BF,
0xE01C0,
0xE01C1,
0xE01C2,
0xE01C3,
0xE01C4,
0xE01C5,
0xE01C6,
0xE01C7,
0xE01C8,
0xE01C9,
0xE01CA,
0xE01CB,
0xE01CC,
0xE01CD,
0xE01CE,
0xE01CF,
0xE01D0,
0xE01D1,
0xE01D2,
0xE01D3,
0xE01D4,
0xE01D5,
0xE01D6,
0xE01D7,
0xE01D8,
0xE01D9,
0xE01DA,
0xE01DB,
0xE01DC,
0xE01DD,
0xE01DE,
0xE01DF,
0xE01E0,
0xE01E1,
0xE01E2,
0xE01E3,
0xE01E4,
0xE01E5,
0xE01E6,
0xE01E7,
0xE01E8,
0xE01E9,
0xE01EA,
0xE01EB,
0xE01EC,
0xE01ED,
0xE01EE,
0xE01EF,
};

View file

@ -0,0 +1,31 @@
#include "libc/nexgen32e/kompressor.h"
#include "third_party/python/Modules/unicodedata.h"
/* clang-format off */
/* GENERATED BY third_party/python/Tools/unicode/makeunicodedata.py 3.2 */
const char _PyUnicode_BidirectionalNames[24][4] = {
"",
"L",
"LRE",
"LRO",
"R",
"AL",
"RLE",
"RLO",
"PDF",
"EN",
"ES",
"ET",
"AN",
"CS",
"NSM",
"BN",
"B",
"S",
"WS",
"ON",
"LRI",
"RLI",
"FSI",
"PDI",
};

View file

@ -0,0 +1,38 @@
#include "libc/nexgen32e/kompressor.h"
#include "third_party/python/Modules/unicodedata.h"
/* clang-format off */
/* GENERATED BY third_party/python/Tools/unicode/makeunicodedata.py 3.2 */
const char _PyUnicode_CategoryNames[31][3] = {
"Cn",
"Lu",
"Ll",
"Lt",
"Mn",
"Mc",
"Me",
"Nd",
"Nl",
"No",
"Zs",
"Zl",
"Zp",
"Cc",
"Cf",
"Cs",
"Co",
"Cn",
"Lm",
"Lo",
"Pc",
"Pd",
"Ps",
"Pe",
"Pi",
"Pf",
"Po",
"Sm",
"Sc",
"Sk",
"So",
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,24 @@
#include "libc/nexgen32e/kompressor.h"
#include "third_party/python/Modules/unicodedata.h"
/* clang-format off */
/* GENERATED BY third_party/python/Tools/unicode/makeunicodedata.py 3.2 */
const char *const _PyUnicode_DecompPrefix[17] = {
"",
"<noBreak>",
"<compat>",
"<super>",
"<fraction>",
"<sub>",
"<font>",
"<circle>",
"<wide>",
"<vertical>",
"<square>",
"<isolated>",
"<final>",
"<initial>",
"<medial>",
"<small>",
"<narrow>",
};

View file

@ -0,0 +1,13 @@
#include "libc/nexgen32e/kompressor.h"
#include "third_party/python/Modules/unicodedata.h"
/* clang-format off */
/* GENERATED BY third_party/python/Tools/unicode/makeunicodedata.py 3.2 */
const char _PyUnicode_EastAsianWidthNames[6][3] = {
"F",
"H",
"W",
"Na",
"A",
"N",
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "third_party/python/Modules/unicodedata.h"
/* clang-format off */
int
_PyUnicode_FindNfcIndex(const _PyUnicode_Reindex *nfc, Py_UCS4 code)
{
unsigned int index;
for (index = 0; nfc[index].start; index++) {
unsigned int start = nfc[index].start;
if (code < start)
return -1;
if (code <= start + nfc[index].count) {
unsigned int delta = code - start;
return nfc[index].index + delta;
}
}
return -1;
}

View file

@ -0,0 +1,285 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "libc/fmt/fmt.h"
#include "third_party/python/Include/pyctype.h"
#include "third_party/python/Include/pyerrors.h"
#include "third_party/python/Include/pymacro.h"
#include "third_party/python/Include/pymem.h"
#include "third_party/python/Modules/unicodedata.h"
#include "third_party/python/Modules/unicodedata_unidata.h"
/* clang-format off */
/* macros used to determine if the given code point is in the PUA range that
* we are using to store aliases and named sequences */
#define IS_ALIAS(cp) ((cp >= _PyUnicode_AliasesStart) && \
(cp < _PyUnicode_AliasesEnd))
#define IS_NAMED_SEQ(cp) ((cp >= _PyUnicode_NamedSequencesStart) && \
(cp < _PyUnicode_NamedSequencesEnd))
static const char * const kHangulSyllables[][3] = {
{ "G", "A", "" },
{ "GG", "AE", "G" },
{ "N", "YA", "GG" },
{ "D", "YAE", "GS" },
{ "DD", "EO", "N", },
{ "R", "E", "NJ" },
{ "M", "YEO", "NH" },
{ "B", "YE", "D" },
{ "BB", "O", "L" },
{ "S", "WA", "LG" },
{ "SS", "WAE", "LM" },
{ "", "OE", "LB" },
{ "J", "YO", "LS" },
{ "JJ", "U", "LT" },
{ "C", "WEO", "LP" },
{ "K", "WE", "LH" },
{ "T", "WI", "M" },
{ "P", "YU", "B" },
{ "H", "EU", "BS" },
{ 0, "YI", "S" },
{ 0, "I", "SS" },
{ 0, 0, "NG" },
{ 0, 0, "J" },
{ 0, 0, "C" },
{ 0, 0, "K" },
{ 0, 0, "T" },
{ 0, 0, "P" },
{ 0, 0, "H" }
};
void
_PyUnicode_FindSyllable(const char *str, int *len, int *pos,
int count, int column)
{
int i, len1;
*len = -1;
for (i = 0; i < count; i++) {
const char *s = kHangulSyllables[i][column];
len1 = Py_SAFE_DOWNCAST(strlen(s), size_t, int);
if (len1 <= *len)
continue;
if (strncmp(str, s, len1) == 0) {
*len = len1;
*pos = i;
}
}
if (*len == -1) {
*len = 0;
}
}
static unsigned long
_gethash(const char *s, int len, int scale)
{
int i;
unsigned long h = 0;
unsigned long ix;
for (i = 0; i < len; i++) {
h = (h * scale) + (unsigned char) Py_TOUPPER(Py_CHARMASK(s[i]));
ix = h & 0xff000000;
if (ix)
h = (h ^ ((ix>>24) & 0xff)) & 0x00ffffff;
}
return h;
}
static int
_cmpname(PyObject *self, int code, const char* name, int namelen)
{
/* check if code corresponds to the given name */
int i;
char buffer[UNIDATA_NAME_MAXLEN+1];
if (!_PyUnicode_GetUcName(self, code, buffer, UNIDATA_NAME_MAXLEN, 1))
return 0;
for (i = 0; i < namelen; i++) {
if (Py_TOUPPER(Py_CHARMASK(name[i])) != buffer[i])
return 0;
}
return buffer[namelen] == '\0';
}
static int
_check_alias_and_seq(unsigned int cp, Py_UCS4* code, int with_named_seq)
{
/* check if named sequences are allowed */
if (!with_named_seq && IS_NAMED_SEQ(cp))
return 0;
/* if the code point is in the PUA range that we use for aliases,
* convert it to obtain the right code point */
if (IS_ALIAS(cp))
*code = _PyUnicode_NameAliases[cp - _PyUnicode_AliasesStart];
else
*code = cp;
return 1;
}
int
_PyUnicode_GetCode(PyObject *self, const char *name, int namelen, Py_UCS4 *code,
int with_named_seq)
{
/* Return the code point associated with the given name.
* Named aliases are resolved too (unless self != NULL (i.e. we are using
* 3.2.0)). If with_named_seq is 1, returns the PUA code point that we are
* using for the named sequence, and the caller must then convert it. */
unsigned int h, v;
unsigned int mask = _PyUnicode_CodeSize - 1;
unsigned int i, incr;
/* Check for hangul syllables. */
if (strncmp(name, "HANGUL SYLLABLE ", 16) == 0) {
int len, L = -1, V = -1, T = -1;
const char *pos = name + 16;
_PyUnicode_FindSyllable(pos, &len, &L, _Hanghoul_LCount, 0);
pos += len;
_PyUnicode_FindSyllable(pos, &len, &V, _Hanghoul_VCount, 1);
pos += len;
_PyUnicode_FindSyllable(pos, &len, &T, _Hanghoul_TCount, 2);
pos += len;
if (L != -1 && V != -1 && T != -1 && pos-name == namelen) {
*code = _Hanghoul_SBase + (L * _Hanghoul_VCount+V) * _Hanghoul_TCount + T;
return 1;
}
/* Otherwise, it's an illegal syllable name. */
return 0;
}
/* Check for unified ideographs. */
if (strncmp(name, "CJK UNIFIED IDEOGRAPH-", 22) == 0) {
/* Four or five hexdigits must follow. */
v = 0;
name += 22;
namelen -= 22;
if (namelen != 4 && namelen != 5)
return 0;
while (namelen--) {
v *= 16;
if (*name >= '0' && *name <= '9')
v += *name - '0';
else if (*name >= 'A' && *name <= 'F')
v += *name - 'A' + 10;
else
return 0;
name++;
}
if (!_PyUnicode_IsUnifiedIdeograph(v))
return 0;
*code = v;
return 1;
}
/* the following is the same as python's dictionary lookup, with
only minor changes. see the makeunicodedata script for more
details */
h = (unsigned int)_gethash(name, namelen, _PyUnicode_CodeMagic);
i = ~h & mask;
v = _PyUnicode_Bextr(_PyUnicode_CodeHash, i, _PyUnicode_CodeHashBits);
if (!v)
return 0;
if (_cmpname(self, v, name, namelen))
return _check_alias_and_seq(v, code, with_named_seq);
incr = (h ^ (h >> 3)) & mask;
if (!incr)
incr = mask;
for (;;) {
i = (i + incr) & mask;
v = _PyUnicode_Bextr(_PyUnicode_CodeHash, i, _PyUnicode_CodeHashBits);
if (!v)
return 0;
if (_cmpname(self, v, name, namelen))
return _check_alias_and_seq(v, code, with_named_seq);
incr = incr << 1;
if (incr > mask)
incr = incr ^ _PyUnicode_CodePoly;
}
}
int
_PyUnicode_GetUcName(PyObject *self, Py_UCS4 code, char *buffer, int buflen,
int with_alias_and_seq)
{
/* Find the name associated with the given code point.
* If with_alias_and_seq is 1, check for names in the Private Use Area 15
* that we are using for aliases and named sequences. */
char *p;
unsigned char *w;
int i, word, offset;
if (code >= 0x110000)
return 0;
/* XXX should we just skip all the code points in the PUAs here? */
if (!with_alias_and_seq && (IS_ALIAS(code) || IS_NAMED_SEQ(code)))
return 0;
if (self && UCD_Check(self)) {
/* in 3.2.0 there are no aliases and named sequences */
const _PyUnicode_ChangeRecord *old;
if (IS_ALIAS(code) || IS_NAMED_SEQ(code))
return 0;
old = get_old_record(self, code);
if (!old->category_changed) {
/* unassigned */
return 0;
}
}
if (_Hanghoul_SBase <= code && code < _Hanghoul_SBase + _Hanghoul_SCount) {
/* Hangul syllable. */
int SIndex = code - _Hanghoul_SBase;
int L = SIndex / _Hanghoul_NCount;
int V = (SIndex % _Hanghoul_NCount) / _Hanghoul_TCount;
int T = SIndex % _Hanghoul_TCount;
if (buflen < 27)
/* Worst case: HANGUL SYLLABLE <10chars>. */
return 0;
p = buffer;
p = stpcpy(p, "HANGUL SYLLABLE ");
p = stpcpy(p, kHangulSyllables[L][0]);
p = stpcpy(p, kHangulSyllables[V][1]);
p = stpcpy(p, kHangulSyllables[T][2]);
*p = 0;
return 1;
}
if (_PyUnicode_IsUnifiedIdeograph(code)) {
if (buflen < 28)
/* Worst case: CJK UNIFIED IDEOGRAPH-20000 */
return 0;
sprintf(buffer, "CJK UNIFIED IDEOGRAPH-%X", code);
return 1;
}
/* get offset into phrasebook */
offset = _PyUnicode_PhrasebookOffset1[(code>>_PyUnicode_PhrasebookShift)];
offset = _PyUnicode_Bextr(_PyUnicode_PhrasebookOffset2,
(offset << _PyUnicode_PhrasebookShift) +
(code & ((1 << _PyUnicode_PhrasebookShift) - 1)),
_PyUnicode_PhrasebookOffset2Bits);
if (!offset)
return 0;
i = 0;
for (;;) {
/* get word index */
word = _PyUnicode_Phrasebook[offset] - _PyUnicode_PhrasebookShort;
if (word >= 0) {
word = (word << 8) + _PyUnicode_Phrasebook[offset+1];
offset += 2;
} else
word = _PyUnicode_Phrasebook[offset++];
if (i) {
if (i > buflen)
return 0; /* buffer overflow */
buffer[i++] = ' ';
}
/* copy word string from lexicon. the last character in the
word has bit 7 set. the last word in a string ends with
0x80 */
w = _PyUnicode_Lexicon + _PyUnicode_LexiconOffset[word];
while (*w < 128) {
if (i >= buflen)
return 0; /* buffer overflow */
buffer[i++] = *w++;
}
if (i >= buflen)
return 0; /* buffer overflow */
buffer[i++] = *w & 127;
if (*w == 128)
break; /* end of word */
}
return 1;
}

View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "third_party/python/Modules/unicodedata.h"
#include "third_party/python/Modules/unicodedata_unidata.h"
/* clang-format off */
void
_PyUnicode_GetDecompRecord(PyObject *self,
Py_UCS4 code,
int *index,
int *prefix,
int *count)
{
unsigned decomp;
if (code >= 0x110000) {
*index = 0;
} else if (self && UCD_Check(self) &&
get_old_record(self, code)->category_changed==0) {
/* unassigned in old version */
*index = 0;
}
else {
*index = _PyUnicode_DecompIndex1[(code>>_PyUnicode_DecompShift)];
*index = _PyUnicode_DecompIndex2[(*index<<_PyUnicode_DecompShift)+
(code&((1<<_PyUnicode_DecompShift)-1))];
}
/* high byte is number of hex bytes (usually one or two), low byte
is prefix code (from*/
decomp = _PyUnicode_Bextr(_PyUnicode_Decomp, *index, _PyUnicode_DecompBits);
*count = decomp >> 8;
*prefix = decomp & 255;
(*index)++;
}

View file

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi
Python 3
https://docs.python.org/3/license.html │
*/
#include "third_party/python/Include/object.h"
#include "third_party/python/Modules/unicodedata.h"
#include "third_party/python/Modules/unicodedata_unidata.h"
/* clang-format off */
const _PyUnicode_Record *
_PyUnicode_GetRecord(Py_UCS4 c)
{
int k, i;
if (c >= 0x110000) {
i = 0;
} else {
k = _PyUnicode_RecordsShift;
i = _PyUnicode_RecordsIndex1[(c >> k)];
i = _PyUnicode_RecordsIndex2[(i << k) + (c & ((1 << k) - 1))];
}
return _PyUnicode_Records + i;
}

View file

@ -0,0 +1,26 @@
#include "libc/nexgen32e/kompressor.h"
#include "third_party/python/Modules/unicodedata.h"
/* clang-format off */
/* GENERATED BY third_party/python/Tools/unicode/makeunicodedata.py 3.2 */
/* Returns 1 for Unicode characters having the line break
* property 'BK', 'CR', 'LF' or 'NL' or having bidirectional
* type 'B', 0 otherwise.
*/
int _PyUnicode_IsLinebreak(Py_UCS4 ch)
{
switch (ch) {
case 0x000A:
case 0x000B:
case 0x000C:
case 0x000D:
case 0x001C:
case 0x001D:
case 0x001E:
case 0x0085:
case 0x2028:
case 0x2029:
return 1;
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show more