diff options
Diffstat (limited to 'libc/misc')
-rw-r--r-- | libc/misc/dprintf.c | 266 | ||||
-rw-r--r-- | libc/misc/ffs.c | 42 | ||||
-rw-r--r-- | libc/misc/unctrl.c | 146 |
3 files changed, 454 insertions, 0 deletions
diff --git a/libc/misc/dprintf.c b/libc/misc/dprintf.c new file mode 100644 index 0000000..071d177 --- /dev/null +++ b/libc/misc/dprintf.c @@ -0,0 +1,266 @@ +/* Debugging printf, for debugging the library itself. + + We don't assume stdio is working. + We do assume _write_r is working. +*/ + +#include "ctype.h" +#include "reent.h" +#include "string.h" +#include "unctrl.h" + +#ifdef __STDC__ +#include "stdarg.h" +#else +#include "varargs.h" +#endif + +static char *parse_number (); +static long get_number (); +static void print_number (); +static void write_char (); +static void write_string (); + +/* Non-zero for big-endian systems. */ +static int big_endian_p; + +/* For now hardcode 2 (stderr) as the console file descriptor. + May wish to let the caller pass in a file descriptor or some such but + this is only for debugging purposes anyway. */ +#define CONSOLE_FD 2 + +/* Standalone printf routine. + + The format string has been enhanced so that multiple values can be dumped + without having to have a %-field for each one (say if you want to dump + 20 words at a certain address). A modifier of `N' says the next argument + is a count, and the one after that is a pointer. + + Example: __dprintf (stderr, "%Nx\n", 20, p); /-* print 20 ints at `p' *-/ + + Supported formats are: c d u x s p. + + All ints are retrieved a byte at a time so alignment issues are not + a problem. + + This routine is used in situations where the only debugging capability + is console output and was written to aid debugging newlib itself. We don't + use printf ourselves as we may be debugging it. We do assume _write_r is + working. +*/ + +void +#ifdef __STDC__ +__dprintf (char *fmt, ...) +#else +__dprintf (fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list args; + + /* Which endian are we? */ + { + short tmp = 1; + big_endian_p = *(char *) &tmp == 0; + } + +#ifdef __STDC__ + va_start (args, fmt); +#else + va_start (args); +#endif + + while (*fmt) + { + char c, *p; + int count; + long l; + + if (*fmt != '%' || *++fmt == '%') + { + write_char (*fmt++); + continue; + } + + if (*fmt == 'N') + { + count = va_arg (args, int); + p = va_arg (args, char *); + ++fmt; + c = *fmt++; + + while (--count >= 0) + { + switch (c) + { + case 'c' : + write_string (unctrl (*p++)); + break; + case 'p' : + print_number (16, 1, get_number (p, sizeof (char *), 1)); + p += sizeof (char *); + break; + case 'd' : + case 'u' : + case 'x' : + print_number (c == 'x' ? 16 : 10, c != 'd', + get_number (p, sizeof (int), c != 'd')); + p += sizeof (int); + break; + case 's' : + write_string (*(char **) p); + p += sizeof (char *); + break; + } + if (count > 0) + write_char (' '); + } + } + else + { + switch (c = *fmt++) + { + case 'c' : + c = va_arg (args, int); + write_string (unctrl (c)); + break; + case 'p' : + l = (_POINTER_INT) va_arg (args, char *); + print_number (16, 1, l); + break; + case 'd' : + case 'u' : + case 'x' : + l = va_arg (args, int); + print_number (c == 'x' ? 16 : 10, c != 'd', l); + break; + case 's' : + p = va_arg (args, char *); + write_string (p); + break; + } + } + } + + va_end (args); +} + +/* Parse a positive decimal integer at S. + FIXME: Was used in earlier version, but not currently used. + Keep for now. */ + +static char * +parse_number (s, p) + char *s; + long *p; +{ + long x = 0; + + while (isdigit (*s)) + { + x = (x * 10) + (*s - '0'); + ++s; + } + + *p = x; + return s; +} + +/* Fetch the number at S of SIZE bytes. */ + +static long +get_number (s, size, unsigned_p) + char *s; + long size; + int unsigned_p; +{ + long x; + unsigned char *p = (unsigned char *) s; + + switch (size) + { + case 1 : + x = *p; + if (!unsigned_p) + x = (x ^ 0x80) - 0x80; + return x; + case 2 : + if (big_endian_p) + x = (p[0] << 8) | p[1]; + else + x = (p[1] << 8) | p[0]; + if (!unsigned_p) + x = (x ^ 0x8000) - 0x8000; + return x; + case 4 : + if (big_endian_p) + x = ((long)p[0] << 24) | ((long)p[1] << 16) | (p[2] << 8) | p[3]; + else + x = ((long)p[3] << 24) | ((long)p[2] << 16) | (p[1] << 8) | p[0]; + if (!unsigned_p) + x = (x ^ 0x80000000L) - 0x80000000L; + return x; +#if 0 /* FIXME: Is there a standard mechanism for knowing if + long longs exist? */ + case 8 : +#endif + default : + return 0; + } +} + +/* Print X in base BASE. */ + +static void +print_number (base, unsigned_p, n) + int base; + int unsigned_p; + long n; +{ + static char chars[16] = "0123456789abcdef"; + char *p, buf[32]; + unsigned long x; + + if (!unsigned_p && n < 0) + { + write_char ('-'); + x = -n; + } + else + x = n; + + p = buf + sizeof (buf); + *--p = '\0'; + do + { + *--p = chars[x % base]; + x /= base; + } + while (x != 0); + + write_string (p); +} + +/* Write C to the console. + We go through the file descriptor directly because we can't assume + stdio is working. */ + +static void +write_char (c) + char c; +{ + _write_r (_REENT, CONSOLE_FD, &c, 1); +} + +/* Write S to the console. + We go through the file descriptor directly because we can't assume + stdio is working. */ + +static void +write_string (s) + char *s; +{ + _write_r (_REENT, CONSOLE_FD, s, strlen (s)); +} diff --git a/libc/misc/ffs.c b/libc/misc/ffs.c new file mode 100644 index 0000000..e4afe7a --- /dev/null +++ b/libc/misc/ffs.c @@ -0,0 +1,42 @@ +/* +FUNCTION + <<ffs>>---find first bit set in a word + +INDEX + ffs + +ANSI_SYNOPSIS + int ffs(int <[word]>); + +TRAD_SYNOPSIS + int ffs(<[word]>); + +DESCRIPTION + +<<ffs>> returns the first bit set in a word. + +RETURNS +<<ffs>> returns 0 if <[c]> is 0, 1 if <[c]> is odd, 2 if <[c]> is a multiple of +2, etc. + +PORTABILITY +<<ffs>> is not ANSI C. + +No supporting OS subroutines are required. */ + +int +ffs (word) + int word; +{ + int i; + + if (!word) + return 0; + + i = 0; + for (;;) + { + if (((1 << i++) & word) != 0) + return i; + } +} diff --git a/libc/misc/unctrl.c b/libc/misc/unctrl.c new file mode 100644 index 0000000..e7350c6 --- /dev/null +++ b/libc/misc/unctrl.c @@ -0,0 +1,146 @@ +/* +FUNCTION + <<unctrl>>---translate characters to upper case + +INDEX + unctrl +INDEX + unctrllen + +ANSI_SYNOPSIS + #include <unctrl.h> + char *unctrl(int <[c]>); + int unctrllen(int <[c]>); + +TRAD_SYNOPSIS + #include <unctrl.h> + char *unctrl(<[c]>); + int unctrllen(<[c]>); + +DESCRIPTION +<<unctrl>> is a macro which returns the printable representation of <[c]> +as a string. +<<unctrllen>> is a macro which returns the length of the printable +representation of <[c]>. + +RETURNS +<<unctrl>> returns a string of the printable representation of <[c]>. + +<<unctrllen>> returns the length of the string which is the printable +representation of <[c]>. + +PORTABILITY +<<unctrl>> and <<unctrllen>> are not ANSI C. + +No supporting OS subroutines are required. +*/ + +/* + * Copyright (c) 1981, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <_ansi.h> + +#ifndef lint +static char sccsid[] = "@(#)unctrl.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +_CONST char * _CONST __unctrl[256] = { + "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", + "^H", "^I", "^J", "^K", "^L", "^M", "^N", "^O", + "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W", + "^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_", + " ", "!", "\"", "#", "$", "%", "&", "'", + "(", ")", "*", "+", ",", "-", ".", "/", + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", ":", ";", "<", "=", ">", "?", + "@", "A", "B", "C", "D", "E", "F", "G", + "H", "I", "J", "K", "L", "M", "N", "O", + "P", "Q", "R", "S", "T", "U", "V", "W", + "X", "Y", "Z", "[", "\\", "]", "^", "_", + "`", "a", "b", "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", "m", "n", "o", + "p", "q", "r", "s", "t", "u", "v", "w", + "x", "y", "z", "{", "|", "}", "~", "^?", + + "0x80", "0x81", "0x82", "0x83", "0x84", "0x85", "0x86", "0x87", + "0x88", "0x89", "0x8a", "0x8b", "0x8c", "0x8d", "0x8e", "0x8f", + "0x90", "0x91", "0x92", "0x93", "0x94", "0x95", "0x96", "0x97", + "0x98", "0x99", "0x9a", "0x9b", "0x9c", "0x9d", "0x9e", "0x9f", + "0xa0", "0xa1", "0xa2", "0xa3", "0xa4", "0xa5", "0xa6", "0xa7", + "0xa8", "0xa9", "0xaa", "0xab", "0xac", "0xad", "0xae", "0xaf", + "0xb0", "0xb1", "0xb2", "0xb3", "0xb4", "0xb5", "0xb6", "0xb7", + "0xb8", "0xb9", "0xba", "0xbb", "0xbc", "0xbd", "0xbe", "0xbf", + "0xc0", "0xc1", "0xc2", "0xc3", "0xc4", "0xc5", "0xc6", "0xc7", + "0xc8", "0xc9", "0xca", "0xcb", "0xcc", "0xcd", "0xce", "0xcf", + "0xd0", "0xd1", "0xd2", "0xd3", "0xd4", "0xd5", "0xd6", "0xd7", + "0xd8", "0xd9", "0xda", "0xdb", "0xdc", "0xdd", "0xde", "0xdf", + "0xe0", "0xe1", "0xe2", "0xe3", "0xe4", "0xe5", "0xe6", "0xe7", + "0xe8", "0xe9", "0xea", "0xeb", "0xec", "0xed", "0xee", "0xef", + "0xf0", "0xf1", "0xf2", "0xf3", "0xf4", "0xf5", "0xf6", "0xf7", + "0xf8", "0xf9", "0xfa", "0xfb", "0xfc", "0xfd", "0xfe", "0xff", +}; + +_CONST char __unctrllen[256] = { + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, +}; |