PRINTF.C
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:15k
源码类别:

操作系统开发

开发平台:

Asm

  1. /*
  2. ;    File              : $Workfile: PRINTF.C$
  3. ;
  4. ;    Description       :
  5. ;
  6. ;    Original Author   : DIGITAL RESEARCH
  7. ;
  8. ;    Last Edited By    : $CALDERA$
  9. ;
  10. ;-----------------------------------------------------------------------;
  11. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  12. ;      
  13. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  14. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  15. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  16. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  17. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  18. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  19. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  20. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  21. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  22. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  23. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  24. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  25. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  26. ;    CIVIL LIABILITY.
  27. ;-----------------------------------------------------------------------;
  28. ;
  29. ;    *** Current Edit History ***
  30. ;    *** End of Current Edit History ***
  31. ;
  32. ;    $Log$
  33. ;
  34. ;    ENDLOG
  35. */
  36. /*
  37.  * 26 Apr 88 Modify the Long conversion routine to display all 10
  38.  *           digits of a 32 bit integer when displayed in decimal
  39.  * 27 May 88 Added string undefs.
  40.  * 1? Jun 88 Support for CODE relative messages using the FARPTR routine.
  41.  * 05 Jun 89 Add EPRINTF routine to display messages on STDERR
  42.  * 30 Oct 89 dispense with digits & uc_digits in resident portion
  43.  *  8 Nov 89 Replaced ASCII calculation with to_dec(), etc. as used
  44.  *           in APPALIB printf module. Much faster (eg dir /l 10% faster).
  45.  *  8 Jan 90 Added parameter order indexing option.
  46.  *  6-Mar-90 Watcom C v 7.0
  47.  * 26-Mar-90 Make _printf CDECL again, otherwise arg processing screws up
  48.  * 23-May-90 increase printf buffers from 128 to 130
  49.  * 02-Dec-90 Re-work, to flush buffer on n to allow large input strings
  50.  * 28-May-91 local buffer is now on the stack instead of static. Reduces
  51.  *           resident size by 128 bytes.
  52.  * 29-Jul-91 Buffer is now a far one, so output redirection to a file works
  53.  *           on a NOVELL drive when we are in seg FFFF.
  54.  */
  55. #include "defines.h"
  56. #include <string.h>
  57. #if defined(MWC) && defined(strlen)
  58. #undef strcmp /* These are defined as macros in string.h */
  59. #undef strcpy /* which are expaneded in line under */
  60. #undef strlen /* Metaware C. These undefs avoid this. */
  61. #endif
  62. #include <portab.h>
  63. #include "command.h"
  64. #include "dosif.h"
  65. #include "global.h"
  66. #define     PRINTF      -1
  67. #define     EPRINTF     -2
  68. #define     SPRINTF     -3
  69. EXTERN VOID c_write (BYTE *, WORD);
  70. EXTERN BYTE FAR * CDECL farptr (BYTE *);
  71. EXTERN BOOLEAN isdigit (BYTE);
  72. EXTERN BOOLEAN err_flag;
  73. /* forward references */
  74. MLOCAL UWORD CDECL  _printf (BYTE *, UWORD *, UWORD);
  75. MLOCAL VOID arg_ptrs (BYTE FAR *, UWORD *, UWORD **);
  76. MLOCAL BYTE FAR * arg_siz (BYTE FAR *, UBYTE *);
  77. MLOCAL BYTE FAR * arg_num (BYTE FAR *, UWORD *);
  78. MLOCAL BYTE *  to_hex (ULONG, BYTE *, BYTE);
  79. MLOCAL BYTE *   to_dec (ULONG, BYTE *);
  80. MLOCAL BYTE *   to_udec (ULONG, BYTE *);
  81. #define UPPER_CASE ('A'-10)
  82. #define LOWER_CASE ('a'-10)
  83. #define MAX_ARG_NUM 10 /* max args with order indxs */
  84. MLOCAL  BYTE FAR *buff  = NULLPTR;
  85. /*GLOBAL  BYTE str[130];*/
  86. MLOCAL BYTE FAR *str;
  87. GLOBAL WORD CDECL printf(fmt,args)
  88. BYTE *fmt;
  89. UWORD args;
  90. {
  91. UWORD totlen,len;
  92. /*BYTE local_buff[130];*/
  93. UWORD bufsize;
  94. /*str = (BYTE FAR *) local_buff;*/
  95. str = gp_far_buff;
  96. buff = str;  /* use local buffer for printing */
  97. totlen = _printf (fmt,&args,PRINTF); /* build up output string */
  98.         len=(UWORD) buff - (UWORD) str;
  99.         if(len) /* if anything in the buffer   */
  100.     far_write(err_flag ? STDERR:STDOUT, str, len);
  101.      /* then flush it */
  102. return totlen+len; /* Return the String Length */
  103. }
  104. GLOBAL WORD CDECL eprintf(fmt,args)
  105. BYTE *fmt;
  106. UWORD args;
  107. {
  108. UWORD totlen, len;
  109. BYTE local_buff[130];
  110. str = (BYTE FAR *) local_buff;
  111. buff = str;  /* use local buffer for printing */
  112.         err_flag = TRUE;
  113. totlen = _printf (fmt,&args,EPRINTF); /* build up output string */
  114.         len = buff-str;
  115.         if(len) { /* if anything in the buffer   */
  116.             far_write(STDERR,str,len);
  117.   }
  118. err_flag = FALSE;
  119. return totlen+len; /* Return the String Length */
  120. }
  121. GLOBAL WORD CDECL fprintf(handle, fmt, args)
  122. UWORD handle;
  123. BYTE *fmt;
  124. UWORD args;
  125. {
  126. UWORD totlen,len;
  127. UWORD bufsize;
  128. str = gp_far_buff;
  129. buff = str;  /* use local buffer for printing */
  130. totlen =_printf (fmt,&args,handle); /* build up output string */
  131.         len = (UWORD) buff - (UWORD) str;
  132.         if(len) /* if anything in the buffer   */
  133.     far_write(handle, str, len); /* then flush it */
  134. return totlen+len; /* Return the String Length */
  135. }
  136. GLOBAL WORD CDECL sprintf(strg, fmt, args)
  137. BYTE *strg;
  138. BYTE *fmt;
  139. UWORD args;
  140. {
  141. buff = (BYTE FAR *) strg; /* Point buffer at String */
  142. return _printf (fmt,&args,SPRINTF);  /* Generate the String */
  143. }
  144. MLOCAL UWORD CDECL  _printf(fmt_near, args, type)
  145. BYTE *fmt_near;
  146. UWORD     *args;
  147. UWORD        type;
  148. {
  149. BYTE FAR *fmt;
  150. WORD rjust; /* if string/number is right justified */
  151. WORD maxwidth, width;
  152. BOOLEAN long_arg; /* true if next argument is long */
  153. ULONG value;
  154. UWORD uvalue;
  155. WORD i, k;
  156. BYTE FAR *cp;
  157. BYTE c, filler;
  158. BYTE s[40], *sp;
  159. LONG *lp;
  160. UWORD *arg_list[MAX_ARG_NUM];
  161. UWORD arg_idx;
  162.         UWORD totlen=0;
  163. fmt = farptr(fmt_near); /* get full address of format string */
  164. arg_ptrs(fmt, args, arg_list); /* init table of argument addresses */
  165. while ((c = *fmt++) != 0) /* scan format string */
  166. {
  167.     if (c == '%') { /* formatting code found */
  168.     s[14] = 0;
  169.     rjust = YES;
  170.     filler = ' ';
  171.     maxwidth = 0x7fff;
  172.     fmt = arg_num(fmt, &arg_idx); /* get argument index */
  173.     if (arg_idx < MAX_ARG_NUM) { /* valid index? */
  174.         fmt++; /*  yes - skip '%' */
  175.         args = arg_list[arg_idx]; /* lookup address of arg */
  176.     }
  177.     if ((c = *fmt) == '-') { /* string is left justified */
  178.         rjust = NO; /*   ... not right justified */
  179.         c = *fmt++; /* get the next character */
  180.     }
  181.     if (c == '0') /* if leading zeroes desired */
  182.         filler = '0'; /*    use '0' instead of ' ' */
  183.     if (*fmt == '*') { /* if formatting width is parameter */
  184.              /*    then get it from parameters */
  185.         width = (WORD)*args++;
  186.         fmt++; /* skip the asterisk */
  187.         c = *fmt++; /* get next character */
  188.     }
  189.     else /* get full width */
  190.         for (width = 0; (c = *fmt++) >= '0' && c <= '9'; )
  191.         width = width*10 + c - '0';
  192.     if (c == '.') { /* if decimal places specified */
  193.         if (*fmt == '*') { /* if width is a parameter */
  194.         maxwidth = (WORD)*args++;
  195.         fmt++; /* skip the asterisk */
  196.         c = *fmt++; /* get next character */
  197.         }
  198.         else /* get decimal places */
  199.         for (maxwidth = 0; (c = *fmt++) >= '0' && c <= '9' ;)
  200.             maxwidth = maxwidth*10 + c - '0';
  201.     }
  202. /* "%ld", "%lu", "lx" specified */
  203.     long_arg = (c == 'l'); /* is the argument supplied long? */
  204.     if (long_arg) /* if long argument */
  205.         c = *fmt++; /* then skip the 'l' character */
  206.     switch (c) {
  207.         case 'd': /* signed argument */
  208.             if (!long_arg)
  209.             value = (WORD) *args++;
  210.             else {
  211.             lp = (LONG *) args;
  212.             value = *lp++;
  213.             args = (UWORD *) lp;
  214.             }
  215.             break;
  216.     case 'u': /* unsigned argument */
  217.     case 'x':
  218.     case 'X':
  219.         if (!long_arg)
  220.         value = (UWORD) *args++;
  221.         else {
  222.         lp = (LONG *) args;
  223.         value = (ULONG) *lp++;
  224.         args = (UWORD *) lp;
  225.         }
  226.         break;
  227.     default: /* "%s", "%c" */
  228.         uvalue = (UWORD) *args++; /* get string address of char */
  229.     }
  230.     switch (c) { /* now convert to ASCII */
  231.         case 'd': /* signed decimal */
  232.          sp = to_dec(value, s+14);
  233.          break;
  234.         case 'u': /* unsigned decimal */
  235.          sp = to_udec(value, s+14);
  236.          break;
  237.         case 'x': /* unsigned hexadecimal, lower case */
  238.          sp = to_hex(value, s+14, LOWER_CASE);
  239.          break;
  240.         case 'X': /* unsigned hexadecimal, upper case */
  241.             sp = to_hex(value, s+14, UPPER_CASE);
  242.             break;
  243.         case 's': /* string -- could be far */
  244.             cp = farptr((BYTE *)uvalue);
  245.             for (i=0; cp[i] != ''; i++)
  246.                 ;
  247.             goto havelen;
  248.         case 'c':
  249.             c = uvalue;
  250. /* drop into "default:" */
  251.         default: /* normal characters */
  252.             sp = s+13;
  253.             *sp = c;
  254.             break;
  255.     }
  256.     i = (s+14) - sp; /* work out length of string */
  257.     cp = (BYTE FAR *) sp; /* convert to FAR pointer */
  258. havelen:
  259.     if (i > maxwidth)
  260.         i = maxwidth;
  261.     if (rjust) {
  262.         while (width-- > i)
  263.     *buff++ = filler;
  264.     }
  265.     for (k = 0; *cp && k < maxwidth; ++k) {
  266.         if (*cp == 'n')
  267.         *buff++ = 'r';
  268.         *buff++ = *cp++;
  269.     }
  270.     if (!rjust) { /* if right justified */
  271.         while (width-- > i)
  272.         *buff++ = ' ';
  273.     }
  274.     }
  275.     else if (c == 'n') { /* expand newline to CR,LF then flush the buffer */
  276.     *buff++ = 'r';
  277.     *buff++ = 'n';
  278.                 if (type!=SPRINTF) {
  279.                     /* Flush the buffer */
  280.             *buff = ''; /* terminate the string */
  281.                     switch (type) {
  282.                         case PRINTF:
  283.                     far_write(err_flag ? STDERR:STDOUT,str,
  284.      (UWORD) buff - (UWORD) str);
  285.                             break;
  286.                         case EPRINTF:
  287.                     far_write(STDERR, str, buff-str);
  288.                             break;
  289.                         default:
  290.                     far_write(type, str, buff-str);
  291.                             break;
  292.                     } /*ENDSWITCH*/
  293.                     totlen+=buff-str;
  294.                     buff=str;
  295.                 }
  296.     }
  297.     else 
  298.     *buff++ = c;
  299. }
  300. *buff = ''; /* terminate the string */
  301.         return totlen+=buff-str;
  302. }
  303. /* Initialise the table of pointers to all arguments (ptr_list).
  304.    The ptr_list table will not be filled in unless the format
  305.    string (fmt) contains parameter order indexes. */
  306. MLOCAL VOID arg_ptrs(fmt, args, ptr_list)
  307. REG BYTE FAR *fmt; /* ASCIIZ format string */
  308. UWORD *args; /* pointer to first argument */
  309. UWORD     *ptr_list[]; /* list of pointers to all arguments */
  310. {
  311. UWORD arg_cnt; /* running count of parameters found */
  312. UWORD num;
  313. UBYTE size_list[MAX_ARG_NUM]; /* number bytes in each argument */
  314. UWORD i;
  315.     /* Read through format string to determine the size of each argument. */
  316.     for (arg_cnt = 0; ; )
  317.     {
  318.      while (*fmt && *fmt != '%') /* find the next parameter */
  319.     fmt++;
  320. if (!*fmt) /* patameter found? */
  321.     break; /*  no - exit loop */
  322. fmt++; /* skip '%' */
  323. if (*fmt == '%') /* "%%" escape for percent? */
  324. {
  325.     fmt++; /*  yes - skip second '%' */
  326.     continue; /*  and look for next parameter */
  327. }
  328. fmt = arg_num(fmt, &num); /* get this argument's index */
  329. if (num >= MAX_ARG_NUM) /* arg index present and valid? */
  330.     break; /*  no - go no further */
  331. /* record this argument's size */
  332. fmt = arg_siz(fmt, &size_list[num]);
  333. arg_cnt++; /* one more argument found */
  334.     }
  335.     /* Loop once for each argument found in format string, filling in
  336.        the offset for that argument in the size_list table. */
  337.     for (i = 0; i < arg_cnt; i++)
  338.     {
  339.      ptr_list[i] = args; /* record the address of arg */
  340. args += (UWORD)(size_list[i]); /* update ptr by size of arg */
  341.     }
  342. }
  343. /* Determine the size in bytes (siz) of the argument that corresponds to the 
  344.    given format string (fmt). Return a pointer to the character following
  345.    the last in the format string. For example...
  346. fmt        siz
  347.     %d 2
  348. %ld 4
  349. %*d 4
  350. */
  351. MLOCAL BYTE FAR * arg_siz(fmt, siz)
  352. REG BYTE FAR *fmt; /* printf argument format string */
  353. UBYTE *siz; /* returned argument size, in bytes */
  354. {
  355.     *siz = 0; /* argument size not yet known */
  356.     if (*fmt != '%')
  357.      return fmt; /* format string must begin with '%' */
  358.     fmt++; /* skip '%' */
  359.     if (*fmt == '#') /* ignore various formatting ctrls */
  360. fmt++;
  361.     if (*fmt == '-')
  362. fmt++;
  363.     if (*fmt == '0')
  364. fmt++;
  365.     if (*fmt == '*')
  366.     { /* width argument also on stack */
  367. *siz += sizeof(WORD); /* width argument is a WORD */
  368. fmt++;
  369.     }
  370.     else /* ignore any static width control */
  371. while (*fmt >= '0' && *fmt <= '9')
  372.     fmt++;
  373.     if (*fmt == '.')
  374.     {
  375. fmt++;
  376. if (*fmt == '*')
  377. { /* 2nd width argument on stack */
  378.     *siz += sizeof(WORD);
  379.     fmt++;
  380. }
  381. else /* ignore any static width control */
  382.     while (*fmt >= '0' && *fmt <= '9')
  383.      fmt++;
  384.     }
  385.     if (*fmt == 'l')
  386.     {
  387.      *siz += sizeof(LONG);
  388. fmt++;
  389.     }
  390.     else
  391. *siz += sizeof(WORD); /* assume sizeof(WORD)==sizeof(BYTE *) */
  392.     return ++fmt; /* skip final char: 'd', 's', etc. */
  393. }
  394. /* Determine the index number (num) of the argument given by the format
  395.    string (fmt). If the format string does not have a valid index number
  396.    num is set to MAX_ARG_NUM. Return a pointer to the character following
  397.    the last in the index number. For example...
  398. fmt num returned pointer to...
  399. 3%4d 3 '%'
  400. 4d MAX_ARG_NUM '4'
  401. % MAX_ARG_NUM '%'
  402. */
  403. MLOCAL BYTE FAR * arg_num(fmt, num)
  404. BYTE FAR *fmt;
  405. UWORD     *num;
  406. {
  407. REG BYTE FAR *cp;
  408. REG UWORD n;
  409.     *num = MAX_ARG_NUM; /* argument index not yet known */
  410.     cp = fmt;
  411.     if (!isdigit(*cp)) /* at least one digit expected */
  412. return fmt;
  413. /* extract index number */
  414.     for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
  415. n = n * 10 + *cp - '0';
  416.     if (*cp != '%')
  417.      return fmt; /* number must be terminated by '%' */
  418.     *num = n; /* record the index number */
  419.     return cp; /* return pointer to last '%' */
  420. }
  421. MLOCAL BYTE * to_hex(n, s, hex_base)
  422. ULONG   n;
  423. BYTE    *s;
  424. BYTE hex_base; /* 'a'-10 for lowercase, 'A'-10 uppercase */
  425. {
  426. REG UBYTE i;
  427.     do
  428.     {
  429. i = (UBYTE)n & 0x0F;
  430. *--s = (i > 9) ? (hex_base + i) : ('0' + i);
  431. n >>= 4;
  432.     }
  433.     while (n != 0);
  434.     return s;
  435. }
  436. MLOCAL BYTE * to_dec(n, s)
  437. ULONG   n;
  438. BYTE    *s;
  439. {
  440.     if ((LONG)n < 0)
  441.     {
  442. s = to_udec(0 - (LONG)n, s);
  443. *--s = '-'; /* preceed number with sign */
  444. return s;
  445.     }
  446.     else
  447. return to_udec(n, s);
  448. }
  449. MLOCAL BYTE * to_udec(n, s)
  450. ULONG   n;
  451. BYTE    *s;
  452. {
  453.     do
  454.     {
  455. *--s = '0' + (n % 10);
  456. n /= 10;
  457.     } 
  458.     while (n != 0);
  459.     return s;
  460. }