00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifdef _KERNEL
00041 #include <types.h>
00042 #include <lib.h>
00043 #define assert KASSERT
00044 #else
00045
00046 #include <sys/types.h>
00047 #include <assert.h>
00048 #include <stdint.h>
00049 #include <stdio.h>
00050 #include <string.h>
00051 #endif
00052
00053 #include <stdarg.h>
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #define USE_LONGLONG
00065
00066
00067
00068
00069 #ifdef USE_LONGLONG
00070 #define INTTYPE long long
00071 #else
00072 #define INTTYPE long
00073 #endif
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #define NUMBER_BUF_SIZE ((sizeof(INTTYPE) * CHAR_BIT) / 3 + 2)
00085
00086
00087
00088
00089 typedef struct {
00090
00091 void (*sendfunc)(void *clientdata, const char *str, size_t len);
00092 void *clientdata;
00093
00094
00095 va_list ap;
00096
00097
00098 int charcount;
00099
00100
00101 int in_pct;
00102
00103
00104 enum {
00105 INTSZ,
00106 LONGSZ,
00107 #ifdef USE_LONGLONG
00108 LLONGSZ,
00109 #endif
00110 } size;
00111
00112
00113 unsigned INTTYPE num;
00114
00115
00116 int sign;
00117
00118
00119 int spacing;
00120
00121
00122 int rightspc;
00123
00124
00125 int fillchar;
00126
00127
00128 int base;
00129
00130
00131 int baseprefix;
00132
00133
00134 int altformat;
00135 } PF;
00136
00137
00138
00139
00140
00141
00142
00143 static
00144 void
00145 __pf_print(PF *pf, const char *txt, size_t len)
00146 {
00147 pf->sendfunc(pf->clientdata, txt, len);
00148 pf->charcount += len;
00149 }
00150
00151
00152
00153
00154 static
00155 void
00156 __pf_endfield(PF *pf)
00157 {
00158 pf->in_pct = 0;
00159 pf->size = INTSZ;
00160 pf->num = 0;
00161 pf->sign = 0;
00162 pf->spacing = 0;
00163 pf->rightspc = 0;
00164 pf->fillchar = ' ';
00165 pf->base = 0;
00166 pf->baseprefix = 0;
00167 pf->altformat = 0;
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 static
00179 void
00180 __pf_modifier(PF *pf, int ch)
00181 {
00182 switch (ch) {
00183 case '#':
00184 pf->altformat = 1;
00185 break;
00186 case '-':
00187 pf->rightspc = 1;
00188 break;
00189 case 'l':
00190 if (pf->size==LONGSZ) {
00191 #ifdef USE_LONGLONG
00192 pf->size = LLONGSZ;
00193 #endif
00194 }
00195 else {
00196 pf->size = LONGSZ;
00197 }
00198 break;
00199 case '0':
00200 if (pf->spacing>0) {
00201
00202
00203
00204
00205 pf->spacing = pf->spacing*10;
00206 }
00207 else {
00208
00209
00210
00211 pf->fillchar = '0';
00212 }
00213 break;
00214 default:
00215
00216
00217
00218
00219
00220 assert(ch>'0' && ch<='9');
00221
00222
00223
00224
00225 pf->spacing = pf->spacing*10 + (ch-'0');
00226 break;
00227 }
00228 }
00229
00230
00231
00232
00233
00234
00235 static
00236 void
00237 __pf_getnum(PF *pf, int ch)
00238 {
00239 if (ch=='p') {
00240
00241
00242
00243
00244
00245
00246 pf->num = (uintptr_t) va_arg(pf->ap, void *);
00247 }
00248 else if (ch=='d') {
00249
00250 INTTYPE signednum=0;
00251 switch (pf->size) {
00252 case INTSZ:
00253
00254 signednum = va_arg(pf->ap, int);
00255 break;
00256 case LONGSZ:
00257
00258 signednum = va_arg(pf->ap, long);
00259 break;
00260 #ifdef USE_LONGLONG
00261 case LLONGSZ:
00262
00263 signednum = va_arg(pf->ap, long long);
00264 break;
00265 #endif
00266 }
00267
00268
00269
00270
00271 if (signednum < 0) {
00272 pf->sign = -1;
00273 pf->num = -signednum;
00274 }
00275 else {
00276 pf->num = signednum;
00277 }
00278 }
00279 else {
00280
00281 switch (pf->size) {
00282 case INTSZ:
00283
00284 pf->num = va_arg(pf->ap, unsigned int);
00285 break;
00286 case LONGSZ:
00287
00288 pf->num = va_arg(pf->ap, unsigned long);
00289 break;
00290 #ifdef USE_LONGLONG
00291 case LLONGSZ:
00292
00293 pf->num = va_arg(pf->ap, unsigned long long);
00294 break;
00295 #endif
00296 }
00297 }
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 static
00311 void
00312 __pf_setbase(PF *pf, int ch)
00313 {
00314 switch (ch) {
00315 case 'd':
00316 case 'u':
00317 pf->base = 10;
00318 break;
00319 case 'x':
00320 case 'p':
00321 pf->base = 16;
00322 break;
00323 case 'o':
00324 pf->base = 8;
00325 break;
00326 }
00327 if (pf->altformat || ch=='p') {
00328 pf->baseprefix = 1;
00329 }
00330 }
00331
00332
00333
00334
00335 static
00336 void
00337 __pf_fill(PF *pf, int spc)
00338 {
00339 char f = pf->fillchar;
00340 int i;
00341 for (i=0; i<spc; i++) {
00342 __pf_print(pf, &f, 1);
00343 }
00344 }
00345
00346
00347
00348
00349
00350
00351
00352 static
00353 void
00354 __pf_printstuff(PF *pf,
00355 const char *prefix, const char *prefix2,
00356 const char *stuff)
00357 {
00358
00359 int len = strlen(prefix)+strlen(prefix2)+strlen(stuff);
00360
00361
00362 int spc = pf->spacing;
00363 if (spc > len) {
00364 spc -= len;
00365 }
00366 else {
00367 spc = 0;
00368 }
00369
00370
00371 if (spc > 0 && pf->rightspc==0 && pf->fillchar!='0') {
00372 __pf_fill(pf, spc);
00373 }
00374
00375
00376 __pf_print(pf, prefix, strlen(prefix));
00377 __pf_print(pf, prefix2, strlen(prefix2));
00378
00379
00380 if (spc > 0 && pf->rightspc==0 && pf->fillchar=='0') {
00381 __pf_fill(pf, spc);
00382 }
00383
00384
00385 __pf_print(pf, stuff, strlen(stuff));
00386
00387
00388 if (spc > 0 && pf->rightspc!=0) {
00389 __pf_fill(pf, spc);
00390 }
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400 static
00401 void
00402 __pf_printnum(PF *pf)
00403 {
00404
00405 const char *const digits = "0123456789abcdef";
00406
00407 char buf[NUMBER_BUF_SIZE];
00408 char *x;
00409 unsigned INTTYPE xnum;
00410 const char *bprefix;
00411 const char *sprefix;
00412
00413
00414 x = buf+sizeof(buf)-1;
00415
00416
00417 *x-- = 0;
00418
00419
00420 xnum = pf->num;
00421
00422
00423
00424
00425
00426 do {
00427
00428
00429
00430
00431 *x = digits[xnum % pf->base];
00432
00433
00434
00435
00436 x--;
00437
00438
00439
00440
00441 xnum = xnum / pf->base;
00442
00443
00444
00445
00446 } while (xnum > 0);
00447
00448
00449
00450
00451
00452
00453
00454 x++;
00455
00456
00457
00458
00459 if (pf->baseprefix && pf->base==16) {
00460 bprefix = "0x";
00461 }
00462 else if (pf->baseprefix && pf->base==8) {
00463 bprefix = "0";
00464 }
00465 else {
00466 bprefix = "";
00467 }
00468
00469
00470
00471
00472 sprefix = pf->sign ? "-" : "";
00473
00474
00475
00476
00477 __pf_printstuff(pf, sprefix, bprefix, x);
00478 }
00479
00480
00481
00482
00483 static
00484 void
00485 __pf_send(PF *pf, int ch)
00486 {
00487
00488 assert(ch!=0);
00489
00490 if (pf->in_pct==0 && ch!='%') {
00491
00492
00493
00494
00495 char c = ch;
00496 __pf_print(pf, &c, 1);
00497 }
00498 else if (pf->in_pct==0) {
00499
00500
00501
00502 pf->in_pct = 1;
00503 }
00504 else if (strchr("#-l0123456789", ch)) {
00505
00506
00507
00508
00509 __pf_modifier(pf, ch);
00510 }
00511 else if (strchr("doupx", ch)) {
00512
00513
00514
00515
00516
00517 __pf_getnum(pf, ch);
00518 __pf_setbase(pf, ch);
00519 __pf_printnum(pf);
00520 __pf_endfield(pf);
00521 }
00522 else if (ch=='s') {
00523
00524
00525
00526 const char *str = va_arg(pf->ap, const char *);
00527 if (str==NULL) {
00528 str = "(null)";
00529 }
00530 __pf_printstuff(pf, "", "", str);
00531 __pf_endfield(pf);
00532 }
00533 else {
00534
00535
00536
00537
00538
00539 char x[2];
00540 if (ch=='c') {
00541 x[0] = va_arg(pf->ap, int);
00542 }
00543 else {
00544 x[0] = ch;
00545 }
00546 x[1] = 0;
00547 __pf_printstuff(pf, "", "", x);
00548 __pf_endfield(pf);
00549 }
00550 }
00551
00552
00553
00554
00555
00556
00557 int
00558 __vprintf(void (*func)(void *clientdata, const char *str, size_t len),
00559 void *clientdata, const char *format, va_list ap)
00560 {
00561 PF pf;
00562 int i;
00563
00564 pf.sendfunc = func;
00565 pf.clientdata = clientdata;
00566 pf.ap = ap;
00567 pf.charcount = 0;
00568 __pf_endfield(&pf);
00569
00570 for (i=0; format[i]; i++) {
00571 __pf_send(&pf, format[i]);
00572 }
00573
00574 return pf.charcount;
00575 }