Contiki 3.x
sprintf.c
1 /*
2  File: printf.c
3 
4  Copyright (c) 2004,2008 Kustaa Nyholm / SpareTimeLabs
5 
6  All rights reserved.
7 
8  Redistribution and use in source and binary forms, with or without modification,
9  are permitted provided that the following conditions are met:
10 
11  Redistributions of source code must retain the above copyright notice, this list
12  of conditions and the following disclaimer.
13 
14  Redistributions in binary form must reproduce the above copyright notice, this
15  list of conditions and the following disclaimer in the documentation and/or other
16  materials provided with the distribution.
17 
18  Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its
19  contributors may be used to endorse or promote products derived from this software
20  without specific prior written permission.
21 
22  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  OF SUCH DAMAGE.
32 
33  */
34 
35 /*
36  * This is BSD code obtained from http://www.sparetimelabs.com/printfrevisited/index.html
37  * From the web page:
38  * "The code is GPL and BSD lincensed, download the BSD licensed version from the link
39  * above or use the GPL licensed code from this page below."
40  *
41  * modified by Beshr Al Nahas <beshr@sics.se> and Simon Duquennoy <simonduq@sics.se>
42  */
43 
44 #include "contiki-conf.h"
45 #include <stdarg.h>
46 #include <ctype.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include "dev/uart0.h"
51 
52 static char *bf, buf[14], uc, zs;
53 static unsigned int num;
54 
55 static void
56 out(char c)
57 {
58  *bf++ = c;
59 }
60 static void
61 outDgt(char dgt)
62 {
63  out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10));
64  zs = 1;
65 }
66 static void
67 divOut(unsigned int div)
68 {
69  unsigned char dgt = 0;
70  while(num >= div) {
71  num -= div;
72  dgt++;
73  }
74  if(zs || dgt > 0) {
75  outDgt(dgt);
76  }
77 }
78 int
79 vsnprintf(char *str, size_t n, const char *fmt, __VALIST va)
80 {
81  char ch, *p, *str_orig = str;
82  char next_ch;
83 
84  while((ch = *fmt++) && str - str_orig < n) {
85  if(ch != '%') {
86  *str++ = ch;
87  } else {
88  char lz = 0;
89  char w = 0;
90  ch = *(fmt++);
91  if(ch == '0') {
92  ch = *(fmt++);
93  lz = 1;
94  }
95  if(ch >= '0' && ch <= '9') {
96  w = 0;
97  while(ch >= '0' && ch <= '9') {
98  w = (((w << 2) + w) << 1) + ch - '0';
99  ch = *fmt++;
100  }
101  }
102  bf = buf;
103  p = bf;
104  zs = 0;
105 start_format:
106  next_ch = *fmt;
107  switch(ch) {
108  case 0:
109  goto abort;
110  case 'l':
111  if(next_ch == 'x'
112  || next_ch == 'X'
113  || next_ch == 'u'
114  || next_ch == 'd') {
115  ch = *(fmt++);
116  goto start_format;
117  }
118  case 'u':
119  case 'd':
120  num = va_arg(va, unsigned int);
121  if(ch == 'd' && (int)num < 0) {
122  num = -(int)num;
123  out('-');
124  }
125  divOut(1000000000);
126  divOut(100000000);
127  divOut(10000000);
128  divOut(1000000);
129  divOut(100000);
130  divOut(10000);
131  divOut(1000);
132  divOut(100);
133  divOut(10);
134  outDgt(num);
135  break;
136  case 'p':
137  case 'x':
138  case 'X':
139  uc = ch == 'X';
140  num = va_arg(va, unsigned int);
141  /* divOut(0x100000000UL); */
142  divOut(0x10000000);
143  divOut(0x1000000);
144  divOut(0x100000);
145  divOut(0x10000);
146  divOut(0x1000);
147  divOut(0x100);
148  divOut(0x10);
149  outDgt(num);
150  break;
151  case 'c':
152  out((char)(va_arg(va, int)));
153  break;
154  case 's':
155  p = va_arg(va, char *);
156  break;
157  case '%':
158  out('%');
159  default:
160  break;
161  }
162  *bf = 0;
163  bf = p;
164 
165  while(*bf++ && w > 0) {
166  w--;
167  }
168  while(w-- > 0) {
169  if(str - str_orig < n) {
170  *str++ = lz ? '0' : ' ';
171  } else {
172  goto abort;
173  }
174  }
175  while((ch = *p++)) {
176  if(str - str_orig < n) {
177  *str++ = ch;
178  } else {
179  goto abort;
180  }
181  }
182  }
183  }
184 
185 abort:
186  if(str - str_orig < n) {
187  *str = '\0';
188  } else {
189  *(--str) = '\0';
190  } return str - str_orig;
191 }
192 int
193 sprintf(char *str, const char *fmt, ...)
194 {
195  int m;
196  __VALIST va;
197  va_start(va, fmt);
198  m = vsnprintf(str, 0xffffffff, fmt, va);
199  va_end(va);
200  return m;
201 }
202 int
203 snprintf(char *str, size_t n, const char *fmt, ...)
204 {
205  int m;
206  __VALIST va;
207  va_start(va, fmt);
208  m = vsnprintf(str, n, fmt, va);
209  va_end(va);
210  return m;
211 }
212 int
213 printf(const char *fmt, ...)
214 {
215  int m, i;
216  char str[256];
217  __VALIST va;
218  va_start(va, fmt);
219  m = vsnprintf(str, sizeof(str), fmt, va);
220  va_end(va);
221  for(i = 0; i < m; i++) {
222  putchar(str[i]);
223  }
224  return m;
225 }
226 int
227 puts(const char *s)
228 {
229  char c;
230  while((c = *s++) != '\0') {
231  putchar(c);
232  }
233  putchar('\n');
234  return strlen(s);
235 }