I49printer.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:41k
- /*
- * Paradigm C/C++ Run-Time Library - Version 5.0
- *
- * Copyright (c) 1998 Paradigm Systems. All rights reserved.
- * Portions Copyright (c) 1996 Borland International.
- *
- * $Revision: 5 $
- * $Workfile: I49printer.c $
- *
- * function(s)
- * Hex4 - converts int to 4 hex digits
- * __vprinter - sends formatted output
- */
- #include "Config.h" // Global Configuration - do not remove!
- #pragma inline
- #include <stdio.h>
- #include "ServicesIncludeasmrules.h"
- #include "ServicesInclude_printf.h"
- #define I49_PRINTF 1
- #ifdef I49_PRINTF
- #pragma codeseg _TEXT "CODE"
- #include "cpuv186tv186t.h"
- #endif
- #define I asm
- #define BREAKPOINT asm int 3
- #ifdef I49_PRINTF
- static const far char NullString[] = "(null)";
- #else
- static char NullString[] = "(null)";
- #endif
- /*-----------------------------------------------------------------------*
- Name Hex4 - converts int to 4 hex digits
- Usage static void near pascal Hex4( void )
- Description Convert 16 bit parameter (in dx) to 4 hex digits at ES: [di].
- NOTE: TC does not realize that "stosb" implies DI, so DI is
- not pushed/popped. That is nice, but one day it may cease
- to be true...
- The calling code expects di to be incremented by 4 as a
- side effect of this function.
- *------------------------------------------------------------------------*/
- I _TEXT segment
- I Hex4 proc near
- I mov al,dh
- I call Byte2Ascii
- I mov al,dl
- I Byte2Ascii: /* convert byte in al to ASCII */
- I db 0d4h,10h /* AAM trick to separate nibbles in al */
- I xchg ah,al
- I call Nibble2Ascii
- I xchg ah,al
- I Nibble2Ascii: /* convert hex digit in al to ASCII */
- I add al,90h
- I daa
- I adc al,40h
- I daa
- I stosb
- I ret
- I endp
- I ends
- /*-----------------------------------------------------------------------*
- __vprinter is a table-driven design, for speed and flexibility. There are
- two tables. The first table classifies all 7-bit ASCII chars and then the
- second table is the switch table which points to the function blocks which
- handle the various classes of characters.
- All characters with the 8th bit set are currently classed as don't cares,
- which is the class of character also used for normal alphabetics. All
- characters less than ' ' (0x20) are also classed as don't cares.
- *------------------------------------------------------------------------*/
- typedef
- enum
- {
- _si, /* sign fill +/- */
- _af, /* alternate form */
- _ar, /* format (width or precision) by argument */
- _lj, /* left justify */
- _pr, /* precision */
- _nu, /* numeral */
- _lo, /* long */
- _ld, /* long double */
- _sh, /* short */
- _fz, /* fill zeros */
- _de, /* decimal */
- _oc, /* octal */
- _un, /* unsigned decimal */
- _he, /* hexadecimal */
- _pt, /* pointer */
- _fl, /* float */
- _ch, /* char */
- _st, /* string */
- _ns, /* number sent */
- _zz, /* terminator */
- _dc, /* don't care */
- _pc, /* percent */
- _ne, /* near pointer */
- _fa, /* far pointer */
- } characterClass;
- /* Here is the table of classes, indexed by character. */
- #ifdef I49_PRINTF
- static const far unsigned char printCtype [96] =
- #else
- static unsigned char printCtype [96] =
- #endif
- {
- /* SP ! " # $ % & ' ( ) * + , - . / */
- _si,_dc,_dc,_af,_dc,_pc,_dc,_dc,_dc,_dc,_ar,_si,_dc,_lj,_pr,_dc,
- /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
- _fz,_nu,_nu,_nu,_nu,_nu,_nu,_nu,_nu,_nu,_dc,_dc,_dc,_dc,_dc,_dc,
- /* _ A B C D E F G H I J K L M N O */
- _dc,_dc,_dc,_dc,_dc,_fl,_fa,_fl,_sh,_dc,_dc,_dc,_ld,_dc,_ne,_dc,
- /* P Q R S T U V W X Y Z [ ] ^ _ */
- _dc,_dc,_dc,_dc,_dc,_dc,_dc,_dc,_he,_dc,_dc,_dc,_dc,_dc,_dc,_dc,
- /* ` a b c d e f g h i j k l m n o */
- _dc,_dc,_dc,_ch,_de,_fl,_fl,_fl,_sh,_de,_dc,_dc,_lo,_dc,_ns,_oc,
- /* p q r s t u v w x y z { | } ~ DEL */
- _pt,_dc,_dc,_st,_dc,_un,_dc,_dc,_he,_dc,_dc,_dc,_dc,_dc,_dc,_dc,
- };
- /*---------------------------------------------------------------------*
- Name __vprinter - sends formatted output
- Usage int pascal __vprinter (putnF *putter,
- void *outP,
- const char *formP,
- void _ss *argP)
- Prototype in _printf.h
- Description The list of arguments *argP is combined with literal text in
- the format string *formP according to format specifications
- inside the format string.
- The supplied procedure *putter is used to generate the output.
- It is required to take the string S, which has been
- constructed by __vprinter, and copy it to the destination
- outP. The destination may be a string, a FILE, or whatever
- other class of construct the caller requires. It is possible
- for several calls to be made to *putter since the buffer S
- is of limited size.
- *putter is required to preserve SI, DI.
- The only purpose of the outP argument is to be passed through
- to putter.
- The object at *argP is a record of unknown structure, which
- structure is interpreted with the aid of the format string.
- Each field of the structure may be an integer, long, double,
- or string (char *). Chars may appear but occupy integer-sized
- cells. Floats, character arrays, and structures may not
- appear.
- Return value The result of the function is a count of the characters sent to
- *outP.
- There is no error indication. When an incorrect conversion
- spec is encountered __vprinter copies the format as a literal
- (since it is assumed that alignment with the argument list has
- been lost), beginning with the '%' which introduced the bad
- format.
- If the destination outP is of limited size, for example a
- string or a full disk, __vprinter does not know. Overflowing
- the destination causes undefined results. In some cases
- *putter is able to handle overflows safely, but that is not
- the concern of __vprinter.
- The syntax of the format string is:
- format ::= ([literal] ['%' conversion ])* ;
- conversion ::= '%' | [flag]* [width] ['.' precision]
- ['l'] type ;
- flag ::= '-' | '+' | ' ' | '#' | '0' ;
- width ::= '*' | number ;
- precision ::= '.' ('*' | number) ;
- type ::= 'd'|'i'|'o'|'u'|'x'|'n'|'X'|'f'|'e'|'E'|
- 'g'|'G'|'c'|'s'|'p'|'N'|'F'
- *---------------------------------------------------------------------*/
- #ifdef I49_PRINTF
- int pascal near __I49vprinter (const char *formP, void _ss *argP)
- #else
- int pascal near __vprinter (putnF near *putter,
- void *outP,
- const char *formP,
- void _ss *argP)
- #endif
- {
- #define Ssize 40
- typedef
- enum
- {
- flagStage, fillzStage, wideStage, dotStage, precStage,
- ellStage, typeStage,
- } syntaxStages;
- typedef
- enum
- {
- altFormatBit = 1, /* the '#' flag */
- leftJustBit = 2, /* the '-' flag */
- notZeroBit = 4, /* 0 (octal) or 0x (hex) prefix */
- fillZerosBit = 8, /* zero fill width */
- isLongBit = 16, /* long-type argument */
- farPtrBit = 32, /* far pointers */
- alt0xBit = 64, /* '#' confirmed for %x format */
- floatBit = 128, /* float arg 4 bytes not 8! */
- LongDoubleBit= 256 /* signal a long double argument*/
- } flagBits;
- flagBits flagSet;
- #ifndef I49_PRINTF
- /* do not buffer any data */
- unsigned aP;
- #endif
- char fc; /* format char, from fmt string */
- char isSigned; /* chooses signed/unsigned ints */
- int width;
- int precision;
- char plusSign;
- int leadZ;
- unsigned abandonP; /* posn of bad syntax in fmt str*/
- char tempStr [__CVTMAX__]; /* longest _realcvt or longtoa string*/
- unsigned totalSent = 0; /* characters sent to putter */
- #ifndef I49_PRINTF
- /* do not buffer any data */
- unsigned Scount = Ssize; /* free space remaining in S */
- char S [Ssize]; /* temp working result buffer */
- #endif
- int eof_error = 0; /* flag, TRUE is EOF error */
- #if 0 /* the remaining variables are held entirely in registers */
- char hexCase; /* upper/lower Hex alphabet */
- long tempL;
- syntaxStages stage; -- CH
- char c;
- char *cP;
- int *iP;
- #endif
- SaveSI
- SaveDI
- /*
- General outline of the method:
- First the string is scanned, and conversion specifications detected.
- The preliminary fields of a conversion (flags, width, precision, long)
- are detected and noted.
- The argument is fetched and converted, under the optional guidance of
- the values of the preliminary fields. With the sole exception of the
- 's' conversion, the converted strings are first placed in the tempStr
- buffer.
- The contents of the tempStr (or the argument string for 's') are copied
- to the output, following the guidance of the preliminary fields in
- matters such as zero fill, field width, and justification.
- */
- I jmp short func_start /* Skip over inline nested PROCs */
- /***************************************************************************
- local, nested functions are placed here
- ES *must* be defined in all models.
- ***************************************************************************/
- #define RETN db 0xC3 /* "RETN" is used to force a near ret */
- /* Get length of string pointed to by ES:DI, return result in CX. */
- I vpr_strlen LABEL NEAR /* scan string ES: [DI] up to