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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [bios/] [printk.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 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
// s80x86 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 s80x86.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
#include <stddef.h>
19
#include <stdarg.h>
20
 
21
#include "serial.h"
22
 
23
struct string_specifier {
24
    int precision;
25
    int zero_pad;
26
};
27
 
28
struct string_formatter {
29
    char *buf;
30
    size_t len;
31
    size_t maxlen;
32
    const char *fmt;
33
    struct string_specifier specifier;
34
};
35
 
36
void output_char(struct string_formatter *formatter, int c)
37
{
38
    if (formatter->len < formatter->maxlen - 1) {
39
        *formatter->buf++ = c;
40
        ++formatter->len;
41
    }
42
}
43
 
44
void output_buf_reversed(struct string_formatter *formatter,
45
                         const char *buf,
46
                         int nchars)
47
{
48
    const char hex_val[] = {'0', '1', '2', '3', '4', '5', '6', '7',
49
                            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
50
 
51
    for (nchars = nchars - 1; nchars >= 0; --nchars) {
52
        unsigned digit = buf[nchars];
53
        output_char(formatter, hex_val[digit]);
54
    }
55
}
56
 
57
void output_zero_padding(struct string_formatter *formatter, int num_zeroes)
58
{
59
    int i;
60
 
61
    if (formatter->specifier.zero_pad && num_zeroes > 0)
62
        for (i = 0; i < num_zeroes; ++i)
63
            output_char(formatter, '0');
64
}
65
 
66
void output_unsigned(struct string_formatter *formatter,
67
                     unsigned val,
68
                     unsigned base)
69
{
70
    char reversal_buf[32];
71
    int nchars = 0;
72
 
73
    do {
74
        reversal_buf[nchars++] = val % base;
75
        val /= base;
76
    } while (val);
77
 
78
    output_zero_padding(formatter, formatter->specifier.precision - nchars);
79
    output_buf_reversed(formatter, reversal_buf, nchars);
80
}
81
 
82
void output_string(struct string_formatter *formatter, const char *str)
83
{
84
    while (*str)
85
        output_char(formatter, *str++);
86
}
87
 
88
void output_pointer(struct string_formatter *formatter, const void *ptr)
89
{
90
    unsigned val = (unsigned)ptr;
91
 
92
    formatter->specifier.precision = 4;
93
    formatter->specifier.zero_pad = 1;
94
 
95
    if (!val) {
96
        output_string(formatter, "(null)");
97
    } else {
98
        output_string(formatter, "0x");
99
        output_unsigned(formatter, val, 16);
100
    }
101
}
102
 
103
void output_item(struct string_formatter *formatter, va_list *ap)
104
{
105
    switch (*formatter->fmt) {
106
    case 's': output_string(formatter, va_arg(*ap, const char *)); break;
107
    case 'u': output_unsigned(formatter, va_arg(*ap, unsigned), 10); break;
108
    case 'x': output_unsigned(formatter, va_arg(*ap, unsigned), 16); break;
109
    case 'p': output_pointer(formatter, va_arg(*ap, const void *)); break;
110
    case 'c':
111
    default: output_char(formatter, va_arg(*ap, int)); break;
112
    }
113
 
114
    ++formatter->fmt;
115
}
116
 
117
void read_precision(struct string_formatter *formatter)
118
{
119
    formatter->specifier.precision = 0;
120
 
121
    while (*formatter->fmt >= '0' && *formatter->fmt <= '9') {
122
        formatter->specifier.precision *= 10;
123
        formatter->specifier.precision += *formatter->fmt - '0';
124
        formatter->fmt++;
125
    }
126
}
127
 
128
void read_zero_pad(struct string_formatter *formatter)
129
{
130
    formatter->specifier.zero_pad = 0;
131
 
132
    if (*formatter->fmt == '0') {
133
        formatter->specifier.zero_pad = 1;
134
        formatter->fmt++;
135
    }
136
}
137
 
138
void parse_specifier(struct string_formatter *formatter)
139
{
140
    formatter->fmt++;
141
 
142
    read_zero_pad(formatter);
143
    read_precision(formatter);
144
}
145
 
146
size_t string_format(char *buf, size_t maxlen, const char *fmt, va_list *ap)
147
{
148
    struct string_formatter formatter = {
149
        .buf = buf, .maxlen = maxlen, .fmt = fmt, .len = 0,
150
    };
151
 
152
    while (formatter.len < maxlen - 1 && *formatter.fmt) {
153
        if (*formatter.fmt == '%') {
154
            parse_specifier(&formatter);
155
            output_item(&formatter, ap);
156
        } else {
157
            output_char(&formatter, *formatter.fmt++);
158
        }
159
    }
160
 
161
    *formatter.buf = '\0';
162
 
163
    return formatter.len;
164
}
165
 
166
void printk(const char *fmt, ...)
167
{
168
    static char printk_buf[128];
169
    va_list ap;
170
 
171
    va_start(ap, fmt);
172
    string_format(printk_buf, sizeof(printk_buf), fmt, &ap);
173
    va_end(ap);
174
 
175
    putstr(printk_buf);
176
}

powered by: WebSVN 2.1.0

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