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

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

Don't mix function and variable declarations.

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