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 #include "c.h"
00034
00035 #include <limits.h>
00036 #ifndef WIN32
00037 #include <sys/ioctl.h>
00038 #endif
00039 #include <sys/param.h>
00040
00041 #ifndef NL_ARGMAX
00042 #define NL_ARGMAX 16
00043 #endif
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 #undef vsnprintf
00096 #undef snprintf
00097 #undef sprintf
00098 #undef vfprintf
00099 #undef fprintf
00100 #undef printf
00101
00102
00103 typedef struct
00104 {
00105 char *bufptr;
00106 char *bufstart;
00107 char *bufend;
00108
00109 FILE *stream;
00110 int nchars;
00111 } PrintfTarget;
00112
00113
00114
00115
00116
00117
00118
00119 typedef enum
00120 {
00121 ATYPE_NONE = 0,
00122 ATYPE_INT,
00123 ATYPE_LONG,
00124 ATYPE_LONGLONG,
00125 ATYPE_DOUBLE,
00126 ATYPE_CHARPTR
00127 } PrintfArgType;
00128
00129 typedef union
00130 {
00131 int i;
00132 long l;
00133 int64 ll;
00134 double d;
00135 char *cptr;
00136 } PrintfArgValue;
00137
00138
00139 static void flushbuffer(PrintfTarget *target);
00140 static int dopr(PrintfTarget *target, const char *format, va_list args);
00141
00142
00143 int
00144 pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
00145 {
00146 PrintfTarget target;
00147
00148 if (str == NULL || count == 0)
00149 return 0;
00150 target.bufstart = target.bufptr = str;
00151 target.bufend = str + count - 1;
00152 target.stream = NULL;
00153
00154 if (dopr(&target, fmt, args))
00155 {
00156 *(target.bufptr) = '\0';
00157 errno = EINVAL;
00158 return -1;
00159 }
00160 *(target.bufptr) = '\0';
00161 return target.bufptr - target.bufstart;
00162 }
00163
00164 int
00165 pg_snprintf(char *str, size_t count, const char *fmt,...)
00166 {
00167 int len;
00168 va_list args;
00169
00170 va_start(args, fmt);
00171 len = pg_vsnprintf(str, count, fmt, args);
00172 va_end(args);
00173 return len;
00174 }
00175
00176 static int
00177 pg_vsprintf(char *str, const char *fmt, va_list args)
00178 {
00179 PrintfTarget target;
00180
00181 if (str == NULL)
00182 return 0;
00183 target.bufstart = target.bufptr = str;
00184 target.bufend = NULL;
00185 target.stream = NULL;
00186
00187 if (dopr(&target, fmt, args))
00188 {
00189 *(target.bufptr) = '\0';
00190 errno = EINVAL;
00191 return -1;
00192 }
00193 *(target.bufptr) = '\0';
00194 return target.bufptr - target.bufstart;
00195 }
00196
00197 int
00198 pg_sprintf(char *str, const char *fmt,...)
00199 {
00200 int len;
00201 va_list args;
00202
00203 va_start(args, fmt);
00204 len = pg_vsprintf(str, fmt, args);
00205 va_end(args);
00206 return len;
00207 }
00208
00209 int
00210 pg_vfprintf(FILE *stream, const char *fmt, va_list args)
00211 {
00212 PrintfTarget target;
00213 char buffer[1024];
00214
00215 if (stream == NULL)
00216 {
00217 errno = EINVAL;
00218 return -1;
00219 }
00220 target.bufstart = target.bufptr = buffer;
00221 target.bufend = buffer + sizeof(buffer) - 1;
00222 target.stream = stream;
00223 target.nchars = 0;
00224 if (dopr(&target, fmt, args))
00225 {
00226 errno = EINVAL;
00227 return -1;
00228 }
00229
00230 flushbuffer(&target);
00231 return target.nchars;
00232 }
00233
00234 int
00235 pg_fprintf(FILE *stream, const char *fmt,...)
00236 {
00237 int len;
00238 va_list args;
00239
00240 va_start(args, fmt);
00241 len = pg_vfprintf(stream, fmt, args);
00242 va_end(args);
00243 return len;
00244 }
00245
00246 int
00247 pg_printf(const char *fmt,...)
00248 {
00249 int len;
00250 va_list args;
00251
00252 va_start(args, fmt);
00253 len = pg_vfprintf(stdout, fmt, args);
00254 va_end(args);
00255 return len;
00256 }
00257
00258
00259 static void
00260 flushbuffer(PrintfTarget *target)
00261 {
00262 size_t nc = target->bufptr - target->bufstart;
00263
00264 if (nc > 0)
00265 target->nchars += fwrite(target->bufstart, 1, nc, target->stream);
00266 target->bufptr = target->bufstart;
00267 }
00268
00269
00270 static void fmtstr(char *value, int leftjust, int minlen, int maxwidth,
00271 int pointflag, PrintfTarget *target);
00272 static void fmtptr(void *value, PrintfTarget *target);
00273 static void fmtint(int64 value, char type, int forcesign,
00274 int leftjust, int minlen, int zpad, int precision, int pointflag,
00275 PrintfTarget *target);
00276 static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target);
00277 static void fmtfloat(double value, char type, int forcesign,
00278 int leftjust, int minlen, int zpad, int precision, int pointflag,
00279 PrintfTarget *target);
00280 static void dostr(const char *str, int slen, PrintfTarget *target);
00281 static void dopr_outch(int c, PrintfTarget *target);
00282 static int adjust_sign(int is_negative, int forcesign, int *signvalue);
00283 static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen);
00284 static void leading_pad(int zpad, int *signvalue, int *padlen,
00285 PrintfTarget *target);
00286 static void trailing_pad(int *padlen, PrintfTarget *target);
00287
00288
00289
00290
00291
00292 static int
00293 dopr(PrintfTarget *target, const char *format, va_list args)
00294 {
00295 const char *format_start = format;
00296 int ch;
00297 bool have_dollar;
00298 bool have_non_dollar;
00299 bool have_star;
00300 bool afterstar;
00301 int accum;
00302 int longlongflag;
00303 int longflag;
00304 int pointflag;
00305 int leftjust;
00306 int fieldwidth;
00307 int precision;
00308 int zpad;
00309 int forcesign;
00310 int last_dollar;
00311 int fmtpos;
00312 int cvalue;
00313 int64 numvalue;
00314 double fvalue;
00315 char *strvalue;
00316 int i;
00317 PrintfArgType argtypes[NL_ARGMAX + 1];
00318 PrintfArgValue argvalues[NL_ARGMAX + 1];
00319
00320
00321
00322
00323
00324 have_dollar = have_non_dollar = false;
00325 last_dollar = 0;
00326 MemSet(argtypes, 0, sizeof(argtypes));
00327
00328 while ((ch = *format++) != '\0')
00329 {
00330 if (ch != '%')
00331 continue;
00332 longflag = longlongflag = pointflag = 0;
00333 fmtpos = accum = 0;
00334 afterstar = false;
00335 nextch1:
00336 ch = *format++;
00337 if (ch == '\0')
00338 break;
00339 switch (ch)
00340 {
00341 case '-':
00342 case '+':
00343 goto nextch1;
00344 case '0':
00345 case '1':
00346 case '2':
00347 case '3':
00348 case '4':
00349 case '5':
00350 case '6':
00351 case '7':
00352 case '8':
00353 case '9':
00354 accum = accum * 10 + (ch - '0');
00355 goto nextch1;
00356 case '.':
00357 pointflag = 1;
00358 accum = 0;
00359 goto nextch1;
00360 case '*':
00361 if (afterstar)
00362 have_non_dollar = true;
00363 afterstar = true;
00364 accum = 0;
00365 goto nextch1;
00366 case '$':
00367 have_dollar = true;
00368 if (accum <= 0 || accum > NL_ARGMAX)
00369 return -1;
00370 if (afterstar)
00371 {
00372 if (argtypes[accum] &&
00373 argtypes[accum] != ATYPE_INT)
00374 return -1;
00375 argtypes[accum] = ATYPE_INT;
00376 last_dollar = Max(last_dollar, accum);
00377 afterstar = false;
00378 }
00379 else
00380 fmtpos = accum;
00381 accum = 0;
00382 goto nextch1;
00383 case 'l':
00384 if (longflag)
00385 longlongflag = 1;
00386 else
00387 longflag = 1;
00388 goto nextch1;
00389 case 'h':
00390 case '\'':
00391
00392 goto nextch1;
00393 case 'd':
00394 case 'i':
00395 case 'o':
00396 case 'u':
00397 case 'x':
00398 case 'X':
00399 if (fmtpos)
00400 {
00401 PrintfArgType atype;
00402
00403 if (longlongflag)
00404 atype = ATYPE_LONGLONG;
00405 else if (longflag)
00406 atype = ATYPE_LONG;
00407 else
00408 atype = ATYPE_INT;
00409 if (argtypes[fmtpos] &&
00410 argtypes[fmtpos] != atype)
00411 return -1;
00412 argtypes[fmtpos] = atype;
00413 last_dollar = Max(last_dollar, fmtpos);
00414 }
00415 else
00416 have_non_dollar = true;
00417 break;
00418 case 'c':
00419 if (fmtpos)
00420 {
00421 if (argtypes[fmtpos] &&
00422 argtypes[fmtpos] != ATYPE_INT)
00423 return -1;
00424 argtypes[fmtpos] = ATYPE_INT;
00425 last_dollar = Max(last_dollar, fmtpos);
00426 }
00427 else
00428 have_non_dollar = true;
00429 break;
00430 case 's':
00431 case 'p':
00432 if (fmtpos)
00433 {
00434 if (argtypes[fmtpos] &&
00435 argtypes[fmtpos] != ATYPE_CHARPTR)
00436 return -1;
00437 argtypes[fmtpos] = ATYPE_CHARPTR;
00438 last_dollar = Max(last_dollar, fmtpos);
00439 }
00440 else
00441 have_non_dollar = true;
00442 break;
00443 case 'e':
00444 case 'E':
00445 case 'f':
00446 case 'g':
00447 case 'G':
00448 if (fmtpos)
00449 {
00450 if (argtypes[fmtpos] &&
00451 argtypes[fmtpos] != ATYPE_DOUBLE)
00452 return -1;
00453 argtypes[fmtpos] = ATYPE_DOUBLE;
00454 last_dollar = Max(last_dollar, fmtpos);
00455 }
00456 else
00457 have_non_dollar = true;
00458 break;
00459 case '%':
00460 break;
00461 }
00462
00463
00464
00465
00466
00467 if (afterstar)
00468 have_non_dollar = true;
00469 }
00470
00471
00472 if (have_dollar && have_non_dollar)
00473 return -1;
00474
00475
00476
00477
00478 for (i = 1; i <= last_dollar; i++)
00479 {
00480 switch (argtypes[i])
00481 {
00482 case ATYPE_NONE:
00483 return -1;
00484 case ATYPE_INT:
00485 argvalues[i].i = va_arg(args, int);
00486 break;
00487 case ATYPE_LONG:
00488 argvalues[i].l = va_arg(args, long);
00489 break;
00490 case ATYPE_LONGLONG:
00491 argvalues[i].ll = va_arg(args, int64);
00492 break;
00493 case ATYPE_DOUBLE:
00494 argvalues[i].d = va_arg(args, double);
00495 break;
00496 case ATYPE_CHARPTR:
00497 argvalues[i].cptr = va_arg(args, char *);
00498 break;
00499 }
00500 }
00501
00502
00503
00504
00505 format = format_start;
00506 while ((ch = *format++) != '\0')
00507 {
00508 if (ch != '%')
00509 {
00510 dopr_outch(ch, target);
00511 continue;
00512 }
00513 fieldwidth = precision = zpad = leftjust = forcesign = 0;
00514 longflag = longlongflag = pointflag = 0;
00515 fmtpos = accum = 0;
00516 have_star = afterstar = false;
00517 nextch2:
00518 ch = *format++;
00519 if (ch == '\0')
00520 break;
00521 switch (ch)
00522 {
00523 case '-':
00524 leftjust = 1;
00525 goto nextch2;
00526 case '+':
00527 forcesign = 1;
00528 goto nextch2;
00529 case '0':
00530
00531 if (accum == 0 && !pointflag)
00532 zpad = '0';
00533
00534 case '1':
00535 case '2':
00536 case '3':
00537 case '4':
00538 case '5':
00539 case '6':
00540 case '7':
00541 case '8':
00542 case '9':
00543 accum = accum * 10 + (ch - '0');
00544 goto nextch2;
00545 case '.':
00546 if (have_star)
00547 have_star = false;
00548 else
00549 fieldwidth = accum;
00550 pointflag = 1;
00551 accum = 0;
00552 goto nextch2;
00553 case '*':
00554 if (have_dollar)
00555 {
00556
00557 afterstar = true;
00558 }
00559 else
00560 {
00561
00562 int starval = va_arg(args, int);
00563
00564 if (pointflag)
00565 {
00566 precision = starval;
00567 if (precision < 0)
00568 {
00569 precision = 0;
00570 pointflag = 0;
00571 }
00572 }
00573 else
00574 {
00575 fieldwidth = starval;
00576 if (fieldwidth < 0)
00577 {
00578 leftjust = 1;
00579 fieldwidth = -fieldwidth;
00580 }
00581 }
00582 }
00583 have_star = true;
00584 accum = 0;
00585 goto nextch2;
00586 case '$':
00587 if (afterstar)
00588 {
00589
00590 int starval = argvalues[accum].i;
00591
00592 if (pointflag)
00593 {
00594 precision = starval;
00595 if (precision < 0)
00596 {
00597 precision = 0;
00598 pointflag = 0;
00599 }
00600 }
00601 else
00602 {
00603 fieldwidth = starval;
00604 if (fieldwidth < 0)
00605 {
00606 leftjust = 1;
00607 fieldwidth = -fieldwidth;
00608 }
00609 }
00610 afterstar = false;
00611 }
00612 else
00613 fmtpos = accum;
00614 accum = 0;
00615 goto nextch2;
00616 case 'l':
00617 if (longflag)
00618 longlongflag = 1;
00619 else
00620 longflag = 1;
00621 goto nextch2;
00622 case 'h':
00623 case '\'':
00624
00625 goto nextch2;
00626 case 'd':
00627 case 'i':
00628 if (!have_star)
00629 {
00630 if (pointflag)
00631 precision = accum;
00632 else
00633 fieldwidth = accum;
00634 }
00635 if (have_dollar)
00636 {
00637 if (longlongflag)
00638 numvalue = argvalues[fmtpos].ll;
00639 else if (longflag)
00640 numvalue = argvalues[fmtpos].l;
00641 else
00642 numvalue = argvalues[fmtpos].i;
00643 }
00644 else
00645 {
00646 if (longlongflag)
00647 numvalue = va_arg(args, int64);
00648 else if (longflag)
00649 numvalue = va_arg(args, long);
00650 else
00651 numvalue = va_arg(args, int);
00652 }
00653 fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
00654 precision, pointflag, target);
00655 break;
00656 case 'o':
00657 case 'u':
00658 case 'x':
00659 case 'X':
00660 if (!have_star)
00661 {
00662 if (pointflag)
00663 precision = accum;
00664 else
00665 fieldwidth = accum;
00666 }
00667 if (have_dollar)
00668 {
00669 if (longlongflag)
00670 numvalue = (uint64) argvalues[fmtpos].ll;
00671 else if (longflag)
00672 numvalue = (unsigned long) argvalues[fmtpos].l;
00673 else
00674 numvalue = (unsigned int) argvalues[fmtpos].i;
00675 }
00676 else
00677 {
00678 if (longlongflag)
00679 numvalue = (uint64) va_arg(args, int64);
00680 else if (longflag)
00681 numvalue = (unsigned long) va_arg(args, long);
00682 else
00683 numvalue = (unsigned int) va_arg(args, int);
00684 }
00685 fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
00686 precision, pointflag, target);
00687 break;
00688 case 'c':
00689 if (!have_star)
00690 {
00691 if (pointflag)
00692 precision = accum;
00693 else
00694 fieldwidth = accum;
00695 }
00696 if (have_dollar)
00697 cvalue = (unsigned char) argvalues[fmtpos].i;
00698 else
00699 cvalue = (unsigned char) va_arg(args, int);
00700 fmtchar(cvalue, leftjust, fieldwidth, target);
00701 break;
00702 case 's':
00703 if (!have_star)
00704 {
00705 if (pointflag)
00706 precision = accum;
00707 else
00708 fieldwidth = accum;
00709 }
00710 if (have_dollar)
00711 strvalue = argvalues[fmtpos].cptr;
00712 else
00713 strvalue = va_arg(args, char *);
00714 fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
00715 target);
00716 break;
00717 case 'p':
00718
00719 if (have_dollar)
00720 strvalue = argvalues[fmtpos].cptr;
00721 else
00722 strvalue = va_arg(args, char *);
00723 fmtptr((void *) strvalue, target);
00724 break;
00725 case 'e':
00726 case 'E':
00727 case 'f':
00728 case 'g':
00729 case 'G':
00730 if (!have_star)
00731 {
00732 if (pointflag)
00733 precision = accum;
00734 else
00735 fieldwidth = accum;
00736 }
00737 if (have_dollar)
00738 fvalue = argvalues[fmtpos].d;
00739 else
00740 fvalue = va_arg(args, double);
00741 fmtfloat(fvalue, ch, forcesign, leftjust,
00742 fieldwidth, zpad,
00743 precision, pointflag,
00744 target);
00745 break;
00746 case '%':
00747 dopr_outch('%', target);
00748 break;
00749 }
00750 }
00751
00752 return 0;
00753 }
00754
00755 static size_t
00756 pg_strnlen(const char *str, size_t maxlen)
00757 {
00758 const char *p = str;
00759
00760 while (maxlen-- > 0 && *p)
00761 p++;
00762 return p - str;
00763 }
00764
00765 static void
00766 fmtstr(char *value, int leftjust, int minlen, int maxwidth,
00767 int pointflag, PrintfTarget *target)
00768 {
00769 int padlen,
00770 vallen;
00771
00772
00773
00774
00775
00776 if (pointflag)
00777 vallen = pg_strnlen(value, maxwidth);
00778 else
00779 vallen = strlen(value);
00780
00781 adjust_padlen(minlen, vallen, leftjust, &padlen);
00782
00783 while (padlen > 0)
00784 {
00785 dopr_outch(' ', target);
00786 --padlen;
00787 }
00788
00789 dostr(value, vallen, target);
00790
00791 trailing_pad(&padlen, target);
00792 }
00793
00794 static void
00795 fmtptr(void *value, PrintfTarget *target)
00796 {
00797 int vallen;
00798 char convert[64];
00799
00800
00801 vallen = sprintf(convert, "%p", value);
00802
00803 dostr(convert, vallen, target);
00804 }
00805
00806 static void
00807 fmtint(int64 value, char type, int forcesign, int leftjust,
00808 int minlen, int zpad, int precision, int pointflag,
00809 PrintfTarget *target)
00810 {
00811 uint64 base;
00812 int dosign;
00813 const char *cvt = "0123456789abcdef";
00814 int signvalue = 0;
00815 char convert[64];
00816 int vallen = 0;
00817 int padlen = 0;
00818 int zeropad;
00819
00820 switch (type)
00821 {
00822 case 'd':
00823 case 'i':
00824 base = 10;
00825 dosign = 1;
00826 break;
00827 case 'o':
00828 base = 8;
00829 dosign = 0;
00830 break;
00831 case 'u':
00832 base = 10;
00833 dosign = 0;
00834 break;
00835 case 'x':
00836 base = 16;
00837 dosign = 0;
00838 break;
00839 case 'X':
00840 cvt = "0123456789ABCDEF";
00841 base = 16;
00842 dosign = 0;
00843 break;
00844 default:
00845 return;
00846 }
00847
00848
00849 if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
00850 value = -value;
00851
00852
00853
00854
00855
00856 if (value == 0 && pointflag && precision == 0)
00857 vallen = 0;
00858 else
00859 {
00860
00861 uint64 uvalue = (uint64) value;
00862
00863 do
00864 {
00865 convert[vallen++] = cvt[uvalue % base];
00866 uvalue = uvalue / base;
00867 } while (uvalue);
00868 }
00869
00870 zeropad = Max(0, precision - vallen);
00871
00872 adjust_padlen(minlen, vallen + zeropad, leftjust, &padlen);
00873
00874 leading_pad(zpad, &signvalue, &padlen, target);
00875
00876 while (zeropad-- > 0)
00877 dopr_outch('0', target);
00878
00879 while (vallen > 0)
00880 dopr_outch(convert[--vallen], target);
00881
00882 trailing_pad(&padlen, target);
00883 }
00884
00885 static void
00886 fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
00887 {
00888 int padlen = 0;
00889
00890 adjust_padlen(minlen, 1, leftjust, &padlen);
00891
00892 while (padlen > 0)
00893 {
00894 dopr_outch(' ', target);
00895 --padlen;
00896 }
00897
00898 dopr_outch(value, target);
00899
00900 trailing_pad(&padlen, target);
00901 }
00902
00903 static void
00904 fmtfloat(double value, char type, int forcesign, int leftjust,
00905 int minlen, int zpad, int precision, int pointflag,
00906 PrintfTarget *target)
00907 {
00908 int signvalue = 0;
00909 int vallen;
00910 char fmt[32];
00911 char convert[512];
00912 int padlen = 0;
00913
00914
00915 if (pointflag)
00916 sprintf(fmt, "%%.%d%c", precision, type);
00917 else
00918 sprintf(fmt, "%%%c", type);
00919
00920 if (adjust_sign((value < 0), forcesign, &signvalue))
00921 value = -value;
00922
00923 vallen = sprintf(convert, fmt, value);
00924
00925 adjust_padlen(minlen, vallen, leftjust, &padlen);
00926
00927 leading_pad(zpad, &signvalue, &padlen, target);
00928
00929 dostr(convert, vallen, target);
00930
00931 trailing_pad(&padlen, target);
00932 }
00933
00934 static void
00935 dostr(const char *str, int slen, PrintfTarget *target)
00936 {
00937 while (slen > 0)
00938 {
00939 int avail;
00940
00941 if (target->bufend != NULL)
00942 avail = target->bufend - target->bufptr;
00943 else
00944 avail = slen;
00945 if (avail <= 0)
00946 {
00947
00948 if (target->stream == NULL)
00949 return;
00950 flushbuffer(target);
00951 continue;
00952 }
00953 avail = Min(avail, slen);
00954 memmove(target->bufptr, str, avail);
00955 target->bufptr += avail;
00956 str += avail;
00957 slen -= avail;
00958 }
00959 }
00960
00961 static void
00962 dopr_outch(int c, PrintfTarget *target)
00963 {
00964 if (target->bufend != NULL && target->bufptr >= target->bufend)
00965 {
00966
00967 if (target->stream == NULL)
00968 return;
00969 flushbuffer(target);
00970 }
00971 *(target->bufptr++) = c;
00972 }
00973
00974
00975 static int
00976 adjust_sign(int is_negative, int forcesign, int *signvalue)
00977 {
00978 if (is_negative)
00979 {
00980 *signvalue = '-';
00981 return true;
00982 }
00983 else if (forcesign)
00984 *signvalue = '+';
00985 return false;
00986 }
00987
00988
00989 static void
00990 adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
00991 {
00992 *padlen = minlen - vallen;
00993 if (*padlen < 0)
00994 *padlen = 0;
00995 if (leftjust)
00996 *padlen = -(*padlen);
00997 }
00998
00999
01000 static void
01001 leading_pad(int zpad, int *signvalue, int *padlen, PrintfTarget *target)
01002 {
01003 if (*padlen > 0 && zpad)
01004 {
01005 if (*signvalue)
01006 {
01007 dopr_outch(*signvalue, target);
01008 --(*padlen);
01009 *signvalue = 0;
01010 }
01011 while (*padlen > 0)
01012 {
01013 dopr_outch(zpad, target);
01014 --(*padlen);
01015 }
01016 }
01017 while (*padlen > (*signvalue != 0))
01018 {
01019 dopr_outch(' ', target);
01020 --(*padlen);
01021 }
01022 if (*signvalue)
01023 {
01024 dopr_outch(*signvalue, target);
01025 if (*padlen > 0)
01026 --(*padlen);
01027 else if (*padlen < 0)
01028 ++(*padlen);
01029 }
01030 }
01031
01032
01033 static void
01034 trailing_pad(int *padlen, PrintfTarget *target)
01035 {
01036 while (*padlen < 0)
01037 {
01038 dopr_outch(' ', target);
01039 ++(*padlen);
01040 }
01041 }