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

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

Added missing includes and declarations.

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