source: buchla-68k/iolib/dofmt.c

Last change on this file was 8973acd, checked in by Thomas Lopatic <thomas@…>, 7 years ago

No more warnings in libcio.

  • Property mode set to 100644
File size: 4.7 KB
Line 
1/*
2 =============================================================================
3 dofmt.c -- integer and string formatted output function
4 Version 4 -- 1987-06-12 -- D.N. Lynx Crowe
5
6 Supports most of the BSD & SysV Unix(tm) [f|s]printf conversion codes -
7 No floating point support in this implementation.
8
9 Returns a long instead of the int returned by the Unix(tm) functions.
10
11 WARNING - "Crufty code":
12
13 This code contains hacks to work around a bug in
14 the Alcyon C compiler, which, among other things,
15 doesn't handle % properly for longs. Conversions for
16 o and x are hacked to use shifts instead of modulus.
17
18 Alcyon 'cruft' is enabled by defining CRUFTY non-zero.
19 =============================================================================
20*/
21
22#define CRUFTY 1
23
24#include "ram.h"
25
26#define MAXDIGS 11
27#define HIBITL (1L << ( (8 * sizeof(int32_t)) - 1))
28
29#define LONGHMSK 0x0FFFFFFFL
30#define LONGOMSK 0x1FFFFFFFL
31
32#define tonum(x) ((x)-'0')
33#define todigit(x) ((x)+'0')
34
35int16_t dofmt_(int16_t (*putsub)(int16_t c), int8_t *format, va_list args)
36{
37 register int16_t fcode;
38
39 int16_t k,
40 n,
41 lzero,
42 count;
43
44 int16_t hradix,
45 length,
46 fplus,
47 fminus,
48 fblank,
49 fsharp,
50 flzero,
51 width,
52 prec;
53
54 register int8_t *bp, *p;
55
56 int8_t *prefix,
57 *tab,
58 buf[MAXDIGS];
59
60 int32_t val;
61
62 count = 0;
63
64 for ( ; ; ) {
65
66 for (bp = format;
67 (fcode = *format) NE '\0' AND fcode NE '%';
68 format++)
69 ;
70
71 if ((n = (int16_t)(format - bp))) {
72
73 count += n;
74
75 while (n--)
76 (*putsub)(*bp++);
77 }
78
79 if (fcode EQ '\0')
80 return(count);
81
82 fplus = fminus = fblank = fsharp = flzero = 0;
83
84 for ( ; ; ) {
85
86 switch (fcode = *++format) {
87
88 case '+':
89 fplus++;
90 continue;
91
92 case '-':
93 fminus++;
94 continue;
95
96 case ' ':
97 fblank++;
98 continue;
99
100 case '#':
101 fsharp++;
102 continue;
103 }
104
105 break;
106 }
107
108 if (fcode EQ '*') {
109
110 width = va_arg(args, int16_t);
111
112 if (width < 0) {
113
114 width = -width;
115 fminus++;
116 }
117
118 format++;
119
120 } else {
121
122 if (fcode EQ '0')
123 flzero++;
124
125 for (width = 0; isdigit(fcode = *format); format++)
126 width = width * 10 + tonum(fcode);
127 }
128
129 if (*format NE '.')
130 prec = -1;
131 else if (*++format EQ '*') {
132
133 prec = va_arg(args, int16_t);
134 format++;
135 } else
136 for (prec = 0; isdigit(fcode = *format); format++)
137 prec = prec * 10 + tonum(fcode);
138
139 length = 0;
140
141 if (*format EQ 'l') {
142
143 length++;
144 format++;
145 }
146
147 prefix = "";
148 lzero = 0;
149
150
151 switch (fcode = *format++) {
152
153 case 'd':
154 case 'u':
155 hradix = 10/2;
156 goto fixed;
157
158 case 'o':
159 hradix = 8/2;
160 goto fixed;
161
162 case 'X':
163 case 'x':
164 hradix = 16/2;
165
166 fixed:
167
168 if (prec < 0) {
169 if (flzero AND width > 0)
170 prec = width;
171 else
172 prec = 1;
173 }
174
175 if (length)
176 val = va_arg(args, int32_t);
177 else if (fcode EQ 'd')
178 val = va_arg(args, int16_t);
179 else
180 val = va_arg(args, uint16_t);
181
182 if (fcode EQ 'd') {
183
184 if (val < 0) {
185
186 prefix = "-";
187
188 if (val NE HIBITL)
189 val = -val;
190
191 } else if (fplus)
192 prefix = "+";
193 else if (fblank)
194 prefix = " ";
195 }
196
197 tab = (fcode EQ 'X') ?
198 "0123456789ABCDEF" : "0123456789abcdef";
199
200 p = bp = buf + MAXDIGS;
201
202
203 switch (hradix) {
204
205 case 4:
206
207 while (val NE 0) {
208
209 *--bp = tab[val & 0x07L];
210 val = (val >> 3) & LONGOMSK;
211 }
212
213 break;
214
215 case 5:
216
217 while (val NE 0) {
218
219#if CRUFTY
220 /* uldiv does a long divide */
221 /* ... with remainder in uldivr */
222
223 val = uldiv(val, 10L);
224 *--bp = tab[uldivr];
225#else
226 /* on most compilers, this works */
227
228 lowbit = val & 1;
229 val = (val >> 1) & ~HIBITL;
230 *--bp = tab[val % hradix * 2 + lowbit];
231 val /= hradix;
232#endif
233 }
234
235 break;
236
237 case 8:
238
239 while (val NE 0) {
240
241 *--bp = tab[val & 0x0FL];
242 val = (val >> 4) & LONGHMSK;
243 }
244 }
245
246 lzero = (int16_t)(bp - p + prec);
247
248 if (fsharp AND bp NE p)
249 switch (fcode) {
250
251 case 'o':
252 if (lzero < 1)
253 lzero = 1;
254 break;
255
256 case 'x':
257 case 'X':
258 prefix = "0x";
259 break;
260 }
261
262 break;
263
264
265 default:
266 buf[0] = (int8_t)fcode;
267 goto c_merge;
268
269 case 'c':
270 buf[0] = (int8_t)va_arg(args, int16_t);
271
272 c_merge:
273
274 p = (bp = &buf[0]) + 1;
275 break;
276
277 case 's':
278 p = bp = va_arg(args, int8_t *);
279
280 if (prec < 0)
281 p += strlen(bp);
282 else {
283 while (*p++ NE '\0' AND --prec GE 0)
284 ;
285 --p;
286 }
287
288 break;
289
290 case '\0':
291 return(-1);
292
293 }
294
295
296 if (lzero < 0)
297 lzero = 0;
298
299 k = (n = (int16_t)(p - bp)) + (lzero +
300 (prefix[0] EQ '\0' ? 0 : (prefix[1] EQ '\0' ? 1 : 2)));
301
302 count += (width >k) ? width : k;
303
304 if (!fminus)
305 while (--width GE k)
306 (*putsub)(' ');
307
308 while (*prefix NE '\0')
309 (*putsub)(*prefix++);
310
311 while (--lzero GE 0)
312 (*putsub)('0');
313
314 if (n > 0)
315 while (n--)
316 (*putsub)(*bp++);
317
318 while (--width GE k)
319 (*putsub)(' ');
320 }
321}
322
Note: See TracBrowser for help on using the repository browser.