public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* what is the use of __umoddi3() and __udivdi3() in the function printf()?
@ 2002-08-15 22:20 Samuel
  2002-08-19 10:53 ` Jan Hubicka
  0 siblings, 1 reply; 2+ messages in thread
From: Samuel @ 2002-08-15 22:20 UTC (permalink / raw)
  To: gcc; +Cc: gcc

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3078 bytes --]

Hai,
I tried to create a program which independant of all system and standard libs. When i modified and make the printf function, the linker says missing symbols ___umoddi3 and ___udivdi3. I globaly declared two functions with the name of the above and complied the program, it works fine now. However i want know what is the use of the above symbols, can you tell me what is the use of these functions or variables?
I herewith the attached the modified version of printf.c and the makefile i used. The makefile contains refer other files also.The included header files does not refer any external symbols. However if you require i am ready to send those files also. 
Thanks & Regards,
Sam ( samuelhard@yahoo.com ) Do You Yahoo!?
HotJobs, a Yahoo! service - Search Thousands of New Jobs Attachment:
Printf.c
Description: Printf.c
Kernel	:	Kernel.o CKernel.o Processor.o MemMan.o Heap.o Keyboard.o VGAText.o PIC.o Timer.o VGACursor.o PCI.o PCIEnum.o NumConvert.o Printf.o String.o Boot.bin  OSLoader.bin 
	ld -Ttext 0x19000  --oformat binary -o Kernel.bin Kernel.o CKernel.o Processor.o MemMan.o Heap.o Keyboard.o IO.o VGAText.o VGACursor.o PIC.o Timer.o PCI.o PCIEnum.o NumConvert.o Printf.o modf.o  String.o
Boot.bin:	Boot/Boot.asm
	nasmw -i Includes -w+orphan-labels -o Boot.bin Boot/Boot.asm
OSLoader.bin	:	Boot/OSLoader.asm
	nasmw -i Includes -w+orphan-labels -o OSLoader.bin Boot/OSLoader.asm
Kernel.o	:	Kernel/Kernel.asm
	nasmw -i Includes -w+orphan-labels -f coff -o Kernel.o Kernel/Kernel.asm
CKernel.o	:	Kernel/CKernel.c
	gcc -ffreestanding -c  -I Includes -o CKernel.o Kernel/CKernel.c
Processor.o	:	Kernel/Processor.asm
	nasmw -i Includes -w+orphan-labels -f coff -o Processor.o Kernel/Processor.asm
MemMan.o	:	Kernel/MemMan.asm
	nasmw -i Includes -w+orphan-labels -f coff -o MemMan.o Kernel/MemMan.asm
Heap.o		:	MemMan.o Kernel/Heap.c
	gcc -ffreestanding -c  -I Includes -o Heap.o Kernel/Heap.c
Keyboard.o	:	Kernel/Keyboard.asm
	nasmw -i Includes -w+orphan-labels -f coff -o Keyboard.o Kernel/Keyboard.asm
VGACursor.o	:	IO.o Kernel/VGACursor.c
	gcc -ffreestanding -c  -I Includes -o VGACursor.o Kernel/VGACursor.c
VGAText.o	:	IO.o Kernel/VGAText.asm
	nasmw -i Includes -w+orphan-labels -f coff -o VGAText.o Kernel/VGAText.asm
PIC.o		:	Kernel/PIC.asm
	nasmw -i Includes -w+orphan-labels -f coff -o PIC.o Kernel/PIC.asm
IO.o		:	Kernel/IO.asm
	nasmw -i Includes -w+orphan-labels -f coff -o IO.o Kernel/IO.asm
Timer.o		:	Kernel/Timer.asm
	nasmw -i Includes -w+orphan-labels -f coff -o Timer.o Kernel/Timer.asm
PCI.o		:	IO.o Kernel/PCI.c
	gcc -ffreestanding -c  -I Includes -o PCI.o Kernel/PCI.c
PCIEnum.o	:	PCI.o Kernel/PCIEnum.c
	gcc -ffreestanding -c  -I Includes -o PCIEnum.o Kernel/PCIEnum.c
NumConvert.o	:	Src/NumConvert.c
	gcc -ffreestanding -c  -I Includes -o NumConvert.o Src/NumConvert.c
Printf.o	:	VGAText.o VGACursor.o modf.o Src/Printf.c
	gcc -ffreestanding -c  -I Includes -o Printf.o Src/Printf.c
modf.o		:	Src/modf.S
	as  -I Includes -o modf.o Src/modf.S
String.o	:	Src/String.c
	gcc -ffreestanding -c  -I Includes -o String.o Src/String.c

[-- Attachment #2: Printf.c --]
[-- Type: text/x-c, Size: 21929 bytes --]

/*	Ace OS Kerenl Source Code - Created on 13-Aug-2002 by Sam (samuelhard@yahoo.com)
	Copied and modified the GCC 3.0 doprnt.c file provided with DJGPP	
*/
#include <StdArga.h>
#include <TypeDefs.h>
#include <ChType.h>
#include <VGAText.h>
void __umoddi3()
    {
    }
void __udivdi3(int x)
    {
    }

char decimal = '.';
int nan = 0;
/* 11-bit exponent (VAX G floating point) is 308 decimal digits */
#define	MAXEXP		308
#define MAXEXPLD	3700 /* this includes subnormal numbers */
//#define	MAXEXP		308
//#define MAXEXPLD	4952 /* this includes subnormal numbers */
/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
#define	MAXFRACT	39

#define	DEFPREC		6
#define	DEFLPREC	6

#define	BUF			(MAXEXPLD+MAXFRACT+1)	/* + decimal point */

#define	PUTC(ch)	(void) PutCh(ch)

#define ARG(basetype) _ulonglong = \
		flags&LONGDBL ? va_arg(argp, long long basetype) : \
		flags&LONGINT ? va_arg(argp, long basetype) : \
		flags&SHORTINT ? (short basetype)va_arg(argp, int) : \
		va_arg(argp, int)

/* have to deal with the negative buffer count kludge */

#define	LONGINT		0x01		/* long integer */
#define	LONGDBL		0x02		/* long double */
#define	SHORTINT	0x04		/* short integer */
#define	ALT			0x08		/* alternate form */
#define	LADJUST		0x10		/* left adjustment */
#define	ZEROPAD		0x20		/* zero (as opposed to blank) pad */
#define	HEXPREFIX	0x40		/* add 0x or 0X prefix */

int cvtl(long double number, int prec, int flags, char *signp, unsigned char fmtch, char *startp, char *endp);
char *roundl(long double fract, int *expv, char *start, char *end,  char ch, char *signp);
char *exponentl(char *p, int expv, unsigned char fmtch);
#ifdef __GO32__
	static int isspeciall(long double d, char *bufp);
#endif

static char NULL_REP[] = "(null)";
int Printf(const char *fmt, ...)
	{_DoPrint(fmt, (&fmt)+1);
	 return 1;
	}
int _DoPrint(const char *fmt0, va_list argp)
	{const char *fmt;		/* format string */
	int ch;					/* character from fmt */
	int cnt;				/* return value accumulator */
	int n;					/* random handy integer */
	char *t;				/* buffer pointer */
	long double _ldouble;	/* double and long double precision arguments %L.[eEfgG] */
	unsigned long long _ulonglong=0; /* integer arguments %[diouxX] */
	int base;				/* base for [diouxX] conversion */
	int dprec;				/* decimal precision in [diouxX] */
	int fieldsz;			/* field size expanded by sign, etc */
	int flags;				/* flags as above */
	int fpprec;				/* `extra' floating precision in [eEfgG] */
	int prec;				/* precision from format (%.3d), or -1 */
	int realsz;				/* field size expanded by decimal precision */
	int size;				/* size of converted field or string */
	int width;				/* width from format (%8d), or 0 */
	char sign;				/* sign prefix (' ', '+', '-', or \0) */
	char softsign;			/* temporary negative sign for floats */
	const char *digs;		/* digits for [diouxX] conversion */
	char buf[BUF];			/* space for %c, %[diouxX], %[eEfgG] */
	int neg_ldouble = 0;	/* non-zero if _ldouble is negative */
	decimal = '.';
	fmt = fmt0;
  	digs = "0123456789abcdef";
  	for (cnt = 0;; ++fmt)
    	{
    	while ((ch = *fmt) && ch != '%')
   			{PUTC (ch);
      		fmt++;
      		cnt++;
      		}
   		if (!ch)
      		return cnt;
   		flags = 0; dprec = 0; fpprec = 0; width = 0;
   		prec = -1; sign = '\0';
 		rflag:
 		switch (*++fmt)
    		{
    		case ' ':
     		 	/*
		       * ``If the space and + flags both appear, the space
		       * flag will be ignored.''
		       *	-- ANSI X3J11
		       */
		       if (!sign)
		       		sign = ' ';
       		   goto rflag;
 		    case '#':
 		   		flags |= ALT;
 		   		goto rflag;
	   		case '*':
		      /*
			   		 * ``A negative field width argument is taken as a
		       * - flag followed by a  positive field width.''
		       *	-- ANSI X3J11
		       * They don't exclude field widths read from args.
		       */
		        if ((width = va_arg(argp, int)) >= 0)
		       		goto rflag;
	       		width = -width;
	       		/* FALLTHROUGH */
       		case '-':
       			flags |= LADJUST;
       			goto rflag;
   			case '+':
   				sign = '+';
   				goto rflag;
			case '.':
				if (*++fmt == '*')
					n = va_arg(argp, int);
				else
					{
					n = 0;
					while (IsAscii(*fmt) && IsDigit(*fmt))
						n = 10 * n + ToDigit(*fmt++);
					--fmt;
					}
				prec = n < 0 ? -1 : n;
				goto rflag;
			case '0':
			      /*
			       * ``Note that 0 is taken as a flag, not as the
			       * beginning of a field width.''
			       *	-- ANSI X3J11
			       */
		       flags |= ZEROPAD;
		       goto rflag;
       	 	case '1': case '2': case '3': case '4':
       	 	case '5': case '6': case '7': case '8': case '9':
       	 		n = 0;
       	 		do {
       	 			n = 10 * n + ToDigit(*fmt);
      	 			} while (IsAscii(*++fmt) && IsDigit(*fmt));
           		width = n;
           		--fmt;
           		goto rflag;
       		case 'L':
       			flags |= LONGDBL;
       			goto rflag;
			case 'h':
				flags |= SHORTINT;
				goto rflag;
			case 'l':
				if (flags&LONGINT)
					flags |= LONGDBL; /* for 'll' - long long */
				else
					flags |= LONGINT;
				goto rflag;
			case 'c':
				*(t = buf) = va_arg(argp, int);
				size = 1;
				sign = '\0';
				goto pforw;
			case 'D':
				flags |= LONGINT;
				/*FALLTHROUGH*/
			case 'd':
			case 'i':
				ARG(int);
				if ((long long)_ulonglong < 0)
					{
					_ulonglong = -_ulonglong;
					sign = '-';
					}
				base = 10;
				goto number;
			case 'e':
			case 'E':
			case 'f':
			case 'g':
			case 'G':
				if (flags & LONGDBL)
					_ldouble = va_arg(argp, long double);
				else
					_ldouble = (long double)va_arg(argp, double);
		        /*
		        * don't do unrealistic precision; just pad it with
		        * zeroes later, so buffer size stays rational.
		        */
		        if (prec > MAXFRACT)
		        	{
		        	if (*fmt != 'g' && (*fmt != 'G' || (flags&ALT)))
		        		fpprec = prec - MAXFRACT;
		        	prec = MAXFRACT;
		        	}
		        else if (prec == -1)
		        	{
		        	if (flags&LONGINT)
		        		prec = DEFLPREC;
		        	else
		        		prec = DEFPREC;
		        	}
		        /*
		        * softsign avoids negative 0 if _double is < 0 and
		        * no significant digits will be shown
		        */
		        if (_ldouble < 0)
					{softsign = '-';
					_ldouble = -_ldouble;
					neg_ldouble = 1;
					}
				else
					{softsign = 0;
					neg_ldouble = 0;
					}
			      /*
			       * cvt may have to round up past the "start" of the
			       * buffer, i.e. ``intf("%.2f", (double)9.999);'';
			       * if the first char isn't NULL, it did.
			       */
				*buf = NULL;
				size = cvtl(_ldouble, prec, flags, &softsign, *fmt, buf, buf + sizeof(buf));
			      /*
			       * If the format specifier requested an explicit sign,
			       * we print a negative sign even if no significant digits
			       * will be shown, and we also print a sign for a NaN.  In
			       * other words, "%+f" might print -0.000000, +NaN and -NaN.
			       */
				if (softsign || (sign == '+' && (neg_ldouble || nan == -1)))
					sign = '-';
				nan = 0;
				t = *buf ? buf : buf + 1;
				goto pforw;
			case 'n':
				if (flags & LONGDBL)
					*va_arg(argp, long long *) = cnt;
				else if (flags & LONGINT)
					*va_arg(argp, long *) = cnt;
				else if (flags & SHORTINT)
					*va_arg(argp, short *) = cnt;
				else
					*va_arg(argp, int *) = cnt;
				break;
			case 'O':
				flags |= LONGINT;
			/*FALLTHROUGH*/
			case 'o':
				ARG(unsigned);
				base = 8;
				goto nosign;
			case 'p':
				/*
      			* ``The argument shall be a pointer to void.  The
		       * value of the pointer is converted to a sequence
		       * of printable characters, in an implementation-
		       * defined manner.''
		       *	-- ANSI X3J11
		       */
		    	/* NOSTRICT */
				_ulonglong = (unsigned long)va_arg(argp, void *);
				base = 16;
				goto nosign;
			case 's':
				if (!(t = va_arg(argp, char *)))
					t = NULL_REP;
				if (prec >= 0)
					{
						/*
						 * can't use strlen; can only look for the
						 * NUL in the first `prec' characters, and
						 * strlen() will go further.
						 */
					char *p			/*, *memchr() */;
					if ((p = StrNChr(t, 0, prec)))
						{size = p - t;
						if (size > prec)
							size = prec;
						}
					else
						size = prec;
					}
				else
					size = StrLen(t);
				sign = '\0';
				goto pforw;
			case 'U':
				flags |= LONGINT;
				/*FALLTHROUGH*/
			case 'u':
				ARG(unsigned);
				base = 10;
				goto nosign;
			case 'X':
				digs = "0123456789ABCDEF";
				/* FALLTHROUGH */
			case 'x':
				ARG(unsigned);
				base = 16;
				/* leading 0x/X only if non-zero */
				if (flags & ALT && _ulonglong != 0)
					flags |= HEXPREFIX;
    			nosign:
					/* unsigned conversions */
					sign = '\0';
				number:
			      /*
			       * ``... diouXx conversions ... if a precision is
			       * specified, the 0 flag will be ignored.''
			       *	-- ANSI X3J11
			       */
					if ((dprec = prec) >= 0)
						flags &= ~ZEROPAD;
		        	/* ``The result of converting a zero value with an
			        * explicit precision of zero is no characters.''
			        *	-- ANSI X3J11*/
					t = buf + BUF;
					if (_ulonglong != 0 || prec != 0)
						{
			        	/* conversion is done separately since operations
					    with long long are much slower */
						#define CONVERT(type) \
    					{ \
						register type _n = (type)_ulonglong; \
						do { \
							*--t = digs[_n % base]; \
							_n /= base; \
							} while (_n); \
						}
						if (flags&LONGDBL)
							CONVERT(unsigned long long) /* no ; */
						else
							CONVERT(unsigned long) /* no ; */
						#undef CONVERT
						if (flags & ALT && base == 8 && *t != '0')
							*--t = '0';		/* octal leading 0 */
				      	}

					digs = "0123456789abcdef";
    	    		size = buf + BUF - t;
				pforw:
			      /*
			       * All reasonable formats wind up here.  At this point,
			       * `t' points to a string which (if not flags&LADJUST)
		    	   * should be padded out to `width' places.  If
			       * flags&ZEROPAD, it should first be prefixed by any
			       * sign or other prefix; otherwise, it should be blank
			       * padded before the prefix is emitted.  After any
		    	   * left-hand padding and prefixing, emit zeroes
			       * required by a decimal [diouxX] precision, then print
			       * the string proper, then emit zeroes required by any
			       * leftover floating precision; finally, if LADJUST,
			       * pad with blanks.
			       */
		
			      /*
			       * compute actual size, so we know how much to pad
			       * fieldsz excludes decimal prec; realsz includes it
		    	   */
					fieldsz = size + fpprec;
					realsz = dprec > fieldsz ? dprec : fieldsz;
					if (sign)
						realsz++;
					if (flags & HEXPREFIX)
						realsz += 2;
					/* right-adjusting blank padding */
					if ((flags & (LADJUST|ZEROPAD)) == 0 && width)
						for (n = realsz; n < width; n++)
							PUTC(' ');
					/* prefix */
					if (sign)
						PUTC(sign);
					if (flags & HEXPREFIX)
						{PUTC('0');
						PUTC((char)*fmt);
						}
					/* right-adjusting zero padding */
					if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
						for (n = realsz; n < width; n++)
							PUTC('0');
					/* leading zeroes from decimal precision */
					for (n = fieldsz; n < dprec; n++)
						PUTC('0');

					/* the string or number proper */
					for (n = size; n > 0; n--)
						PUTC(*t++);
					/* trailing f.p. zeroes */
					while (--fpprec >= 0)
						PUTC('0');
					/* left-adjusting padding (always blank) */
					if (flags & LADJUST)
						for (n = realsz; n < width; n++)
							PUTC(' ');
					/* finally, adjust cnt */
					cnt += width > realsz ? width : realsz;
					break;
			case '\0':			/* "%?" prints ?, unless ? is NULL */
				return cnt;
			default:
				PUTC((char)*fmt);
				cnt++;
			}
		}
  	/* NOTREACHED */
	}

