465 lines
17 KiB
C
465 lines
17 KiB
C
/****************************************************************************
|
|
|
|
|
| (C) Copyright 2000, 2003 Novell, Inc.
|
|
| All Rights Reserved.
|
|
|
|
|
| This program 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 program 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 program; if not, contact Novell, Inc.
|
|
|
|
|
| To contact Novell about this file by physical or electronic mail,
|
|
| you may find current contact information at www.novell.com
|
|
|
|
|
|***************************************************************************
|
|
|
|
|
| NSS Library
|
|
|
|
|
|---------------------------------------------------------------------------
|
|
|
|
|
| $Author: taysom $
|
|
| $Date: 2004-12-31 01:10:58 +0530 (Fri, 31 Dec 2004) $
|
|
|
|
|
| $RCSfile$
|
|
| $Revision: 465 $
|
|
|
|
|
|---------------------------------------------------------------------------
|
|
| This module is used to:
|
|
| The is used by snprint() under Linux. From LIBC sources.
|
|
+-------------------------------------------------------------------------*/
|
|
|
|
#ifndef _SNPRINTF_H_
|
|
#define _SNPRINTF_H_
|
|
|
|
#include <limits.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
// FixFixFix(__linux__) - this file needs to be cleaned up
|
|
|
|
// Kludge area(start)
|
|
|
|
|
|
//#ifndef __cplusplus /* because these may be done better in C++ */
|
|
//#ifdef min
|
|
//#undef min
|
|
//#endif
|
|
//#ifdef max
|
|
//#undef max
|
|
//#endif
|
|
//# define max(a, b) (((a) > (b)) ? (a) : (b))
|
|
//# define min(a, b) (((a) < (b)) ? (a) : (b))
|
|
//# define inrange(lo, x, hi) ((x) >= (lo) && (x) <= (hi))
|
|
// int (max)( int a, int b );
|
|
// int (min)( int a, int b );
|
|
//#endif
|
|
|
|
#ifndef EOF
|
|
#define EOF -1
|
|
#endif
|
|
|
|
#ifdef __linux__
|
|
#define IS_DOUBLE_BYTE(p) (FALSE)
|
|
|
|
// useful for code that is compiled in both char and wchar contexts
|
|
#define ISDIGIT(c) ('0' <= (c) && (c) <= '9')
|
|
#define ISSPACE(c) (' ' == (c) || (0x09 <= (c) && (c) <= 0x0D))
|
|
|
|
#ifndef LLONG_MIN
|
|
# define LLONG_MIN (I64_CONST(-9223372036854775807)-1)/* max value of 'long long' */
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#define _IOWRT 0x00000002 // currently writing ("w")
|
|
#define _IOISASTR 0x00080000 // this is a temp 'string' file (ea. sscanf())
|
|
#define _IOISABNDSTR 0x00100000 // this is a bounded 'string' file, snprintf()
|
|
|
|
///* exact-width signed types... */
|
|
//#ifndef __linux__
|
|
//typedef signed char int8_t;
|
|
//typedef short int int16_t;
|
|
//typedef long int int32_t;
|
|
//typedef SQUAD int64_t;
|
|
//
|
|
///* exact-width unsigned types... */
|
|
//typedef unsigned char uint8_t;
|
|
//typedef unsigned short int uint16_t;
|
|
//typedef unsigned long int uint32_t;
|
|
//typedef QUAD uint64_t;
|
|
//#endif
|
|
|
|
//typedef long ssize_t; /* buffer size plus return codes */
|
|
|
|
#define LIB_LDBL_MANT_DIG 64
|
|
#define LIB_LDBL_DIG 18
|
|
#define LIB_LDBL_MIN_EXP (-16381)
|
|
#define LIB_LDBL_MIN_10_EXP (-4931)
|
|
#define LIB_LDBL_MAX_EXP (+16384)
|
|
#define LIB_LDBL_MAX_10_EXP (+4932)
|
|
|
|
#define LDBL_MANT_DIG LIB_LDBL_MANT_DIG
|
|
#define LDBL_DIG LIB_LDBL_DIG
|
|
#define LDBL_MIN_EXP LIB_LDBL_MIN_EXP
|
|
#define LDBL_MIN_10_EXP LIB_LDBL_MIN_10_EXP
|
|
#define LDBL_MAX_EXP LIB_LDBL_MAX_EXP
|
|
#define LDBL_MAX_10_EXP LIB_LDBL_MAX_10_EXP
|
|
#define LDBL_MAX LIB_LDBL_MAX
|
|
#define LDBL_EPSILON LIB_LDBL_EPSILON
|
|
#define LDBL_MIN LIB_LDBL_MIN
|
|
// Kludge area (end)
|
|
|
|
|
|
|
|
//#include <defs.h>
|
|
//#include <locdata.h>
|
|
//#include <libfloat.h>
|
|
|
|
#ifdef WIDE
|
|
# define CHAR wchar_t // wide character print engine
|
|
# define UCHAR wuchar_t
|
|
#else
|
|
# define CHAR char // multibyte print engine
|
|
# define UCHAR unsigned char
|
|
#endif
|
|
|
|
// 'flags' values for how numbers and strings behave...
|
|
#define ffUNDEF 0x00000000 // right-justify, normal size
|
|
#define ffZERO 0x00000001 // zero-pad
|
|
#define ffDOT 0x00000002 // same as zero-pad for now
|
|
#define ffPLUS 0x00000004 // prepend sign
|
|
#define ffMINUS 0x00000008 // left-justify
|
|
#define ffHALF 0x00000010 // word arg (16 bits) %h
|
|
#define ffHALF_HALF 0x00000020 // byte arg (8 bits) %hh
|
|
#define ffLONG 0x00000040 // long arg (32 bits) %l
|
|
#define ffLONG_LONG 0x00000080 // long long/intmax_t arg (64 bits) %ll, %j
|
|
#define ffLONG_DOUBLE 0x00000100 // long double arg (unsupported)
|
|
#define ffUINT 0x00000200 // unsigned int
|
|
#define ffPTRDIFF 0x00000400 // ptrdiff_t arg (signed 32 bits) %t
|
|
#define ffVPTR 0x00000800 // pointer
|
|
#define ffPOUND 0x00001000 // convert to alternate form (unsupported)
|
|
#define ffSPACE 0x00002000 // space-pad string
|
|
#define ffQUOTE 0x00004000 // enable numeric grouping (3,000 not 3000)
|
|
#define ffCAPS 0x00008000 // upper-case equivalent of another pronoun
|
|
#define ffEOF 0x00010000 // reached end of FILE or string (scan only)
|
|
#define ffSTAR 0x00020000 // '*'
|
|
#define ffSIGN 0x00040000 // floating point sign
|
|
#define ffALLOC 0x00100000 // indicates a temporary allocation
|
|
#define ffDASH 0x00200000 //
|
|
#define ffAFTER 0x00400000 //
|
|
#define ffBEFORE 0x00800000 //
|
|
#define ffBLANK 0x01000000 //
|
|
#define ffSHARP 0x02000000 //
|
|
|
|
#define _ULTOS(p, v) do { *--(p) = (v) % 10 + '0'; } while ((v) /= 10)
|
|
#define _ULLTOS(p, v) do { *--(p) = (v) % 10 + '0'; } while ((v) /= 10)
|
|
//#define _ULLTOS(p, v) do { *--(p) = do_div(v, 10) + '0'; } while ( (v) )
|
|
|
|
/*
|
|
** Based on the conversion specifier in 'ch,' this determines the radix to be
|
|
** used in performing a numeric to string conversion.
|
|
*/
|
|
#define GET_RADIX(ch) \
|
|
(((ch) == 'x' || (ch) == 'X') \
|
|
? 16 \
|
|
: ((ch) == 'o') \
|
|
? 8 \
|
|
: ((ch) == 'b') \
|
|
? 2 \
|
|
: 10)
|
|
|
|
/*
|
|
** These upper bounds must be big enough, but need not be exact.
|
|
** Floating-specific values are checked when convert.c is compiled.
|
|
**
|
|
** NDIG_DEC - maximum decimal digits producable by convert_float()
|
|
** NDIG_HEX - maximum hexadecimal digits producable by convert_float()
|
|
** NDIG_EXP - maximum bytes for decimal exponents (e+d*d)
|
|
**
|
|
** NDIG_A_FMT - maximum bytes for %a (-0xh.h*hp+d*d)
|
|
** NDIG_E_FMT - maximum bytes for %e (-d.d*de+d*d)
|
|
** NDIG_F_FMT - maximum bytes for %f (-d*d.d*d)
|
|
**
|
|
** NDIG_INT - maximum bytes for integer formats (0b%b)
|
|
**
|
|
** NDIG_FMT - maximum bytes of the NDIG_?_FMT formats
|
|
** NDIG_MAX - maximum bytes of all the the numeric formats
|
|
*/
|
|
#define NDIG_DEC (2 + LDBL_DIG + 2)
|
|
#define NDIG_HEX ((LDBL_MANT_DIG + 3) / 4)
|
|
#define NDIG_EXP (2 + 6)
|
|
#define NDIG_A_FMT (1 + 2 + 1 + NDIG_HEX + NDIG_EXP + 1)
|
|
#define NDIG_E_FMT (1 + 1 + NDIG_DEC + NDIG_EXP)
|
|
#define NDIG_F_FMT (1 + 1 + NDIG_DEC)
|
|
#define NDIG_FMT (NDIG_A_FMT > NDIG_E_FMT ? NDIG_A_FMT : NDIG_E_FMT)
|
|
#define NDIG_INT (2 + sizeof(uint64_t) * CHAR_BIT)
|
|
#define NDIG_MAX (NDIG_INT > NDIG_FMT ? NDIG_INT : NDIG_FMT)
|
|
|
|
#define CVT_INF 0 // decimal point for Infinity
|
|
#define CVT_NAN 1 // decimal point for NaN
|
|
|
|
#define CVT_CAPS 0x1 // capitalized version of these modes
|
|
#define CVT_A 0x2
|
|
#define CVT_E 0x4
|
|
#define CVT_F 0x8
|
|
|
|
|
|
#ifdef DO_FLOATING_POINT
|
|
typedef struct // holds incoming and outgoing information...
|
|
{ // ...for convert_float()
|
|
UCHAR *buf; // generate digits in here
|
|
int ndigits; // precision/number of digits
|
|
int mode; // conversion mode
|
|
int decimal; // exponent (offset to decimal point)
|
|
int sign; // 0:nonnegative; 1:negative
|
|
int len; // length of returned string
|
|
union // incoming floating value
|
|
{
|
|
_dval dval;
|
|
_ldval ldval;
|
|
} val;
|
|
} float_cvt_t;
|
|
#endif
|
|
|
|
typedef enum // all the various types that can be given to va_arg()
|
|
{
|
|
T_INT, // default
|
|
T_LONG,
|
|
T_DBL,
|
|
T_LDBL,
|
|
T_VPTR,
|
|
T_CPTR,
|
|
T_SPTR,
|
|
T_IPTR,
|
|
T_LPTR,
|
|
T_FPTR,
|
|
T_DPTR,
|
|
T_LDPTR,
|
|
T_PPTR,
|
|
T_LLONG,
|
|
T_LLPTR
|
|
} ArgType;
|
|
|
|
typedef union
|
|
{
|
|
ArgType type; // used by _parglist()
|
|
va_list ap; // used for passing to va_arg()
|
|
} va_list_U;
|
|
|
|
typedef struct // holds incoming and outgoing information for _cvt's
|
|
{
|
|
unsigned char *buf; // generate digits in here
|
|
int ndig; // precision/number of digits
|
|
int mode; // conversion mode
|
|
int decpt; // exponent (offset to decimal point)
|
|
int sign; // 0:nonnegative; 1:negative
|
|
int len; // length of returned string
|
|
#ifdef DO_FLOATING_POINT
|
|
union // incoming floating value
|
|
{
|
|
_dval dval;
|
|
_ldval ldval;
|
|
} val;
|
|
#endif
|
|
} Cvt;
|
|
|
|
extern const char g_str_uc_hex[]; // "0123456789ABCDEF"
|
|
extern const char g_str_lc_hex[]; // "0123456789abcdef"
|
|
extern const char g_str_mixed_nan[];// "NaN"
|
|
extern const char g_str_uc_nan[]; // "NAN"
|
|
extern const char g_str_lc_nan[]; // "nan"
|
|
extern const char g_str_mixed_inf[];// "Infinity"
|
|
extern const char g_str_uc_inf[]; // "INFINITY"
|
|
extern const char g_str_lc_inf[]; // "infinity"
|
|
|
|
|
|
// prototypes...
|
|
#ifdef DO_FLOATING_POINT
|
|
UCHAR *convert_float( float_cvt_t *, const char *, const char * );
|
|
#endif
|
|
|
|
void _parglist(const CHAR *fmt, va_list_U *arglist, int len, int pos, int scan);
|
|
|
|
unsigned char *_cvt( Cvt *, const char *nanStr, const char *infStr );
|
|
unsigned char *_cvtl( register Cvt *cp, const char *nanStr, const char *infStr );
|
|
|
|
int __cputs ( const char *string );
|
|
|
|
|
|
//#if 0
|
|
//// Macro used by both the print and scan engines to set the locale when needed
|
|
//#define SETLOC(vm, loc) \
|
|
//{ \
|
|
// if (!loc) /* Get a locale if we don't have one */ \
|
|
// { \
|
|
// if (!vm) /* Get the context if we don't have it */ \
|
|
// { \
|
|
// if (vm = _get_vm(0)) \
|
|
// { \
|
|
// loc = &vm->localeconv; \
|
|
// if (!loc->name[0]) \
|
|
// loc = &g_default_locale; \
|
|
// } \
|
|
// else \
|
|
// { \
|
|
// loc = &g_default_locale; \
|
|
// } \
|
|
// } \
|
|
// else if (!vm->localeconv.name[0]) \
|
|
// { \
|
|
// loc = &g_default_locale; \
|
|
// } \
|
|
// else \
|
|
// { \
|
|
// loc = &vm->localeconv; \
|
|
// } \
|
|
// } \
|
|
//}
|
|
//#endif
|
|
|
|
|
|
|
|
|
|
//#include <pshpack1.h>
|
|
|
|
|
|
|
|
struct lconv /* for the current locale... */
|
|
{
|
|
int country; /* internal representations... */
|
|
int language; /* ibid */
|
|
char name[8]; /* as returned from setlocale(LC_ALL, NULL) */
|
|
/* -------------------------- [Numeric Conventions] --------------------- */
|
|
char decimal_point[4]; /* decimal point */
|
|
char thousands_sep[4]; /* separator for digits left of decimal */
|
|
char grouping[4]; /* digit grouping size */
|
|
/* -------------------------- [Monetary Conventions] -------------------- */
|
|
char currency_symbol[4]; /* currency symbol */
|
|
char mon_decimal_point[4]; /* decimal point */
|
|
char mon_thousands_sep[4]; /* separator for digits left of decimal */
|
|
char mon_grouping[8]; /* digit grouping sizes */
|
|
char positive_sign[4]; /* string indicating positive quantities */
|
|
char negative_sign[4]; /* string indicating negative quantities */
|
|
char frac_digits; /* count of digits right of decimal */
|
|
/* for positive monetary quantities: */
|
|
char p_cs_precedes; /* currency symbol precedes quantity */
|
|
char p_sep_by_space; /* currency symbol separated by blank */
|
|
char p_sign_posn; /* position of positive symbol */
|
|
/* for negative monetary quantities: */
|
|
char n_cs_precedes; /* currency symbol precedes quantity */
|
|
char n_sep_by_space; /* currency symbol separated by blank */
|
|
char n_sign_posn; /* position of negative symbol */
|
|
char reserved; /* (reserved for future use) */
|
|
/* -------------------------- [International Monetary Conventions] ------ */
|
|
char int_curr_symbol[15]; /* international currency symbol and separator */
|
|
char int_frac_digits; /* (international) digits right of decimal */
|
|
/* -------------------------- [Time and Date Conventions] --------------- */
|
|
int always_24; /* always enforce 24-hour display (Boolean) */
|
|
char hour_sep[4]; /* hour and seconds separator */
|
|
char hour_sans_sec_sep[4]; /* hour separator when no seconds displayed */
|
|
char date_sep[4]; /* month/day/year separator */
|
|
char time_fmt[16]; /* hours:minutes:seconds format (hh:mm:ss) */
|
|
char date_fmt[16]; /* month/day/year format (mm/dd/yyyy) */
|
|
char full_date_fmt[32]; /* weekday, month, day and year format */
|
|
char ampm[32]; /* delimited string indicating am and pm */
|
|
char AMPM[32]; /* delimited string indicating AM and PM */
|
|
char days[160]; /* delimited string of day names */
|
|
char day_abbrevs[160]; /* delimited string of abbreviated day names */
|
|
char months[160]; /* delimited string of month names */
|
|
char month_abbrevs[160]; /* delimited string of abbreviated month names */
|
|
}; /* sizeof(struct lconv) == 0x360 (864.) */
|
|
|
|
//#include <poppack.h>
|
|
|
|
#define _qcpy(d,s,n) (void *) ((char *) memcpy(d, s, n) + (n))
|
|
|
|
// Macro used by both the print and scan engines to set the locale when needed
|
|
#define SET_LOC(loc) \
|
|
{ \
|
|
if (!loc) /* Get a locale if we don't have one */ \
|
|
{ \
|
|
loc = &g_default_locale; \
|
|
} \
|
|
}
|
|
|
|
//#include "convert.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// F I L E ( S t r e a m ) S t r u c t u r e
|
|
//-----------------------------------------------------------------------------
|
|
typedef struct _iob // ANSI FILE_t stream structure
|
|
{ // this is no longer publicly-exposed
|
|
// struct _iob *next; // the next open FILE_t
|
|
// unsigned long signature; // 'StdF'--identifies this structure
|
|
//# define kOpenStdioSig 'StdF' // --when valid and in use
|
|
//# define kClosedStdioSig '----' // --when on free list
|
|
// void *ofs; // pointer to base of OpenFileStructure
|
|
// unsigned long state; // state of stream, errors, etc.
|
|
//-0x10------------------------------------------------------------------------
|
|
// size_t bufsize; // size of buffer
|
|
int avail; // available (unused/unread) room in buffer
|
|
unsigned char *begptr; // start of buffer
|
|
unsigned char *endptr; // end of buffer
|
|
//-0x20------------------------------------------------------------------------
|
|
unsigned char *ptr; // next character from/to here in buffer
|
|
// unsigned char buf[4]; // fake, micro buffer as a fall-back
|
|
// int fildes; // underlying file descriptor
|
|
// size_t nl_count; // count of '\r\n' sequences in the buffer
|
|
//-0x30------------------------------------------------------------------------
|
|
// size_t begpos; // real position in file of the buffer start
|
|
// size_t eofpos; // real position in file of the buffer end
|
|
// thr_t *owner; // owner of this lock
|
|
// void *lock; // for protected operations
|
|
//-0x40------------------------------------------------------------------------
|
|
// char *tmpfile_name; // allocated/deallocated by tmpfile() et al.
|
|
// pid_t popened_child; // on which pclose() will NXVmJoin()...
|
|
// int *paddington[2];
|
|
} FILE_t;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct // used by doprint.c and nwprint.c
|
|
{ // locals shared between _i[w[s]]doprint and other functions
|
|
FILE_t *fp; // the stream; strings provide fake one
|
|
unsigned char *curptr; // output placed here
|
|
unsigned char *beg; // start of main generated bytes
|
|
unsigned char *end; // one past main generated bytes
|
|
UCHAR *radix; // points at radix, if appropriate
|
|
const UCHAR *prefix; // bytes before main generated ones
|
|
const unsigned char *suffix; // bytes after main generated ones
|
|
const unsigned char *grp; // location in grouping string
|
|
size_t nprefix; // length of prefix (none if 0)
|
|
size_t nsuffix; // length of suffix (none if 0)
|
|
size_t nsuf0; // length of zero-padding for suffix
|
|
size_t nleft0; // number of zeros before main bytes
|
|
size_t nright0; // number of zeros after main bytes
|
|
size_t width; // minimum conversion length
|
|
size_t prec; // precision, valid iff F_DOT
|
|
unsigned long flags; // status about current conversion
|
|
int roomleft; // space left before flush
|
|
int total; // total generated bytes/characters
|
|
int ngrp; // number of digits in current group
|
|
UCHAR buf[NDIG_MAX]; // space for main generated bytes
|
|
UCHAR suf[NDIG_MAX]; // variable suffixes built here
|
|
} PStream;
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|