Imported Upstream version 3.2.2
[debian/gnuradio] / usrp2 / firmware / lib / printf.c
1 /* -*- c -*- */
2 /*
3  * Copyright 2007 Free Software Foundation, Inc.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /*
20  * Based on code from the SDCC z80 library ;)
21  */
22
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 static void 
27 _printn(unsigned u, unsigned base, char issigned,
28         void (*emitter)(char, void *), void *pData)
29 {
30   const char *_hex = "0123456789ABCDEF";
31   if (issigned && ((int)u < 0)) {
32     (*emitter)('-', pData);
33     u = (unsigned)-((int)u);
34   }
35   if (u >= base)
36     _printn(u/base, base, 0, emitter, pData);
37   (*emitter)(_hex[u%base], pData);
38 }
39
40 static void 
41 _printf(const char *format, void (*emitter)(char, void *),
42         void *pData, va_list va)
43 {
44   while (*format) {
45     if (*format != '%')
46       (*emitter)(*format, pData);
47     else {
48       switch (*++format) {
49       case 0:                   /* hit end of format string */
50         return;
51       case 'c':
52         {
53           char c = (char)va_arg(va, int);
54           (*emitter)(c, pData);
55           break;
56         }
57       case 'u':
58         {
59           unsigned u = va_arg(va, unsigned);
60           _printn(u, 10, 0, emitter, pData);
61           break;
62         }
63       case 'd':
64         {
65           unsigned u = va_arg(va, unsigned);
66           _printn(u, 10, 1, emitter, pData);
67           break;
68         }
69       case 'x':
70       case 'p':
71         {
72           unsigned u = va_arg(va, unsigned);
73           _printn(u, 16, 0, emitter, pData);
74           break;
75         }
76       case 's':
77         {
78           char *s = va_arg(va, char *);
79           while (*s) {
80             (*emitter)(*s, pData);
81             s++;
82           }
83           break;
84         }
85       }
86     }
87     format++;
88   }
89 }
90
91 static void 
92 _char_emitter(char c, void *pData __attribute__((unused)))
93 {
94   putchar(c);
95 }
96
97 int 
98 printf(const char *format, ...)
99 {
100   va_list va;
101   va_start(va, format);
102
103   _printf(format, _char_emitter, NULL, va);
104
105   va_end(va);
106
107   // wrong return value...
108   return 0;
109 }
110
111
112 #if 0
113
114 // Totally dangerous.  Don't use
115 static void 
116 _buf_emitter(char c, void *pData)
117 {
118   *((*((char **)pData)))++ = c;
119 }
120
121 int sprintf(char *pInto, const char *format, ...)
122 {
123   va_list va;
124   va_start(va, format);
125
126   _printf(format, _buf_emitter, &pInto, va);
127   *pInto++ = '\0';
128
129   va_end(va);
130
131   // FIXME wrong return value
132   return 0;
133 }
134 #endif