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

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

Added include files for global functions and variables.

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