sprintf.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Copyright (C) 2018 bzt (bztsrc@github)
  3. *
  4. * Permission is hereby granted, free of charge, to any person
  5. * obtaining a copy of this software and associated documentation
  6. * files (the "Software"), to deal in the Software without
  7. * restriction, including without limitation the rights to use, copy,
  8. * modify, merge, publish, distribute, sublicense, and/or sell copies
  9. * of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  19. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  20. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. * DEALINGS IN THE SOFTWARE.
  23. *
  24. */
  25. /**
  26. * minimal sprintf implementation
  27. */
  28. unsigned int vsprintf(char *dst, char* fmt, __builtin_va_list args)
  29. {
  30. long int arg;
  31. int len, sign, i;
  32. char *p, *orig=dst, tmpstr[19];
  33. // failsafes
  34. if(dst==(void*)0 || fmt==(void*)0) {
  35. return 0;
  36. }
  37. // main loop
  38. arg = 0;
  39. while(*fmt) {
  40. // argument access
  41. if(*fmt=='%') {
  42. fmt++;
  43. // literal %
  44. if(*fmt=='%') {
  45. goto put;
  46. }
  47. len=0;
  48. // size modifier
  49. while(*fmt>='0' && *fmt<='9') {
  50. len *= 10;
  51. len += *fmt-'0';
  52. fmt++;
  53. }
  54. // skip long modifier
  55. if(*fmt=='l') {
  56. fmt++;
  57. }
  58. // character
  59. if(*fmt=='c') {
  60. arg = __builtin_va_arg(args, int);
  61. *dst++ = (char)arg;
  62. fmt++;
  63. continue;
  64. } else
  65. // decimal number
  66. if(*fmt=='d') {
  67. arg = __builtin_va_arg(args, int);
  68. // check input
  69. sign=0;
  70. if((int)arg<0) {
  71. arg*=-1;
  72. sign++;
  73. }
  74. if(arg>99999999999999999L) {
  75. arg=99999999999999999L;
  76. }
  77. // convert to string
  78. i=18;
  79. tmpstr[i]=0;
  80. do {
  81. tmpstr[--i]='0'+(arg%10);
  82. arg/=10;
  83. } while(arg!=0 && i>0);
  84. if(sign) {
  85. tmpstr[--i]='-';
  86. }
  87. // padding, only space
  88. if(len>0 && len<18) {
  89. while(i>18-len) {
  90. tmpstr[--i]=' ';
  91. }
  92. }
  93. p=&tmpstr[i];
  94. goto copystring;
  95. } else
  96. // hex number
  97. if(*fmt=='x') {
  98. arg = __builtin_va_arg(args, long int);
  99. // convert to string
  100. i=16;
  101. tmpstr[i]=0;
  102. do {
  103. char n=arg & 0xf;
  104. // 0-9 => '0'-'9', 10-15 => 'A'-'F'
  105. tmpstr[--i]=n+(n>9?0x37:0x30);
  106. arg>>=4;
  107. } while(arg!=0 && i>0);
  108. // padding, only leading zeros
  109. if(len>0 && len<=16) {
  110. while(i>16-len) {
  111. tmpstr[--i]='0';
  112. }
  113. }
  114. p=&tmpstr[i];
  115. goto copystring;
  116. } else
  117. // string
  118. if(*fmt=='s') {
  119. p = __builtin_va_arg(args, char*);
  120. copystring: if(p==(void*)0) {
  121. p="(null)";
  122. }
  123. while(*p) {
  124. *dst++ = *p++;
  125. }
  126. }
  127. } else {
  128. put: *dst++ = *fmt;
  129. }
  130. fmt++;
  131. }
  132. *dst=0;
  133. // number of bytes written
  134. return dst-orig;
  135. }
  136. /**
  137. * Variable length arguments
  138. */
  139. unsigned int sprintf(char *dst, char* fmt, ...)
  140. {
  141. __builtin_va_list args;
  142. __builtin_va_start(args, fmt);
  143. return vsprintf(dst,fmt,args);
  144. }