<commit_before>/********************************************************************
* Description: vsnprintf.h
*   Implementation of vsnprintf for kernel space.
*
*   Derived from the Linux 2.4.18 kernel  (linux/lib/vsprintf.c)
*
* License: GPL Version 2
* System: Linux
*    
* Copyright (c) 2004 All rights reserved.
*
* Last change:
********************************************************************/
/** vsnprintf.h

This file implements a vsnprintf for use in kernel space.  It is
shamelessly stolen from the 2.4.18 kernel's linux/lib/vsprintf.c
It is used when compiling rtapi for 2.2 kernels that don't have
vsnprintf, only vsprintf.  To avoid difficulties with 64 bit
math, we take the simple approach - we don't support longlong
values (or floating point).
*/

/* This is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License
   as published by the Free Software Foundation.  This code is
   distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY 
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.

   You should have received a copy of the GNU General Public License
   along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111 USA
*/

#include <stdarg.h>
#include <stddef.h>
#include <rtapi_ctype.h>
#include <rtapi_math.h>
#include <rtapi_string.h>

/* we use this so that we can do without the string library */
static int strn_len(const char *s, int count)
{
    const char *sc;

    for (sc = s; count-- && *sc != '\0'; ++sc);
    return sc - s;
}

static int skip_atoi(const char **s)
{
    int i = 0;

    while (isdigit(**s))
	i = i * 10 + *((*s)++) - '0';
    return i;
}

#define ZEROPAD	1		/* pad with zero */
#define SIGN	2		/* unsigned/signed long */
#define PLUS	4		/* show plus */
#define SPACE	8		/* space if plus */
#define LEFT	16		/* left justified */
#define SPECIAL	32		/* 0x */
#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */

static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

static char *ch(char *buf, char *end, char ch)
{
    if(buf <= end) *buf = ch;
    return buf+1;
}

static char *st(char *buf, char *end, const char *add)
{
    while(*add)
	buf = ch(buf, end, *add++);
    return buf;
}

static char *number(char *buf, char *end, long long numll, int base,
		    int size, int precision, int type)
{
    unsigned long num;
    char c, sign, tmp[66];
    const char *digits;
    int i;

    digits = (type & LARGE) ? large_digits : small_digits;
    if (type & LEFT) {
	type &= ~ZEROPAD;
    }
    if (base < 2 || base > 36) {
	return 0;
    }
    c = (type & ZEROPAD) ? '0' : ' ';
    sign = 0;
    num = (unsigned long) numll;
    if (type & SIGN) {
	if (numll < 0) {
	    sign = '-';
	    num = -numll;
	    size--;
	} else if (type & PLUS) {
	    sign = '+';
	    size--;
	} else if (type & SPACE) {
	    sign = ' ';
	    size--;
	}
    }
    if (type & SPECIAL) {
	if (base == 16) {
	    size -= 2;
	} else if (base == 8) {
	    size--;
	}
    }
    i = 0;
    if (num == 0) {
	tmp[i++] = '0';
    } else
	while (num != 0) {
	    tmp[i++] = digits[num % base];
	    num /= base;
	}
    if (i > precision) {
	precision = i;
    }
    size -= precision;
    if (!(type & (ZEROPAD + LEFT))) {
	while (size-- > 0) buf = ch(buf, end, ' ');
    }
    if (sign) buf = ch(buf, end, sign);
    if (type & SPECIAL) {
	if (base == 8) {
	    buf = ch(buf, end, '0');
	} else if (base == 16) {
	    buf = ch(buf, end, '0');
	    buf = ch(buf, end, digits[33]);
	}
    }
    if (!(type & LEFT)) {
	while (size-- > 0) buf = ch(buf, end, c);
    }
    while (i < precision--) {
	buf = ch(buf, end, '0');
    }
    while (i-- > 0) {
	buf = ch(buf, end, tmp[i]);
    }
    while (size-- > 0) {
	buf = ch(buf, end, ' ');
    }
    return buf;
}

