Printf () Function Implementation!

xiaoxiao2021-03-05  29

/ ************************************************** ************************************ Stripped-down Printf () chris giese http://www.execpc .com / ~ Geezerrelease Date: DEC 12, 2003THIS CODE IS PUBLIC DOMAIN (NO COPYRIGHT). YOU CAN DO WhatVER You Want with it.

Revised DEC 12, 2003- Fixed vSprintf () And Sprintf () in Test Code

Reviad Jan 28, 2002- Changes to make characterly, 0x80-0xff Display Properly

Revised June 10, 2001- Changes to make vsprintf () Terminate string with '/ 0'

Revised May 12, 2000- Math in do_num is now unsigned, as it should be-% 0 Flag (Pad Left with zeroes) Now Works- Actually Did Some Testing, Maybe Fixed Some Other BUGS

% [Flag] [width] [. PREC] [MOD] [CONV] flag: - Left Justify, Pad Right W / Blanks Done 0 Pad Left W / 0 for Numerics Done Always Print Sign, Or - NO '' Blank) no # (???) NO

Width: (Field Width) DONE

PREC: (Precision) no

CONV: D, I DECIMAL INT DONE U DECIMAL UNSIGNED DONE O Octal Done X, X HEX DONE F, E, G, E G Float No C Char Done S String Done P P P P P P P P P P P P P P P P P PTR DONE

MOD: N Near PTR DONE F FAR PTR NO H Short (16-BIT) INT DONE L Long (32-bit) INT DONE L Long Long (64-bit) int No *********** *********************************************************** ************************ / # include / * strlen () * / # include / * stdout, palchar (), fputs () (but NOT Printf () :) * /

#if 0 # include / * va_list, va_start (), VA_ARG (), VA_END () * / # else / * Home-brew stdarg.h, also public-domain: * /

/ * Assume: width of st. Don't use sizeof (char *) OROTHER POITER BECAUS SIZEOF (Char *) == 4 for large-model 16-bit code.assume: width is a power of 2 * / # define STACK_WIDTH sizeof (int) / * Round up object width so it's an even multiple of STACK_WIDTH.Using & for division here, so STACK_WIDTH must be a power of 2. * / # define TYPE_WIDTH (TYPE) / ((sizeof (TYPE) STACK_WIDTH - 1) & ~ (stack_width - 1)))

/ * Point The VA_LIST POINTER TO LASTARG, THEN ADVANCE BEYOND It to the first variable arg * / # define va_start (ptr, lastarg) / PTR = (VA_LIST) (Lastarg) TYPE_WIDTH (Lastarg))

#define va_end (ptr) / * Nothing * /

/ * Increment the va_list pointer, the return (Evaluate to, actually) The previous value of the pointer.wheee! At last; a valid use for the ccoma operator! * / # Define va_arg (PTR, TYPE) (/ (char) *) (PTR) = type_width (type) /, / * ((Type *) ((char *) - type_width (type))) /) / * EVERY OTHER Compiler / Libc Seems To BE USING 'VOID * ', SO ... (i _was_ using' unsigned char * / typef void * va_list;

#ENDIF

/ * Flags used in processing format string * / # define PR_LJ 0x01 / * left justify * / # define PR_CA 0x02 / * use AF instead of af for hex * / # define PR_SG 0x04 / * signed numeric conversion (% d vs.% u) * / # define pr_32 0x08 / * long (32-bit) Numeric Conversion * / # define pr_16 0x10 / * short (16-bit) Numeric Conversion * / # define pr_ws 0x20 / * pr_sg set and num WAS <0 * / # define pr_lz 0x40 / * pad left with '0' instead of '' * / # define pr_fp 0x80 / ​​* Pointers Are Far * // * Largest Number Handled IS 2 ^ 32-1, Lowest Radix Handled IS 8.2 ^ 32- 1 in base 8 HAS 11 DIGITS (Add 5 for Trailing Nul and for SLOP) * / # define pr_bufflen 16typedEf int (* fnptr_t) (unsigned c, void ** helper); / *********** *********************************************************** *************** Name: do_printfaction: minimal subsfunction for? Printf, Calls Function 'FN' with arg 'PTR' for Each Character To Be OutputReturns: Total Number of Characters Output ** *********************************************************** ************************ / INT DO_PRINTF (CO NST Char * FMT, VA_LIST ARGS, FNPTR_T FN, VOID * PTR) {Unsigned Flags, Actual_WD, Count, Given_wd; Unsigned Char * Where, BUF [PR_BUFLEN]; Unsigned Char State, Radix; Long Num;