static long double pten[] =	{1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L, 1e512L, 1e1024L, 1e2048L, 1e4096L};
static long double ptenneg[] ={1e-1L, 1e-2L, 1e-4L, 1e-8L, 1e-16L, 1e-32L, 1e-64L, 1e-128L, 1e-256L,1e-512L, 1e-1024L, 1e-2048L, 1e-4096L};

#define MAXP 4096
#define NP   12
#define P    (4294967296.0L * 4294967296.0L * 2.0L)   /* 2^65 */
static long double INVPREC = P;
static long double PREC = 1.0L/P;
#undef P
/*
 * Defining FAST_LDOUBLE_CONVERSION results in a little bit faster
 * version, which might be less accurate (about 1 bit) for long
 * double. For 'normal' double it doesn't matter.
 */
/* #define FAST_LDOUBLE_CONVERSION */

int cvtl(long double number, int prec, int flags, char *signp, unsigned char fmtch,char *startp, char *endp)
	{char *p, *t;
	long double fract=0;
	int dotrim, expcnt, gformat;
	int doextradps=0;    /* Do extra decimal places if the precision needs it */
	int doingzero=0;     /* We're displaying 0.0 */
	long double integer, tmp;

	if ((expcnt = isspeciall(number, startp)))
		return(expcnt);

	dotrim = expcnt = gformat = 0;
	/* fract = modfl(number, &integer); */
	integer = number;

	/* get an extra slot for rounding. */
	t = ++startp;

	p = endp - 1;
	if (integer)
		{
		int i, lp=NP, pt=MAXP;
		#ifndef FAST_LDOUBLE_CONVERSION
			long double oint = integer, dd=1.0L;
		#endif
		if (integer > INVPREC)
			{integer *= PREC;
			while(lp >= 0) 
				{if (integer >= pten[lp])
					{expcnt += pt;
					integer *= ptenneg[lp];
					#ifndef FAST_LDOUBLE_CONVERSION
						dd *= pten[lp];
					#endif
					}
				pt >>= 1;
				lp--;
				}
			#ifndef FAST_LDOUBLE_CONVERSION
				integer = oint/dd;
			#else
				integer *= INVPREC;
			#endif
			}
		/*
	    * Do we really need this ?
    	*/
		for (i = 0; i < expcnt; i++)
      		*p-- = '0';
		}
		number = integer;
		fract = modfl(number, &integer);
		/* If integer is zero then we need to look at where the sig figs are */
		if (integer<1)
			{/* If fract is zero the zero before the decimal point is a sig fig */
			if (fract==0.0)
   				doingzero=1;
			/* If fract is non-zero all sig figs are in fractional part */
			else 
   				doextradps=1;
  			}
		/*
		* get integer portion of number; put into the end of the buffer; the
		* .01 is added for modf(356.0 / 10, &integer) returning .59999999...
		*/
		for (; integer; ++expcnt)
			{ tmp = modfl(integer * 0.1L , &integer);
    		*p-- = ToChar((int)((tmp + .01L) * 10));
  			}
		switch(fmtch)
			{
			case 'f':
				/* reverse integer into beginning of buffer */
				if (expcnt)
					for (; ++p < endp; *t++ = *p);
				else
					*t++ = '0';
				/*
				* if precision required or alternate flag set, add in a
				* decimal point.
				*/
				if (prec || flags&ALT)
					*t++ = decimal;
				/* if requires more precision and some fraction left */
				if (fract)
					{if (prec)
					do {
						fract = modfl(fract * 10.0L, &tmp);
						*t++ = ToChar((int)tmp);
						}while (--prec && fract);
					if (fract)
						startp = roundl(fract, (int *)NULL, startp, t - 1, (char)0, signp);
					}
				for (; prec--; *t++ = '0');
				break;
			case 'e':
			case 'E':
				eformat:
					if (expcnt)
						{*t++ = *++p;
						if (prec || flags&ALT)
							*t++ = decimal;
						/* if requires more precision and some integer left */
						for (; prec && ++p < endp; --prec)
							*t++ = *p;
						/* if done precision and more of the integer component,
						* round using it; adjust fract so we don't re-round
						* later.*/
						if (!prec && ++p < endp)
							{fract = 0;
							startp = roundl((long double)0.0L, &expcnt,startp, t - 1, *p, signp);
							}
						/* adjust expcnt for digit in front of decimal */
						--expcnt;
						}
						/* until first fractional digit, decrement exponent */
					else if (fract)
						{int lp=NP, pt=MAXP;
						#ifndef FAST_LDOUBLE_CONVERSION
							long double ofract = fract, dd=1.0L;
						#endif
						expcnt = -1;
						if (fract < PREC)
							{fract *= INVPREC;
							while(lp >= 0)
								{if (fract <= ptenneg[lp])
									{expcnt -= pt;
									fract *= pten[lp];
									#ifndef FAST_LDOUBLE_CONVERSION
										dd *= pten[lp];
									#endif
									}
								pt >>= 1;
								lp--;
								}
							#ifndef FAST_LDOUBLE_CONVERSION
								fract = ofract*dd;
							#else
								fract *= PREC;
							#endif
							}
						/* adjust expcnt for digit in front of decimal */
						for (/* expcnt = -1 */ ;; --expcnt)
							{fract = modfl(fract * 10.0L, &tmp);
							if (tmp)
      							break;
            				}
						*t++ = ToChar((int)tmp);
						if (prec || flags&ALT)
							*t++ = decimal;
						}
					else
 						{*t++ = '0';
						if (prec || flags&ALT)
							*t++ = decimal;
						}
				/* if requires more precision and some fraction left */
				if (fract)
					{if (prec)
						do {
							fract = modfl(fract * 10.0L, &tmp);
							*t++ = ToChar((int)tmp);
							} while (--prec && fract);
						if (fract)
							startp = roundl(fract, &expcnt, startp, t - 1, (char)0, signp);
					}
				/* if requires more precision */
				for (; prec--; *t++ = '0');
				/* unless alternate flag, trim any g/G format trailing 0's */
				if (gformat && !(flags&ALT))
					{while (t > startp && *--t == '0');
					if (*t == decimal)
						--t;
					++t;
					}
				t = exponentl(t, expcnt, fmtch);
				break;
			case 'g':
			case 'G':
				if (prec)
    				{/* If doing zero and precision is greater than 0 count the * 0 before the decimal place */
					if (doingzero) --prec;
					}
				else
    				{/* a precision of 0 is treated as precision of 1 unless doing zero */
					if (!doingzero) ++prec;
					}
			    /* ``The style used depends on the value converted; style e
			     * will be used only if the exponent resulting from the
		    	 * conversion is less than -4 or greater than the precision.''
			     *	-- ANSI X3J11 */
				if (expcnt > prec || (!expcnt && fract && fract < .0001))
					{
					/* g/G format counts "significant digits, not digits of
    				* precision; for the e/E format, this just causes an
					* off-by-one problem, i.e. g/G considers the digit
					* before the decimal point significant and e/E doesn't
					* count it as precision.*/
					--prec;
					fmtch -= 2;		/* G->E, g->e */
					gformat = 1;
					goto eformat;
					}
				/* reverse integer into beginning of buffer, note, decrement precision */
				if (expcnt)
					for (; ++p < endp; *t++ = *p, --prec);
				else
					*t++ = '0';
			    /* if precision required or alternate flag set, add in a
			     * decimal point.  If no digits yet, add in leading 0. */
				if (prec || flags&ALT)
					{dotrim = 1;
					*t++ = decimal;
					}
				else
					dotrim = 0;
				/* if requires more precision and some fraction left */
				while (prec && fract)
					{fract = modfl(fract * 10.0L, &tmp);
					*t++ = ToChar((int)tmp);
					/* If we're not adding 0s or we are but they're sig figs:
			        * decrement the precision */
					if ((doextradps!=1) || ((int)tmp!=0)) 
     					{doextradps=0;
						prec--;
      					}
					}
				if (fract)
					startp = roundl(fract, (int *)NULL, startp, t - 1, (char)0, signp);
				/* alternate format, adds 0's for precision, else trim 0's */
				if (flags&ALT)
					for (; prec--; *t++ = '0');
				else if (dotrim)
					{while (t > startp && *--t == '0');
					if (*t != decimal)
						++t;
					}
		}
	return t - startp;
	}

