home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / kernex32.zip / mwdd_src.zip / 32bits / ext2-os2 / util / vsprintf.c < prev   
C/C++ Source or Header  |  1997-03-16  |  13KB  |  377 lines

  1. //
  2. // $Header: d:\\32bits\\ext2-os2\\util\\rcs\\vsprintf.c,v 1.2 1997/03/16 13:21:33 Willm Exp $
  3. //
  4.  
  5. // 32 bits OS/2 device driver and IFS support. Provides 32 bits kernel 
  6. // services (DevHelp) and utility functions to 32 bits OS/2 ring 0 code 
  7. // (device drivers and installable file system drivers).
  8. // Copyright (C) 1995, 1996, 1997  Matthieu WILLM (willm@ibm.net)
  9. //
  10. // This program is free software; you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation; either version 2 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program; if not, write to the Free Software
  22. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24. #ifdef __IBMC__
  25. #pragma strings(readonly)
  26. #endif
  27.  
  28. /*
  29.  *  From:
  30.  *
  31.  *  linux/lib/vsprintf.c
  32.  *
  33.  *  Copyright (C) 1991, 1992  Linus Torvalds
  34.  */
  35.  
  36. /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  37. /*
  38.  * Wirzenius wrote this portably, Torvalds fucked it up :-)
  39.  */
  40. #ifdef OS2
  41. #include <string.h>
  42. #include <os2.h>
  43. #include <os2/types.h>
  44. #include <os2/StackToFlat.h>
  45. #include <os2/DevHlp32.h>
  46. #endif
  47. #include <stdarg.h>
  48. #ifdef OS2
  49. #define VA_START(ap, last) ap = ((va_list)__StackToFlat(&last)) + __nextword(last)
  50. #endif
  51.  
  52. #ifndef OS2
  53. #include <linux/types.h>
  54. #include <linux/string.h>
  55. #include <linux/ctype.h>
  56. #else
  57.  
  58.  
  59. static int skip_atoi(const char **s);
  60. static char * number(char * str, long num, int base, int size, int precision, int type);
  61. int sprintf(char * buf, const char *fmt, ...);
  62. int DH32ENTRY vsprintf(char *buf, const char *fmt, va_list args);
  63.  
  64.  
  65. #if !defined(MINIFSD) && !defined(MWDD32) && !defined(FSD32)
  66. /*
  67.  * Routines accessed in interrupt context (here through the 'printk' call)
  68.  */
  69. #pragma alloc_text(EXT2_FIXED_CODE, sprintf)
  70. #pragma alloc_text(EXT2_FIXED_CODE, vsprintf)
  71. #pragma alloc_text(EXT2_FIXED_CODE, number)
  72. #pragma alloc_text(EXT2_FIXED_CODE, skip_atoi)
  73. #endif
  74.  
  75. #endif
  76.  
  77. size_t strnlen(const char * s, size_t count)
  78. {
  79.         const char *sc;
  80.  
  81.         for (sc = s; *sc != '\0' && count--; ++sc)
  82.                 /* nothing */;
  83.         return sc - s;
  84. }
  85. #ifdef XXXFSD32
  86. unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
  87. {
  88.         unsigned long result = 0,value;
  89.  
  90.         if (!base) {
  91.                 base = 10;
  92.                 if (*cp == '0') {
  93.                         base = 8;
  94.                         cp++;
  95.                         if ((*cp == 'x') && isxdigit(cp[1])) {
  96.                                 cp++;
  97.                                 base = 16;
  98.                         }
  99.                 }
  100.         }
  101.         while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
  102.             ? toupper(*cp) : *cp)-'A'+10) < base) {
  103.                 result = result*base + value;
  104.                 cp++;
  105.         }
  106.         if (endp)
  107.                 *endp = (char *)cp;
  108.         return result;
  109. }
  110. #endif
  111. /* we use this so that we can do without the ctype library */
  112. #define is_digit(c)     ((c) >= '0' && (c) <= '9')
  113.  
  114. static int skip_atoi(const char **s)
  115. {
  116.         int i=0;
  117.  
  118.         while (is_digit(**s))
  119.                 i = i*10 + *((*s)++) - '0';
  120.         return i;
  121. }
  122.  
  123. #define ZEROPAD 1               /* pad with zero */
  124. #define SIGN    2               /* unsigned/signed long */
  125. #define PLUS    4               /* show plus */
  126. #define SPACE   8               /* space if plus */
  127. #define LEFT    16              /* left justified */
  128. #define SPECIAL 32              /* 0x */
  129. #define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */
  130.  
  131. #ifndef OS2
  132. #define do_div(n,base) ({ \
  133. int __res; \
  134. __res = ((unsigned long) n) % (unsigned) base; \
  135. n = ((unsigned long) n) / (unsigned) base; \
  136. __res; })
  137. #endif
  138.  
  139. static char * number(char * str, long num, int base, int size, int precision
  140.         ,int type)
  141. {
  142.         char c,sign,tmp[66];
  143.         const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
  144.         int i;
  145.  
  146.         if (type & LARGE)
  147.                 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  148.         if (type & LEFT)
  149.                 type &= ~ZEROPAD;
  150.         if (base < 2 || base > 36)
  151.                 return 0;
  152.         c = (type & ZEROPAD) ? '0' : ' ';
  153.         sign = 0;
  154.         if (type & SIGN) {
  155.                 if (num < 0) {
  156.                         sign = '-';
  157.                         num = -num;
  158.                         size--;
  159.                 } else if (type & PLUS) {
  160.                         sign = '+';
  161.                         size--;
  162.                 } else if (type & SPACE) {
  163.                         sign = ' ';
  164.                         size--;
  165.                 }
  166.         }
  167.         if (type & SPECIAL) {
  168.                 if (base == 16)
  169.                         size -= 2;
  170.                 else if (base == 8)
  171.                         size--;
  172.         }
  173.         i = 0;
  174.         if (num == 0)
  175.                 tmp[i++]='0';
  176. #ifndef OS2
  177.         else while (num != 0)
  178.                 tmp[i++] = digits[do_div(num,base)];
  179. #else
  180.         else while (num != 0) {
  181.                 unsigned long __res;
  182.                 __res = ((unsigned long) num) % (unsigned long) base;
  183.                 num = ((unsigned long) num) / (unsigned long) base;
  184.                 tmp[i++] = digits[__res];
  185.              }
  186. #endif
  187.         if (i > precision)
  188.                 precision = i;
  189.         size -= precision;
  190.         if (!(type&(ZEROPAD+LEFT)))
  191.                 while(size-->0)
  192.                         *str++ = ' ';
  193.         if (sign)
  194.                 *str++ = sign;
  195.         if (type & SPECIAL)
  196.                 if (base==8)
  197.                         *str++ = '0';
  198.                 else if (base==16) {
  199.                         *str++ = '0';
  200.                         *str++ = digits[33];
  201.                 }
  202.         if (!(type & LEFT))
  203.                 while (size-- > 0)
  204.                         *str++ = c;
  205.         while (i < precision--)
  206.                 *str++ = '0';
  207.         while (i-- > 0)
  208.                 *str++ = tmp[i];
  209.         while (size-- > 0)
  210.                 *str++ = ' ';
  211.         return str;
  212. }
  213.  
  214. int DH32ENTRY vsprintf(char *buf, const char *fmt, va_list args)
  215. {
  216.         int len;
  217.         unsigned long num;
  218.         int i, base;
  219.         char * str;
  220.         char *s;
  221.  
  222.         int flags;              /* flags to number() */
  223.  
  224.         int field_width;        /* width of output field */
  225.         int precision;          /* min. # of digits for integers; max
  226.                                    number of chars for from string */
  227.         int qualifier;          /* 'h', 'l', or 'L' for integer fields */
  228.  
  229.         for (str=buf ; *fmt ; ++fmt) {
  230.                 if (*fmt != '%') {
  231.                         *str++ = *fmt;
  232.                         continue;
  233.                 }
  234.  
  235.                 /* process flags */
  236.                 flags = 0;
  237.                 repeat:
  238.                         ++fmt;          /* this also skips first '%' */
  239.                         switch (*fmt) {
  240.                                 case '-': flags |= LEFT; goto repeat;
  241.                                 case '+': flags |= PLUS; goto repeat;
  242.                                 case ' ': flags |= SPACE; goto repeat;
  243.                                 case '#': flags |= SPECIAL; goto repeat;
  244.                                 case '0': flags |= ZEROPAD; goto repeat;
  245.                                 }
  246.  
  247.                 /* get field width */
  248.                 field_width = -1;
  249.                 if (is_digit(*fmt))
  250.                         field_width = skip_atoi(__StackToFlat(&fmt));
  251.                 else if (*fmt == '*') {
  252.                         ++fmt;
  253.                         /* it's the next argument */
  254.                         field_width = va_arg(args, int);
  255.                         if (field_width < 0) {
  256.                                 field_width = -field_width;
  257.                                 flags |= LEFT;
  258.                         }
  259.                 }
  260.  
  261.                 /* get the precision */
  262.                 precision = -1;
  263.                 if (*fmt == '.') {
  264.                         ++fmt;
  265.                         if (is_digit(*fmt))
  266.                                 precision = skip_atoi(__StackToFlat(&fmt));
  267.                         else if (*fmt == '*') {
  268.                                 ++fmt;
  269.                                 /* it's the next argument */
  270.                                 precision = va_arg(args, int);
  271.                         }
  272.                         if (precision < 0)
  273.                                 precision = 0;
  274.                 }
  275.  
  276.                 /* get the conversion qualifier */
  277.                 qualifier = -1;
  278.                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  279.                         qualifier = *fmt;
  280.                         ++fmt;
  281.                 }
  282.  
  283.                 /* default base */
  284.                 base = 10;
  285.  
  286.                 switch (*fmt) {
  287.                 case 'c':
  288.                         if (!(flags & LEFT))
  289.                                 while (--field_width > 0)
  290.                                         *str++ = ' ';
  291.                         *str++ = (unsigned char) va_arg(args, int);
  292.                         while (--field_width > 0)
  293.                                 *str++ = ' ';
  294.                         continue;
  295.  
  296.                 case 's':
  297.                         s = va_arg(args, char *);
  298.                         if (!s)
  299.                                 s = "<NULL>";
  300.  
  301.                         len = strnlen(s, precision);
  302.  
  303.                         if (!(flags & LEFT))
  304.                                 while (len < field_width--)
  305.                                         *str++ = ' ';
  306.                         for (i = 0; i < len; ++i)
  307.                                 *str++ = *s++;
  308.                         while (len < field_width--)
  309.                                 *str++ = ' ';
  310.                         continue;
  311.  
  312.                 case 'p':
  313.                         if (field_width == -1) {
  314.                                 field_width = 2*sizeof(void *);
  315.                                 flags |= ZEROPAD;
  316.                         }
  317.                         str = number(str,
  318.                                 (unsigned long) va_arg(args, void *), 16,
  319.                                 field_width, precision, flags);
  320.                         continue;
  321.  
  322.  
  323.                 case 'n':
  324.                         if (qualifier == 'l') {
  325.                                 long * ip = va_arg(args, long *);
  326.                                 *ip = (str - buf);
  327.                         } else {
  328.                                 int * ip = va_arg(args, int *);
  329.                                 *ip = (str - buf);
  330.                         }
  331.                         continue;
  332.  
  333.                 /* integer number formats - set up the flags and "break" */
  334.                 case 'o':
  335.                         base = 8;
  336.                         break;
  337.  
  338.                 case 'X':
  339.                         flags |= LARGE;
  340.                 case 'x':
  341.                         base = 16;
  342.                         break;
  343.  
  344.                 case 'd':
  345.                 case 'i':
  346.                         flags |= SIGN;
  347.                 case 'u':
  348.                         break;
  349.  
  350.                 default:
  351.                         if (*fmt != '%')
  352.                                 *str++ = '%';
  353.                         if (*fmt)
  354.                                 *str++ = *fmt;
  355.                         else
  356.                                 --fmt;
  357.                         continue;
  358.                 }
  359.                 if (qualifier == 'l')
  360.                         num = va_arg(args, unsigned long);
  361.                 else if (qualifier == 'h')
  362.                         if (flags & SIGN)
  363.                                 num = va_arg(args, short);
  364.                         else
  365.                                 num = va_arg(args, unsigned short);
  366.                 else if (flags & SIGN)
  367.                         num = va_arg(args, int);
  368.                 else
  369.                         num = va_arg(args, unsigned int);
  370.                 str = number(str, num, base, field_width, precision, flags);
  371.         }
  372.         *str = '\0';
  373.         return str-buf;
  374. }
  375.  
  376.  
  377.