# HG changeset patch # User Michael Spacefalcon # Date 1367218822 0 # Node ID 45bf8af5f0619cfa604e46982666b7b56b03ac5f # Parent ddda170fa6f464f746bc9dd8539ec31a3810239c libprintf brought in from older PPC/m68k code, but fucking GCC refuses to compile - need to convert to Anshit C diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/Makefile Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,16 @@ +CC= arm-elf-gcc +CFLAGS= -Os -fno-builtin +AR= arm-elf-ar +RANLIB= arm-elf-ranlib + +OBJS= doprnt.o printf.o putchar.o puts.o sprintf.o sprintf_putchar.o \ + vprintf.o vsprintf.o + +all: libprintf.a + +libprintf.a: ${OBJS} + ${AR} cru $@ ${OBJS} + ${RANLIB} $@ + +clean: + rm -f *.[oa] *errs diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/README Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,15 @@ +The present libprintf is a very light printf implementation that is well-suited +for simple bare-metal programs like loadagent; in the present case it overrides +the much heavier printf implementation in newlib. Programs like the present +loadagent only need printf in order to scribble on the serial console port, +and the most sensible implementation is to have the "character output" function +from the guts of printf point directly to the physical UART output routine, or +a trivial wrapper that turns \n into \r\n. In contrast, newlib's version would +pull in the complete FILE table infrastructure and malloc etc - maybe OK for +more complex embedded programs that use those facilities for other things under +a bona fide RTOS, but it would be disgusting to pull that stuff in for a +minimal program like ours. + +The present printf implementation has been used earlier by the same author +(Michael Spacefalcon) in the StarMON family of PowerPC bootloaders, and in my +MC68x302-based SDSL CPE devices (Hack-o-Rocket and OSDCU). diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/doprnt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/doprnt.c Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,301 @@ +/* the guts of printf - this implementation came from 4.3BSD-Tahoe */ + +#include +#include +#include + +#define PUTC(ch) ((*outfunc)((ch), outfunc_param)) + +#define ARG() \ + _ulong = flags&LONGINT ? va_arg(argp, long) : \ + flags&SHORTINT ? va_arg(argp, short) : va_arg(argp, int); + +#define BUF 256 + +#define todigit(c) ((c) - '0') +#define tochar(n) ((n) + '0') + +/* have to deal with the negative buffer count kludge */ +#define NEGATIVE_COUNT_KLUDGE + +#define LONGINT 0x01 /* long integer */ +#define LONGDBL 0x02 /* long double; unimplemented */ +#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 */ + +_doprnt(fmt0, argp, outfunc, outfunc_param) + u_char *fmt0; + va_list argp; + void (*outfunc)(); + void *outfunc_param; +{ + register u_char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int cnt; /* return value accumulator */ + register int n; /* random handy integer */ + register char *t; /* buffer pointer */ + u_long _ulong; /* 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 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 */ + char *digs; /* digits for [diouxX] conversion */ + char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + + fmt = fmt0; + digs = "0123456789abcdef"; + for (cnt = 0;; ++fmt) { + for (; (ch = *fmt) && ch != '%'; ++cnt, ++fmt) + PUTC(ch); + if (!ch) + return (cnt); + + flags = 0; dprec = 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': + 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(); + if ((long)_ulong < 0) { + _ulong = -_ulong; + sign = '-'; + } + base = 10; + goto number; + case 'n': + 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(); + 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 */ + _ulong = (u_long)va_arg(argp, void *); + base = 16; + goto nosign; + case 's': + if (!(t = va_arg(argp, char *))) + t = "(null)"; + 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; + + for (p = t, size = 0; size < prec; p++, size++) + if (*p == '\0') + break; + } else + size = strlen(t); + sign = '\0'; + goto pforw; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + ARG(); + base = 10; + goto nosign; + case 'X': + digs = "0123456789ABCDEF"; + /* FALLTHROUGH */ + case 'x': + ARG(); + base = 16; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _ulong != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ +nosign: sign = '\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ +number: 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 (_ulong != 0 || prec != 0) { + do { + *--t = digs[_ulong % base]; + _ulong /= base; + } while (_ulong); + digs = "0123456789abcdef"; + if (flags & ALT && base == 8 && *t != '0') + *--t = '0'; /* octal leading 0 */ + } + 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; + if (sign) + fieldsz++; + if (flags & HEXPREFIX) + fieldsz += 2; + realsz = dprec > fieldsz ? dprec : fieldsz; + + /* 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'); + + for (n = size; --n >= 0; ) + PUTC(*t++); + /* 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 */ +} diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/printf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/printf.c Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,18 @@ +#include + +extern void putchar(); + +int +printf(va_alist) + va_dcl +{ + va_list ap; + char *fmt; + int len; + + va_start(ap); + fmt = va_arg(ap, char *); + len = _doprnt(fmt, ap, &putchar); + va_end(ap); + return(len); +} diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/putchar.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/putchar.c Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,9 @@ +extern void serial_out(); + +void +putchar(ch) +{ + if (ch == '\n') + serial_out('\r'); + serial_out(ch); +} diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/puts.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/puts.c Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,10 @@ +void +puts(s) + char *s; +{ + int c; + + while (c = *s++) + putchar(c); + putchar('\n'); +} diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/sprintf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/sprintf.c Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,21 @@ +#include + +extern void _sprintf_putchar(); + +int +sprintf(va_alist) + va_dcl +{ + va_list ap; + char *strptr; + char *fmt; + int len; + + va_start(ap); + strptr = va_arg(ap, char *); + fmt = va_arg(ap, char *); + len = _doprnt(fmt, ap, &_sprintf_putchar, &strptr); + *strptr = '\0'; + va_end(ap); + return(len); +} diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/sprintf_putchar.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/sprintf_putchar.c Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,8 @@ +void +_sprintf_putchar(ch, pp) + int ch; + char **pp; +{ + **pp = ch; + (*pp)++; +} diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/vprintf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/vprintf.c Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,11 @@ +#include + +extern void putchar(); + +int +vprintf(fmt, ap) + char *fmt; + va_list ap; +{ + return(_doprnt(fmt, ap, &putchar)); +} diff -r ddda170fa6f4 -r 45bf8af5f061 loadagent/libprintf/vsprintf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loadagent/libprintf/vsprintf.c Mon Apr 29 07:00:22 2013 +0000 @@ -0,0 +1,17 @@ +#include + +extern void _sprintf_putchar(); + +int +vsprintf(str, fmt, ap) + va_list ap; + char *str, *fmt; +{ + char *strptr; + int len; + + strptr = str; + len = _doprnt(fmt, ap, &_sprintf_putchar, &strptr); + *strptr = '\0'; + return(len); +}