char * roundl(long double fract, int *expv, char *start, char *end, char ch, char *signp)
	{long double tmp;
	if (fract)
 		{if (fract == 0.5L)
			{char *e = end;
			if (*e == '.')
				e--;
			if (*e == '0' || *e == '2' || *e == '4' || *e == '6' || *e == '8')
				{tmp = 3.0;
				goto start;
				}
			}
			(void)modfl(fract * 10.0L, &tmp);
  		}
	else
		tmp = ToDigit(ch);
	start:
		if (tmp > 4)
			for (;; --end)
				{if (*end == decimal)
					--end;
				if (++*end <= '9')
					break;
				*end = '0';
				if (end == start)
					{if (expv)
						{/* e/E; increment exponent */
						*end = '1';
						++*expv;
						}
					else
						{/* f; add extra digit */
						*--end = '1';
						--start;
						}
					break;
					}
				}
	/* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
		else if (*signp == '-')
			for (;; --end)
				{if (*end == decimal)
					--end;
				if (*end != '0')
					break;
				if (end == start)
					*signp = 0;
				}
	return start;
	}

char * exponentl(char *p, int expv, unsigned char fmtch)
	{
	char *t;
	char expbuf[MAXEXPLD];

	*p++ = fmtch;
	if (expv < 0)
		{expv = -expv;
		*p++ = '-';
		}
	else
 		*p++ = '+';
	t = expbuf + MAXEXPLD;
	if (expv > 9)
		{
  		do {
			*--t = ToChar(expv % 10);
			} while ((expv /= 10) > 9);
		*--t = ToChar(expv);
		for (; t < expbuf + MAXEXPLD; *p++ = *t++);
		}
	else
		{
		*p++ = '0';
		*p++ = ToChar(expv);
		}
	return p;
	}
int isspeciall(long double d, char *bufp)
	{struct IEEExp {
		unsigned manl:32;
		unsigned manh:32;
		unsigned exp:15;
		unsigned sign:1;
	}*ip = (struct IEEExp *)&d;

	nan = 0;  /* don't assume the static is 0 (emacs) */
	if (ip->exp != 0x7fff)
		return(0);
	if ((ip->manh & 0x7fffffff) || ip->manl)
		{StrCpy(bufp, "NaN");
		nan = ip->sign ? -1 : 1; /* kludge: we don't need the sign,  it's not nice
				but it should work */
		}
	else
		(void)StrCpy(bufp, "Inf");
	return(3);
	}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: what is the use of __umoddi3() and __udivdi3() in the function printf()?
  2002-08-15 22:20 what is the use of __umoddi3() and __udivdi3() in the function printf()? Samuel
@ 2002-08-19 10:53 ` Jan Hubicka
  0 siblings, 0 replies; 2+ messages in thread
From: Jan Hubicka @ 2002-08-19 10:53 UTC (permalink / raw)
  To: Samuel; +Cc: gcc, gcc

> 
> Hai,
> 
> I tried to create a program which independant of all system and standard libs. When i modified and make the printf function, the linker says missing symbols ___umoddi3 and ___udivdi3. I globaly declared two functions with the name of the above and complied the program, it works fine now. However i want know what is the use of the above symbols, can you tell me what is the use of these functions or variables?

Some operations not supported by hardware directly are turned into calls
of runtime.  In this case ___umoddi3 does 64bit modulo and ___udivdi3
divide operation.  You may want to link the runtime (libgcc.a) into your
program to get proper implementations.  The libgcc.a is independent on
the rest of environment so it should not cause problems for you.

Honza

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-08-19 10:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-08-15 22:20 what is the use of __umoddi3() and __udivdi3() in the function printf()? Samuel
2002-08-19 10:53 ` Jan Hubicka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).