Guest User

Untitled

a guest
Jun 24th, 2018
272
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.62 KB | None | 0 0
  1. /*
  2. * Integer vsnprintf, et. al.
  3. *
  4. * Copyright (C) 2018 MURAMATSU Atsushi <amura@tomato.sakura.ne.jp>
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation files
  8. * (the "Software"), to deal in the Software without restriction,
  9. * including without limitation the rights to use, copy, modify, merge,
  10. * publish, distribute, sublicense, and/or sell copies of the Software,
  11. * and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. /*
  26. * integer vsnprintf, et. al. based on BDS C v1.6 library (PDS)
  27. *
  28. * This code provides
  29. * sprintf family:
  30. * my_vsnprintf, my_snprintf, my_vsprintf, my_sprintf,
  31. * and
  32. * fprintf family (if defined WITH_FILEIO macro):
  33. * my_vfprintf, my_fprintf, my_vprintf, my_printf
  34. *
  35. * Supported flags:
  36. * '0': zero padding
  37. * '-': left adgust
  38. * '+': always show sign
  39. * ' ': space presented when value is positive
  40. *
  41. * Supported modifies:
  42. * 'l': long
  43. *
  44. * Supported conversions:
  45. * 'd', 'i': decimal
  46. * 'u': unsigned decimal
  47. * 'o': octal
  48. * 'x': hexadecimal (lower case)
  49. * 'X': hexadecimal (upper case)
  50. * 'b': binary decimal
  51. * 'c': charactor
  52. * 's': string
  53. * '%' and others: non-converted
  54. */
  55. /*
  56. STDLIB2.C -- for BDS C v1.6 -- 1/86
  57. Copyright (c) 1982, 1986 by BD Software, Inc.
  58.  
  59. The files STDLIB1.C, STDLIB2.C and STDLIB3.C contain the source
  60. listings for all functions present in the DEFF.CRL library object
  61. file. (Note: DEFF2.CRL contains the .CSM-coded portions of the
  62. library.)
  63.  
  64. STDLIB2.C contains mainly formatted text I/O functions:
  65.  
  66. printf fprintf sprintf lprintf _spr
  67. scanf fscanf sscanf _scn
  68. getline puts
  69. putdec
  70.  
  71. */
  72.  
  73. #include <stdlib.h>
  74. #include <string.h>
  75. #include <ctype.h>
  76. #include <limits.h>
  77.  
  78. /*** PROTOTYPES ****/
  79. /* #ifndef MY_VSPRINTF_H */
  80. /* #define MY_VSPRINTF_H */
  81.  
  82. /* #define WITH_FILEIO 1 */
  83.  
  84. #include <stdarg.h>
  85. int my_vsnprintf(char *buffer, int n, const char *format, va_list va);
  86. int my_snprintf(char *buffer, int n, const char *format, ...);
  87. int my_vsprintf(char *buffer, const char *format, va_list va);
  88. int my_sprintf(char *buffer, const char *format, ...);
  89.  
  90. #ifdef WITH_FILEIO
  91. #include <stdio.h>
  92. int my_vfprintf(FILE *out, const char *format, va_list va);
  93. int my_fprintf(FILE *out, const char *format, ...);
  94. int my_vprintf(const char *format, va_list va);
  95. int my_printf(const char *format, ...);
  96. #endif /* WITH_FILEIO */
  97.  
  98. /* #endif */ /* MY_VSPRINTF_H */
  99. /*** END OF PROTOTYPES ****/
  100.  
  101. typedef enum { OK, ERROR } _result_t;
  102. static int _spr(const char *format, va_list va,
  103. _result_t (*putcf)(char, void *), void *arg);
  104.  
  105. struct bufdata {
  106. char *bufptr;
  107. char *endbufptr;
  108. };
  109.  
  110. static _result_t
  111. _mem_writer(char c, void *arg)
  112. {
  113. struct bufdata *data = (struct bufdata *)arg;
  114. if (data->endbufptr && data->bufptr >= data->endbufptr)
  115. return ERROR;
  116. *(data->bufptr++) = c;
  117. return OK;
  118. }
  119.  
  120. int
  121. my_vsnprintf(char *buffer, int n, const char *format, va_list va)
  122. {
  123. int s;
  124. struct bufdata data;
  125. if (n == 0) return 0;
  126. data.bufptr = buffer;
  127. data.endbufptr = buffer + n;
  128. _spr(format, va, &_mem_writer, &data);
  129. s = data.bufptr - buffer;
  130. _mem_writer('\0', &data);
  131. buffer[n-1] = '\0';
  132. return s;
  133. }
  134.  
  135. int
  136. my_vsprintf(char *buffer, const char *format, va_list va)
  137. {
  138. int s;
  139. struct bufdata data;
  140. data.bufptr = buffer;
  141. data.endbufptr = NULL;
  142. _spr(format, va, &_mem_writer, &data);
  143. s = data.bufptr - buffer;
  144. _mem_writer('\0', &data);
  145. return s;
  146. }
  147.  
  148. int
  149. my_snprintf(char *buffer, int n, const char *format, ...)
  150. {
  151. int s;
  152. va_list va;
  153. va_start(va, format);
  154. s = my_vsnprintf(buffer, n, format, va);
  155. va_end(va);
  156. return s;
  157. }
  158.  
  159. int
  160. my_sprintf(char *buffer, const char *format, ...)
  161. {
  162. int s;
  163. va_list va;
  164. va_start(va, format);
  165. s = my_vsprintf(buffer, format, va);
  166. va_end(va);
  167. return s;
  168. }
  169.  
  170. #ifdef WITH_FILEIO
  171.  
  172. struct filedata {
  173. FILE *outfile;
  174. int outcount;
  175. };
  176.  
  177. static _result_t
  178. _file_writer(char c, void *arg)
  179. {
  180. struct filedata *data = (struct filedata *)arg;
  181. if (fputc(c, data->outfile) == EOF)
  182. return ERROR;
  183. data->outcount++;
  184. return OK;
  185. }
  186.  
  187. int
  188. my_vfprintf(FILE *out, const char *format, va_list va)
  189. {
  190. struct filedata data;
  191. data.outfile = out;
  192. data.outcount = 0;
  193. _spr(format, va, &_file_writer, &data);
  194. return data.outcount;
  195. }
  196.  
  197. int
  198. my_fprintf(FILE *out, const char *format, ...)
  199. {
  200. int s;
  201. va_list va;
  202. va_start(va, format);
  203. s = my_vfprintf(out, format, va);
  204. va_end(va);
  205. return s;
  206. }
  207.  
  208. int
  209. my_vprintf(const char *format, va_list va)
  210. {
  211. return my_vfprintf(stdout, format, va);
  212. }
  213.  
  214. int
  215. my_printf(const char *format, ...)
  216. {
  217. int s;
  218. va_list va;
  219. va_start(va, format);
  220. s = my_vprintf(format, va);
  221. va_end(va);
  222. return s;
  223. }
  224. #endif /* WITH_FILEIO */
  225.  
  226. /*
  227. Internal routine used by "_spr" to perform ascii-
  228. to-decimal conversion and update an associated pointer:
  229. */
  230.  
  231. static int
  232. _gv2(const char **sptr)
  233. {
  234. int n;
  235. n = 0;
  236. while (isdigit(**sptr))
  237. n = 10*n + *(*sptr)++ - '0';
  238. return n;
  239. }
  240.  
  241. static char
  242. _uspr(char **string, unsigned long n, unsigned base, int upperflag)
  243. {
  244. int length;
  245. if (n < base) {
  246. *(*string)++ = (n < 10) ? n + '0'
  247. : (upperflag ? (n + 'A' - 10) : (n + 'a' - 10));
  248. return 1;
  249. }
  250. length = _uspr(string, n / base, base, upperflag);
  251. _uspr(string, n % base, base, upperflag);
  252. return length + 1;
  253. }
  254.  
  255. static int
  256. _spr(const char *format, va_list va, _result_t (*putcf)(char, void*), void *arg)
  257. {
  258. char c, prefill, *wptr, sign;
  259. long value;
  260. int ljflag, upperflag, longflag;
  261. int base = 10;
  262. char wbuf[128]; /* 128 is enough for all but %s */
  263. int length, *args, width, precision;
  264.  
  265. while ((c = *format++)) {
  266. if (c == '%') {
  267. wptr = wbuf;
  268. precision = INT_MAX;
  269. width = ljflag = upperflag = longflag = 0;
  270. prefill = ' ';
  271. sign = '\0';
  272.  
  273. while (1) {
  274. if (*format == '-')
  275. ljflag = 1;
  276. else if (*format == '0')
  277. prefill = '0';
  278. else if (*format == ' ')
  279. sign = ' ';
  280. else if (*format == '+')
  281. sign = '+';
  282. else
  283. break;
  284. format++;
  285. }
  286. if (*format == '*') {
  287. format++;
  288. width = va_arg(va, int);
  289. }
  290. else if (isdigit(*format))
  291. width = _gv2(&format);
  292. if (*format == '.') {
  293. format++;
  294. if (*format == '*') {
  295. format++;
  296. precision = va_arg(va, int);
  297. }
  298. else {
  299. precision = _gv2(&format);
  300. }
  301. }
  302.  
  303. if (*format == 'l') {
  304. format++;
  305. longflag = 1;
  306. }
  307. switch (c = *format++) {
  308. case 'd':
  309. case 'i':
  310. {
  311. long value;
  312. if (longflag)
  313. value = va_arg(va, long);
  314. else
  315. value = va_arg(va, int);
  316. if (value < 0) {
  317. *wptr++ = '-';
  318. value = -value;
  319. width--;
  320. }
  321. else if (sign != '\0') {
  322. *wptr++ = sign;
  323. width--;
  324. }
  325. width -= _uspr(&wptr, value, base, 0);
  326. }
  327. goto pad;
  328. case 'u':
  329. base = 10; goto val;
  330. case 'b':
  331. base = 2; goto val;
  332. case 'x':
  333. base = 16; goto val;
  334. case 'X':
  335. base = 16; upperflag = 1; goto val;
  336. case 'o':
  337. base = 8;
  338. val:
  339. if (longflag)
  340. width -= _uspr(&wptr, va_arg(va, unsigned long),
  341. base, upperflag);
  342. else
  343. width -= _uspr(&wptr, va_arg(va, unsigned),
  344. base, upperflag);
  345. goto pad;
  346.  
  347. case 'c':
  348. *wptr++ = va_arg(va, int) & 0xff;
  349. width--;
  350. goto pad;
  351.  
  352. pad:
  353. *wptr = '\0';
  354. length = strlen(wptr = wbuf);
  355. pad7: /* don't modify the string at wptr */
  356. if (!ljflag) {
  357. while (width-- > 0)
  358. if (putcf(prefill, arg) == ERROR)
  359. return ERROR;
  360. }
  361. while (length--) {
  362. if (putcf(*wptr++, arg) == ERROR)
  363. return ERROR;
  364. }
  365. if (ljflag) {
  366. while (width-- > 0)
  367. if (putcf(' ', arg) == ERROR)
  368. return ERROR;
  369. }
  370. break;
  371.  
  372. case 's':
  373. wptr = va_arg(va, char *);
  374. length = strlen(wptr);
  375. if (precision < length)
  376. length = precision;
  377. width -= length;
  378. goto pad7;
  379.  
  380. case '\0':
  381. return OK;
  382.  
  383. default:
  384. if (putcf(c, arg) == ERROR)
  385. return ERROR;
  386. }
  387. }
  388. else if (putcf(c, arg) == ERROR)
  389. return ERROR;
  390. }
  391. return OK;
  392. }
  393.  
  394. #ifdef DEBUG
  395. #include <stdio.h>
  396.  
  397. void
  398. test(const char *name, const char *format, ...)
  399. {
  400. char buf1[1024], buf2[1024];
  401. int s1, s2;
  402. va_list va1, va2;
  403. va_start(va1, format);
  404. va_copy(va2, va1);
  405. s1 = vsprintf(buf1, format, va1);
  406. s2 = my_vsprintf(buf2, format, va2);
  407. va_end(va1);
  408. va_end(va2);
  409. if (strcmp(buf1, buf2) != 0)
  410. printf("ERR!:: %s:%s:%s\n", name, buf1, buf2);
  411. if (s1 != s2)
  412. printf("ERR!:: %s: %d != %d\n", name, s1, s2);
  413. /* printf("(%d)%s\n", s1, buf1); */
  414. }
  415.  
  416. int
  417. main()
  418. {
  419. test("test1", "testdata, %d, %10d", 10, 200);
  420. test("test2", "testdata, %s, %10.10s", "dfadf,", "xxxxxxxxxxxxx");
  421. test("test3", "testdata, %x, %10X", 10, 200);
  422. test("test4", "testdata, %X, %10x", 10, 200);
  423. test("test5", "testdata, %ld, %10ld", 1100000000L, 2000000000000L);
  424. test("test6", "testdata, %+d, %+10d", -10, 200);
  425. test("test7", "testdata, %+x, %+o", 10, 200);
  426. test("test8", "testdata, %03x, %04o", 10, 200);
  427. test("test9", "testdata, % 2d, % 3x", 10, 200);
  428. return 0;
  429. }
  430.  
  431. #endif
Add Comment
Please, Sign In to add comment