XINU
doprnt.c
Go to the documentation of this file.
1 /* dprnt.c - _doprnt, _prtl2, _prtl8, _prtl10, _prtX16, _prtl16 */
2 
3 #include <stdarg.h>
4 
5 #define MAXSTR 80
6 #define NULL 0
7 #define PRECISION 6
8 
9 static void _prtl10(long num, char *str);
10 static void _prtl8(long num, char *str);
11 static void _prtX16(long num, char *str);
12 static void _prtl16(long num, char *str);
13 static void _prtl2(long num, char *str);
14 static void _prtdbl(double num, int precision, char *str);
15 
16 /*------------------------------------------------------------------------
17  * _doprnt - Format and write output using 'func' to write characters.
18  * (Patched for Sun3 by Shawn Ostermann.)
19  * All arguments passed as 4 bytes, long==int.
20  *------------------------------------------------------------------------
21  */
22 void _doprnt(
23  char *fmt,
24  va_list ap,
25  int (*func)(int)
26  )
27 {
28  int c;
29  int i;
30  int f; /* The format character (comes after %) */
31  char *str; /* Running pointer in string */
32  char string[20]; /* The string str points to this output */
33 
34  /* from number conversion */
35  int length; /* Length of string "str" */
36  char fill; /* Fill character (' ' or '0') */
37  int leftjust; /* 0 = right-justified, else left-just */
38  int fmax, fmin; /* Field specifications % MIN . MAX s */
39  int leading; /* No. of leading/trailing fill chars */
40  char sign; /* Set to '-' for negative decimals */
41  char digit1; /* Offset to add to first numeric digit */
42  long larg;
43  double darg;
44 
45  for (;;)
46  {
47  /* Echo characters until '%' or end of fmt string */
48  while ((c = *fmt++) != '%')
49  {
50  if (c == '\0')
51  {
52  return;
53  }
54  (*func) (c);
55  }
56  /* Echo "...%%..." as '%' */
57  if (*fmt == '%')
58  {
59  (*func) (*fmt++);
60  continue;
61  }
62  /* Check for "%-..." == Left-justified output */
63  if ((leftjust = ((*fmt == '-')) ? 1 : 0))
64  {
65  fmt++;
66  }
67  /* Allow for zero-filled numeric outputs ("%0...") */
68  fill = (*fmt == '0') ? *fmt++ : ' ';
69  /* Allow for minimum field width specifier for %d,u,x,o,c,s */
70  /* Also allow %* for variable width (%0* as well) */
71  fmin = 0;
72  if (*fmt == '*')
73  {
74  fmin = va_arg(ap, int);
75 
76  ++fmt;
77  }
78  else
79  {
80  while ('0' <= *fmt && *fmt <= '9')
81  {
82  fmin = fmin * 10 + *fmt++ - '0';
83  }
84  }
85  /* Allow for maximum string width for %s */
86  fmax = 0;
87  if (*fmt == '.')
88  {
89  if (*(++fmt) == '*')
90  {
91  fmax = va_arg(ap, int);
92  ++fmt;
93  }
94  else
95  {
96  while ('0' <= *fmt && *fmt <= '9')
97  {
98  fmax = fmax * 10 + *fmt++ - '0';
99  }
100  }
101  }
102 
103  str = string;
104  if ((f = *fmt++) == '\0')
105  {
106  (*func) ('%');
107  return;
108  }
109  sign = '\0'; /* sign == '-' for negative decimal */
110 
111  switch (f)
112  {
113  case 'c':
114  string[0] = va_arg(ap, int);
115  string[1] = '\0';
116  fmax = 0;
117  fill = ' ';
118  break;
119 
120  case 's':
121  str = va_arg(ap, char *);
122 
123  if (NULL == str)
124  {
125  str = "(null)";
126  }
127  fill = ' ';
128  break;
129 
130  case 'd':
131  larg = va_arg(ap, long);
132 
133  if (larg < 0)
134  {
135  sign = '-';
136  }
137  _prtl10(larg, str);
138  break;
139 
140  case 'f':
141  darg = va_arg(ap, double);
142 
143  if (darg < 0)
144  {
145  sign = '-';
146  }
147  _prtdbl(darg, PRECISION, str);
148  break;
149 
150  case 'u':
151  digit1 = '\0';
152  /* "negative" longs in unsigned format */
153  /* can't be computed with long division */
154  /* convert *args to "positive", digit1 */
155  /* = how much to add back afterwards */
156  larg = va_arg(ap, long);
157 
158  while (larg < 0)
159  {
160  larg -= 1000000000L;
161  ++digit1;
162  }
163  _prtl10(larg, str);
164  str[0] += digit1;
165  fmax = 0;
166  break;
167 
168  case 'o':
169  larg = va_arg(ap, long);
170 
171  _prtl8(larg, str);
172  fmax = 0;
173  break;
174 
175  case 'X':
176  larg = va_arg(ap, long);
177 
178  _prtX16(larg, str);
179  fmax = 0;
180  break;
181 
182  case 'x':
183  larg = va_arg(ap, long);
184 
185  _prtl16(larg, str);
186  fmax = 0;
187  break;
188 
189  case 'H':
190  larg = va_arg(ap, long);
191 
192  _prtX16(larg, str);
193 
194  larg = va_arg(ap, long);
195 
196  _prtX16(larg, str + 8);
197 
198  fmax = 0;
199  break;
200 
201  case 'h':
202  larg = va_arg(ap, long);
203 
204  _prtl16(larg, str);
205 
206  larg = va_arg(ap, long);
207 
208  _prtl16(larg, str + 8);
209 
210  fmax = 0;
211  break;
212 
213  case 'b':
214  larg = va_arg(ap, long);
215 
216  _prtl2(larg, str);
217  fmax = 0;
218  break;
219 
220  default:
221  (*func) (f);
222  break;
223  }
224  for (length = 0; str[length] != '\0'; length++)
225  {;
226  }
227  if (fmin > MAXSTR || fmin < 0)
228  {
229  fmin = 0;
230  }
231  if (fmax > MAXSTR || fmax < 0)
232  {
233  fmax = 0;
234  }
235  leading = 0;
236  if (fmax != 0 || fmin != 0)
237  {
238  if (fmax != 0)
239  {
240  if (length > fmax)
241  {
242  length = fmax;
243  }
244  }
245  if (fmin != 0)
246  {
247  leading = fmin - length;
248  }
249  if (sign == '-')
250  {
251  --leading;
252  }
253  }
254  if (sign == '-' && fill == '0')
255  {
256  (*func) (sign);
257  }
258  if (leftjust == 0)
259  {
260  for (i = 0; i < leading; i++)
261  {
262  (*func) (fill);
263  }
264  }
265  if (sign == '-' && fill == ' ')
266  {
267  (*func) (sign);
268  }
269  for (i = 0; i < length; i++)
270  {
271  (*func) (str[i]);
272  }
273  if (leftjust != 0)
274  {
275  for (i = 0; i < leading; i++)
276  (*func) (fill);
277  }
278  }
279 
280 }
281 
282 /*------------------------------------------------------------------------
283  * _prtl10 - Converts long to base 10 string.
284  *------------------------------------------------------------------------
285  */
286 static void _prtl10(
287  long num,
288  char *str
289  )
290 {
291  int i;
292  char temp[11];
293 
294  temp[0] = '\0';
295  temp[1] = ((num<0) ? -(num%10) : (num%10)) + '0';
296  num /= (num<0) ? -10 : 10;
297  for (i = 2; i <= 10; i++) {
298  temp[i] = num % 10 + '0';
299  num /= 10;
300  }
301  for (i = 10; temp[i] == '0'; i--);
302  if (i == 0)
303  i++;
304  while (i >= 0)
305  *str++ = temp[i--];
306 }
307 
308 /*------------------------------------------------------------------------
309  * _prtl8 - Converts long to base 8 string.
310  *------------------------------------------------------------------------
311  */
312 static void _prtl8(
313  long num,
314  char *str
315  )
316 {
317  int i;
318  char temp[12];
319 
320  temp[0] = '\0';
321  for (i = 1; i <= 11; i++)
322  {
323  temp[i] = (num & 07) + '0';
324  num = num >> 3;
325  }
326  temp[11] &= '3';
327  for (i = 11; temp[i] == '0'; i--);
328  if (i == 0)
329  i++;
330  while (i >= 0)
331  *str++ = temp[i--];
332 }
333 
334 /*------------------------------------------------------------------------
335  * _prtl16 - Converts long to lowercase hex string.
336  *------------------------------------------------------------------------
337  */
338 static void _prtl16(
339  long num,
340  char *str
341  )
342 {
343  int i;
344  char temp[9];
345 
346  temp[0] = '\0';
347  for (i = 1; i <= 8; i++)
348  {
349  temp[i] = "0123456789abcdef"[num & 0x0F];
350  num = num >> 4;
351  }
352  for (i = 8; temp[i] == '0'; i--);
353  if (i == 0)
354  i++;
355  while (i >= 0)
356  *str++ = temp[i--];
357 }
358 
359 /*------------------------------------------------------------------------
360  * _prtX16 - Converts long to uppercase hex string.
361  *------------------------------------------------------------------------
362  */
363 static void _prtX16(
364  long num,
365  char *str
366  )
367 {
368  int i;
369  char temp[9];
370 
371  temp[0] = '\0';
372  for (i = 1; i <= 8; i++)
373  {
374  temp[i] = "0123456789ABCDEF"[num & 0x0F];
375  num = num >> 4;
376  }
377  for (i = 8; temp[i] == '0'; i--);
378  if (i == 0)
379  i++;
380  while (i >= 0)
381  *str++ = temp[i--];
382 }
383 
384 /*------------------------------------------------------------------------
385  * _prtl2 - Converts long to binary string.
386  *------------------------------------------------------------------------
387  */
388 static void _prtl2(
389  long num,
390  char *str
391  )
392 {
393  int i;
394  char temp[35];
395 
396  temp[0] = '\0';
397  for (i = 1; i <= 32; i++)
398  {
399  temp[i] = ((num % 2) == 0) ? '0' : '1';
400  num = num >> 1;
401  }
402  for (i = 32; temp[i] == '0'; i--);
403  if (i == 0)
404  i++;
405  while (i >= 0)
406  *str++ = temp[i--];
407 }
408 
409 /*------------------------------------------------------------------------
410  * _prtdbl - Converts double to binary string.
411  *------------------------------------------------------------------------
412  */
413 static void _prtdbl(
414  double num,
415  int precision,
416  char *str
417  )
418 {
419  int i,mp;
420  long w,p;
421 
422  for(i = 0, mp = 1; i < precision; i++, mp *= 10);
423 
424  num = ((num<0) ? -(num) : (num));
425  w = (long)(num);
426  p = (long)(num * mp) - (long)(w * mp);
427 
428  _prtl10(w, str);
429  while(*str != '\0') { str++; }
430  *str++ = '.';
431  _prtl10(p, str);
432 }
#define NULL
Definition: doprnt.c:6
static void _prtl2(long num, char *str)
Definition: doprnt.c:388
#define PRECISION
Definition: doprnt.c:7
static void _prtl10(long num, char *str)
Definition: doprnt.c:286
static void _prtX16(long num, char *str)
Definition: doprnt.c:363
static void _prtl16(long num, char *str)
Definition: doprnt.c:338
#define MAXSTR
Definition: doprnt.c:5
#define va_arg(va, type)
可変長引数の値を返し、次の引数へ進む。 「va_start()とva_end()の間」もしくは「va_copy()とva_end()の間...
Definition: stdarg.h:34
可変長引数を実現するための宣言およびマクロ
void _doprnt(char *fmt, va_list ap, int(*func)(int))
Definition: doprnt.c:22
static void _prtdbl(double num, int precision, char *str)
Definition: doprnt.c:413
__builtin_va_list va_list
可変個の実引数を扱うための情報を保持するための型(__builtin_va_listはGCCに定義された型) ...
Definition: stdarg.h:7
static void _prtl8(long num, char *str)
Definition: doprnt.c:312