static char *fnumber(char *buf, char *end, double num)
{
    int exp;
    double mantissa = frexp(fabs(num), &exp);
    int i;

    if(signbit(num)) buf = ch(buf, end, '-');
    if(isnan(num)) { buf = st(buf, end, "NaN"); return buf; }
    if(isinf(num)) { buf = st(buf, end, "Inf"); return buf; }

    buf = st(buf, end, "0x");

    /* want one digit to the left of the radix point.  ldexp should return in
     * the range [0.5,1) but guard with an 'if' just in case */
    if(mantissa != 0 && mantissa < 1) { mantissa *= 16; exp -= 4; }

    /* first digit */
    i = (int)floor(mantissa);
    buf = ch(buf, end, large_digits[i]);
    mantissa = 16 * (mantissa - i);

    /* radix point if any fractional digits */
    if(mantissa) { buf = ch(buf, end, '.'); }
    while(mantissa) {
        /* remaning digits, if any */
        i = (int)floor(mantissa);
        buf = ch(buf, end, large_digits[i]);
        mantissa = 16 * (mantissa - i);
    }

    buf = ch(buf, end, 'P');
    buf = number(buf, end, exp, 10, 0, 0, PLUS|SIGN);<commit_msg>rtapi_vsnprintf: integer version of %A for ieee<commit_after>/********************************************************************
* Description: vsnprintf.h
*   Implementation of vsnprintf for kernel space.
*
*   Derived from the Linux 2.4.18 kernel  (linux/lib/vsprintf.c)
*
* License: GPL Version 2
* System: Linux
*    
* Copyright (c) 2004 All rights reserved.
*
* Last change:
********************************************************************/
/** vsnprintf.h

This file implements a vsnprintf for use in kernel space.  It is
shamelessly stolen from the 2.4.18 kernel's linux/lib/vsprintf.c
It is used when compiling rtapi for 2.2 kernels that don't have
vsnprintf, only vsprintf.  To avoid difficulties with 64 bit
math, we take the simple approach - we don't support longlong
values (or floating point).
*/

/* This is free software; you can redistribute it and/or modify it
   under the terms of version 2 of the GNU General Public License
   as published by the Free Software Foundation.  This code is
   distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY 
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.

   You should have received a copy of the GNU General Public License
   along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111 USA
*/

#include <stdarg.h>
#include <stddef.h>
#include <rtapi_ctype.h>
#include <rtapi_math.h>
#include <rtapi_string.h>

/* we use this so that we can do without the string library */
static int strn_len(const char *s, int count)
{
    const char *sc;

    for (sc = s; count-- && *sc != '\0'; ++sc);
    return sc - s;
}

static int skip_atoi(const char **s)
{
    int i = 0;

    while (isdigit(**s))
	i = i * 10 + *((*s)++) - '0';
    return i;
}

#define ZEROPAD	1		/* pad with zero */
#define SIGN	2		/* unsigned/signed long */
#define PLUS	4		/* show plus */
#define SPACE	8		/* space if plus */
#define LEFT	16		/* left justified */
#define SPECIAL	32		/* 0x */
#define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */

static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

static char *ch(char *buf, char *end, char ch)
{
    if(buf <= end) *buf = ch;
    return buf+1;
}

static char *st(char *buf, char *end, const char *add)
{
    while(*add)
	buf = ch(buf, end, *add++);
    return buf;
}

static char *number(char *buf, char *end, long long numll, int base,
		    int size, int precision, int type)
{
    unsigned long num;
    char c, sign, tmp[66];
    const char *digits;
    int i;

    digits = (type & LARGE) ? large_digits : small_digits;
    if (type & LEFT) {
	type &= ~ZEROPAD;
    }
    if (base < 2 || base > 36) {
	return 0;
    }
    c = (type & ZEROPAD) ? '0' : ' ';
    sign = 0;
    num = (unsigned long) numll;
    if (type & SIGN) {
	if (numll < 0) {
	    sign = '-';
	    num = -numll;
	    size--;
	} else if (type & PLUS) {
	    sign = '+';
	    size--;
	} else if (type & SPACE) {
	    sign = ' ';
	    size--;
	}
    }
    if (type & SPECIAL) {
	if (base == 16) {
	    size -= 2;
	} else if (base == 8) {
	    size--;
	}
    }
    i = 0;
    if (num == 0) {
	tmp[i++] = '0';
    } else
	while (num != 0) {
	    tmp[i++] = digits[num % base];
	    num /= base;
	}
    if (i > precision) {
	precision = i;
    }
    size -= precision;
    if (!(type & (ZEROPAD + LEFT))) {
	while (size-- > 0) buf = ch(buf, end, ' ');
    }
    if (sign) buf = ch(buf, end, sign);
    if (type & SPECIAL) {
	if (base == 8) {
	    buf = ch(buf, end, '0');
	} else if (base == 16) {
	    buf = ch(buf, end, '0');
	    buf = ch(buf, end, digits[33]);
	}
    }
    if (!(type & LEFT)) {
	while (size-- > 0) buf = ch(buf, end, c);
    }
    while (i < precision--) {
	buf = ch(buf, end, '0');
    }
    while (i-- > 0) {
	buf = ch(buf, end, tmp[i]);
    }
    while (size-- > 0) {
	buf = ch(buf, end, ' ');
    }
    return buf;
}

#if defined(__i386__) || defined(__amd64__)
#define IS_IEEE754 /// XXX this should ultimately be replaced by a configure test
#endif

#if defined(IS_IEEE754)
static int next_digit(unsigned long long *mantissa)
{
    int result = ((*mantissa) >> 52) & 0xf;
    *mantissa = ((*mantissa) << 4) & ((1ull<<56)-1);
    return result;
}
#endif

static char *fnumber(char *buf, char *end, double num)
{
#if defined(IS_IEEE754)
    union ieee754_double du;
    int exponent, i;
    unsigned long long mantissa;

    du.d = num;

    if(du.ieee.negative) buf = ch(buf, end, '-');

    if(du.ieee.exponent == 0x7ff) {
	// inf or nan	
        if(du.ieee.mantissa0 == 0 && du.ieee.mantissa1 == 0) {
	    buf = st(buf, end, "Inf"); return buf;
	} else {
	    buf = st(buf, end, "NaN"); return buf;
	}
    } else if(du.ieee.exponent == 0) {
	// denormalized or zero
	exponent = du.ieee.exponent - IEEE754_DOUBLE_BIAS;
	mantissa = ((unsigned long long)du.ieee.mantissa0 << 32) + du.ieee.mantissa1;
	if(mantissa == 0) {
	    exponent = 0;
	} else {
	    while(!(mantissa & (1ull<<52))) {
		exponent--;
		mantissa <<= 1;
	    }
	}
    } else {
	// normal
	exponent = du.ieee.exponent - IEEE754_DOUBLE_BIAS;
	mantissa = ((unsigned long long)du.ieee.mantissa0 << 32) + du.ieee.mantissa1 + (1ull<<52);
    }

    buf = st(buf, end, "0x");

    /* first digit */
    i = next_digit(&mantissa);
    buf = ch(buf, end, large_digits[i]);

    if(mantissa) { buf = ch(buf, end, '.'); }
    while(mantissa) {
        /* remaning digits, if any */
        i = next_digit(&mantissa);
        buf = ch(buf, end, large_digits[i]);
    }

    buf = ch(buf, end, 'P');
    buf = number(buf, end, exponent, 10, 0, 0, PLUS|SIGN);
#else
    int exp;
    double mantissa = frexp(fabs(num), &exp);
    int i;

    if(signbit(num)) buf = ch(buf, end, '-');
    if(isnan(num)) { buf = st(buf, end, "NaN"); return buf; }
    if(isinf(num)) { buf = st(buf, end, "Inf"); return buf; }

    buf = st(buf, end, "0x");

    /* want one digit to the left of the radix point.  ldexp should return in
     * the range [0.5,1) but guard with an 'if' just in case */
    if(mantissa != 0 && mantissa < 1) { mantissa *= 16; exp -= 4; }

    /* first digit */
    i = (int)floor(mantissa);
    buf = ch(buf, end, large_digits[i]);
    mantissa = 16 * (mantissa - i);

    /* radix point if any fractional digits */
    if(mantissa) { buf = ch(buf, end, '.'); }
    while(mantissa) {
        /* remaning digits, if any */
        i = (int)floor(mantissa);
        buf = ch(buf, end, large_digits[i]);
        mantissa = 16 * (mantissa - i);
    }

    buf = ch(buf, end, 'P');
    buf = number(buf, end, exp, 10, 0, 0, PLUS|SIGN);
#endif
{'fraction_non_alphanumeric': 0.17314338700160162, 'fraction_numerical': 0.023771390036247154, 'mean_word_length': 2.6617283950617283, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3355733', 'n_tokens_mistral': 4597, 'n_tokens_neox': 4244, 'n_words': 1417}