State = flags = count = given_wd = 0; / * begin scanning format specifier list * / for (; * fmt; fmt ) {switch (state) {/ * state 0: awaiting% * / case 0: if (* fmt! = '%') / * Not% ... * / {fn (* fmt, & ptr); / * ... Just echo it * / count ; Break;} / * Found%, Get next char and advance state to Check if next char is a flag * / state ; fmt ; / * Fall through * /// * state 1: awaiting flags (% -0) * / case 1: if (* fmt == '%') / * %% * / {FN (* FMT, & PTR); count ; state = flags = given_wd = 0; Break;} if (* fmt == '-') {IF (Flags & Pr_LJ) / *% - ILLEGAL * / State = flags = given_wd = 0; else flags | = pr_lj; break;} / * not a flag char: Advance State to check if it's field width * / state ; / * check now for '% 0 ... * / IF (* fmt == '0') {FLAGS | = Pr_LZ; FMT ;} / * Fall Through * //////////////- * Field Width * / Case 2: IF (* fmt> = '0' && * fmt <= '9') {given_wd = 10 * given_wd (* fmt - '0'); Break;} / * Not Field Width: Advance State to Check if it's a modifier * / state ; / * Fall Through * /// * State 3: AWAITING MODIFIER Chars (fnLH) * / case 3: if (* fmt == 'f') { Flags | = Pr_fp; Break;} if (* fmt == 'n') Break; if (* fmt == 'L') {FLAGS | = PR_32; Break;} if (* fmt == 'h') { Flags | = Pr_16; Break;} / * not modifier: Advance State To Check if IT '

Sa converness char * / state ; / * Fall Through * /// * State 4: awaiting converness chars (xxpndiuocs) * / case 4: where = buf pr_bufflen - 1; * where = '/ 0'; switch (* fmt) {CASE 'X': Flags | = Pr_ca; / * Fall Through * // * xxx - Far Pointers (% FP,% FN) Not Yet Supported * / Case 'x': Case 'P': Case 'N': RADIX = 16; goto do_num; case 'd': cas | = pr_sg; / * fall through * / case 'u': radix = 10; goto do_num; case 'o': radix = 8; / * LOAD The value to be printed. l = long = 32 bits: * / do_num: if (Flags & Pr_32) Num = VA_ARG (Args, unsigned long); / * h = short = 16 bits (signed or unsigned) * / Else if (Flags & Pr_16) {IF (Flags & Pr_SG) NUM = VA_ARG (Args, Short); Else Num = VA_ARG (Args, Unsigned Short);} / * no h Nor L: Sizeof (int) Bits (Signed OR) Unsigned) * / else {if (flags & pr_sg) Num = VA_ARG (Args, Int); Else Num = VA_ARG (Args, unsigned int);} / * Take Care of Sign * / IF (Flags & PR_SG) {IF (Num <0) {Flags | = Pr_WS; Num = -Num;}} / * Convert binary to octal / decimal / hex asciiok, i found my misteake. The math here is _ALWAYS_ UNSIGNED * / DO {unsigned Long Temp;

Temp = (unsigned long) NUM% RADIX; WHERE--; IF (Temp <10) * where = TEMP '0'; Else IF (Flags & Pr_CA) * where = Temp - 10 'A'; Else * Where = Temp - 10 'a'; Num = (unsigned long) Num / Radix;} while (NUM! = 0); goto emit; case 'c': / * disallow pad-left-with-Zeroes for% C * / Flags & = ~ pr_lz; where--; * where = (unsigned char) va_arg (args, unsigned char); actual_wd = 1; goto emit2; case 's': / * disallow pad-left-with-Zeroes for% S * / flags & = ~ pr_lz; where = va_arg (args, unsigned char *); emit: actual_wd = strlen (where); if (flags & pra_ws) actual_wd ; / * if we pad Left with zeroes, do the sign now * / IF ((((((("PR_WS | PR_LZ)) == (Pr_WS | PR_LZ)) {Fn ('-', & PTR); Count ;} / * Pad on Left with spaces or zeroes (for right justify) * / Emit2: IF ((Flags & Pr_LJ) == 0) {while (given_wd> actual_wd) {fn (Flags & Pr_LZ? '0': ', & PTR); count ; given_wd--; }} / * If We Pad Left with spaces, do the sign now * / if ((Flags & (Pr_WS | PR_LZ)) == Pr_WS) {Fn ('-', & PT); Count ;} / * Emit String / CHAR / Converted Number * / While (* where! = '/ 0') {Fn (* Where , & Ptr); Count ;} / * Pad on Right $ Spaces (for Left Justify) * / if (Given_WD

} Break; default: Break;} default: state = flags = given_wd = 0; Break;}} return count;} # i 1 / * testing * // ************** *********************************************************** *********** SPRINTF ********************************************************* *********************************************************** / Static Int vsprintf_help (unsigned C, Void * * PTR) {char * dst; DST = * PTR; * DST = (char) C; * PTR = dst; return 0;} / ****************** *********************************************************** *********************************************************** ********************************************* / INT vSprintf (Char * BUF, Const Char * FMT, VA_LIST ARGS ) {INT RV;

RV = DO_PRINTF (FMT, Args, vsprintf_help, (void *) BUF); BUF [RV] = '/ 0'; return RV;} / **************** *********************************************************** *********************************************************** ********************************************* / INT SPRINTF (Char * BUF, Const Char * FMT,. ..) {VA_LIST ARGS; int RV;

VA_START (ARGS, FMT); RV = vsprintf (buf, fmt, args); VA_END (ARGS); return rv;} / ********************** *********************************************************** ***************************************************************************************************************************************************************************************************** ******** ************************************************************ / INT VPRINTF_HELP (unsigned C, void ** PTURN 0;} / *********************************************** *********************************************************** *********************************************************** **************** / INT VPRINTF (const char * fmt, va_list args) {Return Do_Printf (FMT, Args, vprintf_help, null);} / ****** *********************************************************** *********************************************************** ***************************************************************** / INT Printf (const char * fmt, ...) {va_list args; int RV; VA_START (ARGS, FMT); RV = Vprintf (FMT, ARGS); VA_END (ARGS); Return RV;} / ****** *********************************************************** *********************************************************** ******************************* *********************** / INT main (void) {char buf [64];

Sprintf (BUF, "% u score and% i years ago ... / n", 4, -7); FPUTS (BUF, STDOUT); / * PUTS () Adds newline * /

Sprintf (buf, "-1L == 0x% lx == octal% lo / n", -1L, -1L); FPUTS (BUF, STDOUT); / * PUTS () Adds newline * /

Printf ("<% - 08s> and <% 08s> justified strings / n", "left", "right"); return 0;} # Endif

转载请注明原文地址:https://www.9cbs.com/read-38088.html

New Post(0)