📄 doprnt.c
字号:
/* Calculate padding zero requirement */ p = buf + MAXDIGS; lzero = bp - p + prec; /* Handle the # flag */ if (fsharp && bp != p) { switch (fcode) { case 'o': if (lzero < 1) lzero = 1; break; case 'x': prefix = "0x"; break; case 'X': prefix = "0X"; break; } } break;#if FLOAT#ifdef sparc#define GETQVAL /* Sun-4 macro to get a quad q from the argument list, passed as a pointer. */ \ { qval = *(va_arg(args.ap, quadruple*)) ; }#else#define GETQVAL /* Sun-3 macro to get a quad q from the argument list, passed as a value. */ \ { int iq ; unsigned long * pl = (unsigned long *) (&qval) ; for(iq=0;iq<4;iq++) pl[iq] = (unsigned long) va_arg(args.ap, unsigned long) ; }#endif case 'E': case 'e': /* * E-format. The general strategy * here is fairly easy: we take * what econvert gives us and re-format it. */ /* Establish default precision */ if (prec < 0) prec = 6; /* Fetch the value */ if (Lsize == 0) { /* Double */ dval = va_arg(args.ap, double); bp = econvert(dval, prec + 1, &decpt, &sign, convertbuffer); } else { /* Long Double = quadruple */ GETQVAL; bp = qeconvert(&qval, prec + 1, &decpt, &sign, convertbuffer); } /* Determine the prefix */ if (sign) prefix = "-"; else if (fplus) prefix = "+"; else if (fblank) prefix = " "; if (convertbuffer[0] > '9') { /* handle infinity, nan */ bp = &convertbuffer[0]; for (p = bp+1 ; *p != 0 ; p++) ; goto ebreak ; } { register char *stringp; /* Place the first digit in the buffer */ stringp = &buf[0]; *stringp++ = *bp != '\0'? *bp++: '0'; /* Put in a decimal point if needed */ if (prec != 0 || fsharp) *stringp++ = decpt_char; /* Create the rest of the mantissa */ rzero = prec; while (rzero > 0 && *bp!= '\0') { --rzero; *stringp++ = *bp++; } p = stringp; } bp = &buf[0]; /* Create the exponent */ if (convertbuffer[0] != '0') n = decpt - 1; else n = 0 ; if (n < 0) n = -n; _fourdigitsquick( (short unsigned) n, &(expbuf[2]) ) ; expbuf[6] = 0 ; if (n < 100) /* * Normally two digit exponent field, * three or four if required. */ { suffix = &(expbuf[4]) ; suffixlength = 4 ; } else if (n < 1000) { suffix = &(expbuf[3]) ; suffixlength = 5 ; } else { suffix = &(expbuf[2]) ; suffixlength = 6 ; } /* Put in the exponent sign */ *--suffix = (decpt > 0 || convertbuffer[0] == '0' )? '+': '-'; /* Put in the e; note kludge in 'g' format */ *--suffix = fcode;ebreak:#if FZERO if (fzero &! fminus) /* Calculate padding zero requirement */ lzero = width - (strlen(prefix) + (p - buf) + rzero + suffixlength);#endif break; case 'f': /* * F-format floating point. This is * a good deal less simple than E-format. * The overall strategy will be to call * fconvert, reformat its result into buf, * and calculate how many trailing * zeroes will be required. There will * never be any leading zeroes needed. */ /* Establish default precision */ if (prec < 0) prec = 6; if (Lsize == 0) { dval = va_arg(args.ap, double); bp = fconvert(dval, prec, &decpt, &sign, convertbuffer); } else { GETQVAL ; bp = qfconvert(&qval, prec, &decpt, &sign, convertbuffer); } /* Determine the prefix */ if (sign) prefix = "-"; else if (fplus) prefix = "+"; else if (fblank) prefix = " "; if (convertbuffer[0] > '9') { /* handle infinity, nan */ bp = &convertbuffer[0]; for (p = bp+1 ; *p != 0 ; p++) ; goto fbreak ; } { register char *stringp; /* Initialize buffer pointer */ stringp = &buf[0]; /* Emit the digits before the decimal point */ n = decpt; if (n <= 0) *stringp++ = '0'; else do if (*bp == '\0' ) *stringp++ = '0'; else { *stringp++ = *bp++; } while (--n != 0); /* Decide whether we need a decimal point */ if (fsharp || prec > 0) *stringp++ = decpt_char; /* Digits(if any) after the decimal point */ n = prec; rzero = prec - n; while (--n >= 0) { if (++decpt <= 0 || *bp == '\0') *stringp++ = '0'; else { *stringp++ = *bp++; } }#if FZERO if (fzero &! fminus) /* Calculate padding zero requirement */ lzero = width - (strlen(prefix) + (stringp - buf) + rzero);#endif p = stringp; } bp = &buf[0];fbreak: break; case 'G': case 'g': /* * g-format. We play around a bit * and then jump into e or f, as needed. */ /* Establish default precision */ if (prec < 0) prec = 6; else if (prec == 0) prec = 1; if (Lsize == 0) { dval = va_arg(args.ap, double); bp = gconvert(dval, prec, fsharp, convertbuffer); } else { GETQVAL; bp = qgconvert(&qval, prec, fsharp, convertbuffer); } bp = convertbuffer ; if (convertbuffer[0] == '-') { prefix = "-" ; bp++; } else if (fplus) prefix = "+"; else if (fblank) prefix = " "; if (isupper(fcode)) { /* Put in a big E for small minds. */ for (p = bp ; (*p != NULL) && (*p != 'e') ; p++) ; if (*p == 'e') *p = 'E' ; for (; (*p != NULL) ; p++) ; /* Find end of string. */ } else for (p = bp ; *p != NULL ; p++) ; /* Find end of string. */ rzero = 0;#if FZERO if (fzero & !fminus) /* Calculate padding zero requirement */ lzero = width - (strlen(prefix) + (p - bp) + rzero);#endif break ;#endif case 'c': buf[0] = va_arg(args.ap, int); bp = &buf[0]; p = bp + 1; break; case 's': bp = va_arg(args.ap, char *); if (prec < 0) prec = MAXINT; /* avoid *(0) */ if (bp == NULL) bp = nullstr; for (n=0; *bp++ != '\0' && n < prec; n++) ;#if FZERO if (fzero &! fminus) lzero = width - n;#endif p = --bp; bp -= n; break; case '\0': /* well, what's the punch line? */ goto out; case 'n': svswitch = 1; break; default: p = bp = &fcode; p++; break; } /* Calculate number of padding blanks */ nblank = width#if FLOAT - (rzero < 0? 0: rzero) - strlen(suffix)#endif - (p - bp) - (lzero < 0? 0: lzero) - strlen(prefix); /* Blanks on left if required */ if (!fminus) while (--nblank >= 0) emitchar(' '); /* Prefix, if any */ while (*prefix != '\0') { emitchar(*prefix); prefix++; } /* Zeroes on the left */ while (--lzero >= 0) emitchar('0'); /* The value itself */ while (bp < p) { emitchar(*bp); bp++; }#if FLOAT /* Zeroes on the right */ while (--rzero >= 0) emitchar('0'); /* The suffix */ while (*suffix != '\0') { emitchar(*suffix); suffix++; }#endif /* Blanks on the right if required */ if (fminus) while (--nblank >= 0) emitchar(' '); /* If %n is seen, save count in argument */ if (svswitch == 1) { long *svcount; svcount = va_arg (args.ap, int *); *svcount = count; svswitch = 0; } } /* else */ } while ((c = *cp++) != '\0'); /* do */out: file->_ptr = fileptr; file->_cnt = filecnt; if (file->_flag & (_IONBF | _IOLBF) && (file->_flag & _IONBF || memchr((char *)file->_base, '\n', fileptr - file->_base) != NULL)) (void) _xflsbuf(file); return (ferror(file)? EOF: count);}/* This function initializes arglst, to contain the appropriate va_list values * for the first MAXARGS arguments. */void_mkarglst(fmt, args, arglst)char *fmt;stva_list args;stva_list arglst[];{ static char *digits = "01234567890", *skips = "# +-.0123456789hL$"; enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR, LONG_PTR, INT_PTR}; enum types typelst[MAXARGS], curtype; int maxnum, n, curargno, flags; /* * Algorithm 1. set all argument types to zero. * 2. walk through fmt putting arg types in typelst[]. * 3. walk through args using va_arg(args.ap, typelst[n]) * and set arglst[] to the appropriate values. * Assumptions: Cannot use %*$... to specify variable position. */ (void)memset((void *)typelst, 0, sizeof(typelst)); maxnum = -1; curargno = 0; while ((fmt = strchr(fmt, '%')) != 0) { fmt++; /* skip % */ if (fmt[n = strspn(fmt, digits)] == '$') { curargno = atoi(fmt) - 1; /* convert to zero base */ fmt += n + 1; } flags = 0; again:; fmt += strspn(fmt, skips); switch (*fmt++) { case '%': /*there is no argument! */ continue; case 'l': flags |= 0x1; goto again; case '*': /* int argument used for value */ flags |= 0x2; curtype = INT; break; case 'e': case 'E': case 'f': case 'g': case 'G': curtype = DOUBLE; break; case 's': curtype = CHAR_PTR; break; case 'p': curtype = VOID_PTR; break; case 'n': if (flags & 0x1) curtype = LONG_PTR; else curtype = INT_PTR; break; default: if (flags & 0x1) curtype = LONG; else curtype = INT; break; } if (curargno >= 0 && curargno < MAXARGS) { typelst[curargno] = curtype; if (maxnum < curargno) maxnum = curargno; } curargno++; /* default to next in list */ if (flags & 0x2) /* took care of *, keep going */ { flags ^= 0x2; goto again; } } for (n = 0 ; n <= maxnum; n++) { arglst[n] = args; if (typelst[n] == 0) typelst[n] = INT; switch (typelst[n]) { case INT: va_arg(args.ap, int); break; case LONG: va_arg(args.ap, long); break; case CHAR_PTR: va_arg(args.ap, char *); break; case DOUBLE: va_arg(args.ap, double); break; case LONG_DOUBLE: va_arg(args.ap, double); break; case VOID_PTR: va_arg(args.ap, void *); break; case LONG_PTR: va_arg(args.ap, long *); break; case INT_PTR: va_arg(args.ap, int *); break; } }}/* * This function is used to find the va_list value for arguments whose * position is greater than MAXARGS. This function is slow, so hopefully * MAXARGS will be big enough so that this function need only be called in * unusual circumstances. * pargs is assumed to contain the value of arglst[MAXARGS - 1]. */void_getarg(fmt, pargs, argno)char *fmt;stva_list *pargs;int argno;{ static char *digits = "01234567890", *skips = "# +-.0123456789h$"; int i, n, curargno, flags; char *sfmt = fmt; int found = 1; curargno = i = MAXARGS; while (found) { fmt = sfmt; found = 0; while ((i != argno) && (fmt = strchr(fmt, '%')) != 0) { fmt++; /* skip % */ if (fmt[n = strspn(fmt, digits)] == '$') { curargno = atoi(fmt); fmt += n + 1; } /* find conversion specifier for next argument */ if (i != curargno) { curargno++; continue; } else found = 1; flags = 0; again:; fmt += strspn(fmt, skips); switch (*fmt++) { case '%': /*there is no argument! */ continue; case 'l': flags |= 0x1; goto again; case '*': /* int argument used for value */ flags |= 0x2; (void)va_arg((*pargs).ap, int); break; case 'e': case 'E': case 'f': case 'g': case 'G': if (flags & 0x1) (void)va_arg((*pargs).ap, double); else (void)va_arg((*pargs).ap, double); break; case 's': (void)va_arg((*pargs).ap, char *); break; case 'p': (void)va_arg((*pargs).ap, void *); break; case 'n': if (flags & 0x1) (void)va_arg((*pargs).ap, long *); else (void)va_arg((*pargs).ap, int *); break; default: if (flags & 0x1) (void)va_arg((*pargs).ap, long int); else (void)va_arg((*pargs).ap, int); break; } i++; curargno++; /* default to next in list */ if (flags & 0x2) /* took care of *, keep going */ { flags ^= 0x2; goto again; } } /* missing specifier for parameter, assume parameter is an int */ if (!found && i != argno) { (void)va_arg((*pargs).ap, int); i++; curargno++; found = 1; } }}/* * parse a string, mini parse */static char *_check_dol(s, val) char *s; int *val;{ char *os; /* save old string */ int tmp_val = 0; int flag = 0; while (isdigit (*s)) { ++flag; tmp_val = tmp_val*10 + *s - '0'; s++; } if (flag == 0) return ((char *)NULL); if (*s == '$') { *val = tmp_val; return(++s); } return ((char *)NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -