OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [sw/] [mini-libc/] [printf.c] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 csantifort
/*----------------------------------------------------------------
2
//                                                              //
3
//  printf.c                                                    //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  printf functions for the mini-libc library.                 //
10
//                                                              //
11
//  Author(s):                                                  //
12
//      - Conor Santifort, csantifort.amber@gmail.com           //
13
//                                                              //
14
//////////////////////////////////////////////////////////////////
15
//                                                              //
16
// Copyright (C) 2010 Authors and OPENCORES.ORG                 //
17
//                                                              //
18
// This source file may be used and distributed without         //
19
// restriction provided that this copyright statement is not    //
20
// removed from the file and that any derivative work contains  //
21
// the original copyright notice and the associated disclaimer. //
22
//                                                              //
23
// This source file is free software; you can redistribute it   //
24
// and/or modify it under the terms of the GNU Lesser General   //
25
// Public License as published by the Free Software Foundation; //
26
// either version 2.1 of the License, or (at your option) any   //
27
// later version.                                               //
28
//                                                              //
29
// This source is distributed in the hope that it will be       //
30
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
31
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
32
// PURPOSE.  See the GNU Lesser General Public License for more //
33
// details.                                                     //
34
//                                                              //
35
// You should have received a copy of the GNU Lesser General    //
36
// Public License along with this source; if not, download it   //
37
// from http://www.opencores.org/lgpl.shtml                     //
38
//                                                              //
39
----------------------------------------------------------------*/
40
 
41
#include "stdio.h"
42
 
43
/* Defines */
44
#define PAD_RIGHT 1
45
#define PAD_ZERO  2
46
 
47
/* the following should be enough for 32 bit int */
48
#define PRINT_BUF_LEN 16
49
 
50
 
51
inline void outbyte(char** dst, char c)
52
{
53
/* Note the standard number for stdout in Unix is 1 but
54
   I use 0 here, because I don't support stdin or stderr
55
*/
56
if (*dst)
57
    *(*dst)++ = c;
58
else
59
    _outbyte(c);
60
}
61
 
62
 
63
int sprintf(char* dst, const char *fmt, ...)
64
{
65
    register unsigned long *varg = (unsigned long *)(&fmt);
66
    *varg++;
67
 
68
    /* Need to pass a pointer to a pointer to the location to
69
       write the character, to that the pointer to the location
70
       can be incremented by the final outpute function
71
    */
72
 
73
    return print(&dst, fmt, varg);
74
}
75
 
76
int printf(const char *fmt, ...)
77
{
78
    register unsigned long *varg = (unsigned long *)(&fmt);
79
    *varg++;
80
    char *dst = 0;
81
 
82
    return print((char**)&dst, fmt, varg);
83
}
84
 
85
/*  printf supports the following types of syntax ---
86
    char *ptr = "Hello world!";
87
    char *np = 0;
88
    int i = 5;
89
    unsigned int bs = sizeof(int)*8;
90
    int mi;
91
    mi = (1 << (bs-1)) + 1;
92
 
93
    printf("%s\n", ptr);
94
    printf("printf test\n");
95
    printf("%s is null pointer\n", np);
96
    printf("%d = 5\n", i);
97
    printf("%d = - max int\n", mi);
98
    printf("char %c = 'a'\n", 'a');
99
    printf("hex %x = ff\n", 0xff);
100
    printf("hex %02x = 00\n", 0);
101
    printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
102
    printf("%d %s(s)%", 0, "message");
103
    printf("\n");
104
    printf("%d %s(s) with %%\n", 0, "message");
105
 
106
*/
107
 
