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

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

Removed form-feed comments.

  • Property mode set to 100644
File size: 4.8 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#define max(a,b) ((a)>(b)?(a):(b))
35#define min(a,b) ((a)<(b)?(a):(b))
36
37int32_t dofmt_(int16_t (*putsub)(int16_t c), int8_t *format, va_list args)
38{
39 register int16_t fcode;
40
41 int32_t k,
42 n,
43 lzero,
44 count;
45
46 int16_t hradix,
47 lowbit,
48 length,
49 fplus,
50 fminus,
51 fblank,
52 fsharp,
53 flzero,
54 width,
55 prec;
56
57 register int8_t *bp, *p;
58
59 int8_t *prefix,
60 *tab,
61 buf[MAXDIGS];
62
63 int32_t val;
64
65 count = 0;
66
67 for ( ; ; ) {
68
69 for (bp = format;
70 (fcode = *format) NE '\0' AND fcode NE '%';
71 format++)
72 ;
73
74 if (n = (int32_t)format - (int32_t)bp) {
75
76 count += n;
77
78 while (n--)
79 (*putsub)(*bp++);
80 }
81
82 if (fcode EQ '\0')
83 return(count);
84
85 fplus = fminus = fblank = fsharp = flzero = 0;
86
87 for ( ; ; ) {
88
89 switch (fcode = *++format) {
90
91 case '+':
92 fplus++;
93 continue;
94
95 case '-':
96 fminus++;
97 continue;
98
99 case ' ':
100 fblank++;
101 continue;
102
103 case '#':
104 fsharp++;
105 continue;
106 }
107
108 break;
109 }
110
111 if (fcode EQ '*') {
112
113 width = va_arg(args, int16_t);
114
115 if (width < 0) {
116
117 width = -width;
118 fminus++;
119 }
120
121 format++;
122
123 } else {
124
125 if (fcode EQ '0')
126 flzero++;
127
128 for (width = 0; isdigit(fcode = *format); format++)
129 width = width * 10 + tonum(fcode);
130 }
131
132 if (*format NE '.')
133 prec = -1;
134 else if (*++format EQ '*') {
135
136 prec = va_arg(args, int16_t);
137 format++;
138 } else
139 for (prec = 0; isdigit(fcode = *format); format++)
140 prec = prec * 10 + tonum(fcode);
141
142 length = 0;
143
144 if (*format EQ 'l') {
145
146 length++;
147 format++;
148 }
149
150 prefix = "";
151 lzero = 0;
152
153
154 switch (fcode = *format++) {
155
156 case 'd':
157 case 'u':
158 hradix = 10/2;
159 goto fixed;
160
161 case 'o':
162 hradix = 8/2;
163 goto fixed;
164
165 case 'X':
166 case 'x':
167 hradix = 16/2;
168
169 fixed:
170
171 if (prec < 0)
172 if (flzero AND width > 0)
173 prec = width;
174 else
175 prec = 1;
176
177 if (length)
178 val = va_arg(args, int32_t);
179 else if (fcode EQ 'd')
180 val = va_arg(args, int16_t);
181 else
182 val = va_arg(args, uint16_t);
183
184 if (fcode EQ 'd') {
185
186 if (val < 0) {
187
188 prefix = "-";
189
190 if (val NE HIBITL)
191 val = -val;
192
193 } else if (fplus)
194 prefix = "+";
195 else if (fblank)
196 prefix = " ";
197 }
198
199 tab = (fcode EQ 'X') ?
200 "0123456789ABCDEF" : "0123456789abcdef";
201
202 p = bp = buf + MAXDIGS;
203
204
205 switch (hradix) {
206
207 case 4:
208
209 while (val NE 0) {
210
211 *--bp = tab[val & 0x07L];
212 val = (val >> 3) & LONGOMSK;
213 }
214
215 break;
216
217 case 5:
218
219 while (val NE 0) {
220
221#if CRUFTY
222 /* uldiv does a long divide */
223 /* ... with remainder in uldivr */
224
225 val = uldiv(val, 10L);
226 *--bp = tab[uldivr];
227#else
228 /* on most compilers, this works */
229
230 lowbit = val & 1;
231 val = (val >> 1) & ~HIBITL;
232 *--bp = tab[val % hradix * 2 + lowbit];
233 val /= hradix;
234#endif
235 }
236
237 break;
238
239 case 8:
240
241 while (val NE 0) {
242
243 *--bp = tab[val & 0x0FL];
244 val = (val >> 4) & LONGHMSK;
245 }
246 }
247
248 lzero = (int32_t)bp - (int32_t)p + (int32_t)prec;
249
250 if (fsharp AND bp NE p)
251 switch (fcode) {
252
253 case 'o':
254 if (lzero < 1)
255 lzero = 1;
256 break;
257
258 case 'x':
259 case 'X':
260 prefix = "0x";
261 break;
262 }
263
264 break;
265
266
267 default:
268 buf[0] = fcode;
269 goto c_merge;
270
271 case 'c':
272 buf[0] = va_arg(args, int16_t);
273
274 c_merge:
275
276 p = (bp = &buf[0]) + 1;
277 break;
278
279 case 's':
280 p = bp = va_arg(args, int8_t *);
281
282 if (prec < 0)
283 p += strlen(bp);
284 else {
285 while (*p++ NE '\0' AND --prec GE 0)
286 ;
287 --p;
288 }
289
290 break;
291
292 case '\0':
293 return(-1);
294
295 }
296
297
298 if (lzero < 0)
299 lzero = 0;
300
301 k = (n = (int32_t)p - (int32_t)bp) + (int32_t)(lzero +
302 (prefix[0] EQ '\0' ? 0 : (prefix[1] EQ '\0' ? 1 : 2)));
303
304 count += (width >k) ? width : k;
305
306 if (!fminus)
307 while (--width GE k)
308 (*putsub)(' ');
309
310 while (*prefix NE '\0')
311 (*putsub)(*prefix++);
312
313 while (--lzero GE 0)
314 (*putsub)('0');
315
316 if (n > 0)
317 while (n--)
318 (*putsub)(*bp++);
319
320 while (--width GE k)
321 (*putsub)(' ');
322 }
323}
324
Note: See TracBrowser for help on using the repository browser.