108
int print(char** dst, const char *format, unsigned long *varg)
109
{
110
    register int width, pad;
111
    register int pc = 0;
112
    char scr[2];
113
 
114
    for (; *format != 0; ++format) {
115
       if (*format == '%') {
116
          ++format;
117
          width = pad = 0;
118
          if (*format == '\0') break;
119
          if (*format == '%') goto out;
120
          if (*format == '-') {
121
             ++format;
122
             pad = PAD_RIGHT;
123
          }
124
          while (*format == '0') {
125
             ++format;
126
             pad |= PAD_ZERO;
127
          }
128
          for ( ; *format >= '0' && *format <= '9'; ++format) {
129
             width *= 10;
130
             width += *format - '0';
131
          }
132
          if( *format == 's' ) {
133
             register char *s = *((char **)varg++);
134
             pc += prints (dst, s?s:"(null)", width, pad);
135
             continue;
136
          }
137
          if( *format == 'd' ) {
138
             pc += printi (dst, *varg++, 10, 1, width, pad, 'a');
139
             continue;
140
          }
141
          if( *format == 'x' ) {
142
             pc += printi (dst, *varg++, 16, 0, width, pad, 'a');
143
             continue;
144
          }
145
          if( *format == 'X' ) {
146
             pc += printi (dst, *varg++, 16, 0, width, pad, 'A');
147
             continue;
148
          }
149
          if( *format == 'u' ) {
150
             pc += printi (dst, *varg++, 10, 0, width, pad, 'a');
151
             continue;
152
          }
153
          if( *format == 'c' ) {
154
             /* char are converted to int then pushed on the stack */
155
             scr[0] = *varg++;
156
             scr[1] = '\0';
157
             pc += prints (dst, scr, width, pad);
158
             continue;
159
          }
160
       }
161
       else {
162
       out:
163
          if (*format=='\n') outbyte(dst,'\r');
164
          outbyte (dst, *format);
165
          ++pc;
166
       }
167
    }
168
 
169
    return pc;
170
}
171
 
172
 
173
/* Print a string - no formatting characters will be interpreted here */
174
int prints(char** dst, const char *string, int width, int pad)
175
{
176
    register int pc = 0, padchar = ' ';
177
 
178
    if (width > 0) {
179
       register int len = 0;
180
       register const char *ptr;
181
       for (ptr = string; *ptr; ++ptr) ++len;
182
       if (len >= width) width = 0;
183
       else width -= len;
184
       if (pad & PAD_ZERO) padchar = '0';
185
    }
186
    if (!(pad & PAD_RIGHT)) {
187
       for ( ; width > 0; --width) {
188
          outbyte(dst, padchar);
189
          ++pc;
190
       }
191
    }
192
    for ( ; *string ; ++string) {
193
       outbyte(dst, *string);
194
       ++pc;
195
    }
196
    for ( ; width > 0; --width) {
197
       outbyte(dst, padchar);
198
       ++pc;
199
    }
200
 
201
    return pc;
202
}
203
 
204
 
205
/* Printf an integer */
206
int printi(char** dst, unsigned long i, int b, int sg, int width, int pad, int letbase)
207
{
208
    char print_buf[PRINT_BUF_LEN];
209
    char *s;
210
    int t, neg = 0, pc = 0;
211
    unsigned int u = i;
212
 
213
    if (i == 0) {
214
       print_buf[0] = '0';
215
       print_buf[1] = '\0';
216
       return prints (dst, print_buf, width, pad);
217
    }
218
 
219
    if (sg && b == 10 && i < 0) {
220
       neg = 1;
221
       u = -i;
222
    }
223
 
224
    s = print_buf + PRINT_BUF_LEN-1;
225
    *s = '\0';
226
 
227
    while (u) {
228
       if ( b == 16 )    t = u & 0xf;                  /* hex modulous */
229
       else              t = u - ( _div (u, b) * b );  /* Modulous */
230
 
231
       if( t >= 10 )
232
          t += letbase - '0' - 10;
233
       *--s = t + '0';
234
 
235
    /*   u /= b;  */
236
       if ( b == 16)  u = u >> 4;    /* divide by 16 */
237
       else           u = _div(u, b);
238
    }
239
 
240
    if (neg) {
241
       if( width && (pad & PAD_ZERO) ) {
242
          /* _outbyte('-'); */
243
          outbyte(dst,'-');
244
          ++pc;
245
          --width;
246
       }
247
       else {
248
          *--s = '-';
249
       }
250
    }
251
 
252
    return pc + prints (dst, s, width, pad);
253
}
254
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.