snprintf.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:11k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1983, 1995, 1996 Eric P. Allman
  3.  * Copyright (c) 1988, 1993
  4.  * The Regents of the University of California.  All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *   must display the following acknowledgement:
  16.  * This product includes software developed by the University of
  17.  * California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *   may be used to endorse or promote products derived from this software
  20.  *   without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34. #ifdef NOT_USED
  35. #include "sendmail.h"
  36. #include "pathnames.h"
  37. #endif
  38. #include "postgres.h"
  39. #include "regex/cdefs.h"
  40. #include <stdio.h>
  41. #include <stdarg.h>
  42. #include <sys/ioctl.h>
  43. #include <sys/param.h>
  44. /*
  45.  * We do all internal arithmetic in the widest available integer type,
  46.  * here called long_long (or ulong_long for unsigned).
  47.  */
  48. #ifdef HAVE_LONG_LONG_INT_64
  49. typedef long long long_long;
  50. typedef unsigned long long ulong_long;
  51. #else
  52. typedef long long_long;
  53. typedef unsigned long ulong_long;
  54. #endif
  55. /*
  56. ** SNPRINTF, VSNPRINT -- counted versions of printf
  57. **
  58. ** These versions have been grabbed off the net.  They have been
  59. ** cleaned up to compile properly and support for .precision and
  60. ** %lx has been added.
  61. */
  62. /**************************************************************
  63.  * Original:
  64.  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
  65.  * A bombproof version of doprnt (dopr) included.
  66.  * Sigh.  This sort of thing is always nasty do deal with. Note that
  67.  * the version here does not include floating point. (now it does ... tgl)
  68.  *
  69.  * snprintf() is used instead of sprintf() as it does limit checks
  70.  * for string length.  This covers a nasty loophole.
  71.  *
  72.  * The other functions are there to prevent NULL pointers from
  73.  * causing nast effects.
  74.  **************************************************************/
  75. /*static char _id[] = "$Id: snprintf.c,v 1.22 1999/05/25 16:10:28 momjian Exp $";*/
  76. static char *end;
  77. static int SnprfOverflow;
  78. int snprintf(char *str, size_t count, const char *fmt,...);
  79. int vsnprintf(char *str, size_t count, const char *fmt, va_list args);
  80. static void dopr(char *buffer, const char *format, va_list args);
  81. int
  82. snprintf(char *str, size_t count, const char *fmt,...)
  83. {
  84. int len;
  85. va_list args;
  86. va_start(args, fmt);
  87. len = vsnprintf(str, count, fmt, args);
  88. va_end(args);
  89. return len;
  90. }
  91. int
  92. vsnprintf(char *str, size_t count, const char *fmt, va_list args)
  93. {
  94. str[0] = 0;
  95. end = str + count - 1;
  96. SnprfOverflow = 0;
  97. dopr(str, fmt, args);
  98. if (count > 0)
  99. end[0] = 0;
  100. if (SnprfOverflow)
  101. elog(NOTICE, "vsnprintf overflow, len = %d, str = %s",
  102.  count, str);
  103. return strlen(str);
  104. }
  105. /*
  106.  * dopr(): poor man's version of doprintf
  107.  */
  108. static void fmtstr(char *value, int ljust, int len, int zpad, int maxwidth);
  109. static void fmtnum(long_long value, int base, int dosign, int ljust, int len, int zpad);
  110. static void fmtfloat(double value, char type, int ljust, int len, int precision, int pointflag);
  111. static void dostr(char *str, int cut);
  112. static void dopr_outch(int c);
  113. static char *output;
  114. static void
  115. dopr(char *buffer, const char *format, va_list args)
  116. {
  117. int ch;
  118. long_long value;
  119. double fvalue;
  120. int longlongflag = 0;
  121. int longflag = 0;
  122. int pointflag = 0;
  123. int maxwidth = 0;
  124. char    *strvalue;
  125. int ljust;
  126. int len;
  127. int zpad;
  128. output = buffer;
  129. while ((ch = *format++))
  130. {
  131. switch (ch)
  132. {
  133. case '%':
  134. ljust = len = zpad = maxwidth = 0;
  135. longflag = longlongflag = pointflag = 0;
  136. nextch:
  137. ch = *format++;
  138. switch (ch)
  139. {
  140. case 0:
  141. dostr("**end of format**", 0);
  142. return;
  143. case '-':
  144. ljust = 1;
  145. goto nextch;
  146. case '0': /* set zero padding if len not set */
  147. if (len == 0 && !pointflag)
  148. zpad = '0';
  149. case '1':
  150. case '2':
  151. case '3':
  152. case '4':
  153. case '5':
  154. case '6':
  155. case '7':
  156. case '8':
  157. case '9':
  158. if (pointflag)
  159. maxwidth = maxwidth * 10 + ch - '0';
  160. else
  161. len = len * 10 + ch - '0';
  162. goto nextch;
  163. case '*':
  164. if (pointflag)
  165. maxwidth = va_arg(args, int);
  166. else
  167. len = va_arg(args, int);
  168. goto nextch;
  169. case '.':
  170. pointflag = 1;
  171. goto nextch;
  172. case 'l':
  173. if (longflag)
  174. longlongflag = 1;
  175. else
  176. longflag = 1;
  177. goto nextch;
  178. case 'u':
  179. case 'U':
  180. /* fmtnum(value,base,dosign,ljust,len,zpad) */
  181. if (longflag)
  182. {
  183. if (longlongflag)
  184. value = va_arg(args, long_long);
  185. else
  186. value = va_arg(args, long);
  187. }
  188. else
  189. value = va_arg(args, int);
  190. fmtnum(value, 10, 0, ljust, len, zpad);
  191. break;
  192. case 'o':
  193. case 'O':
  194. /* fmtnum(value,base,dosign,ljust,len,zpad) */
  195. if (longflag)
  196. {
  197. if (longlongflag)
  198. value = va_arg(args, long_long);
  199. else
  200. value = va_arg(args, long);
  201. }
  202. else
  203. value = va_arg(args, int);
  204. fmtnum(value, 8, 0, ljust, len, zpad);
  205. break;
  206. case 'd':
  207. case 'D':
  208. if (longflag)
  209. {
  210. if (longlongflag)
  211. value = va_arg(args, long_long);
  212. else
  213. value = va_arg(args, long);
  214. }
  215. else
  216. value = va_arg(args, int);
  217. fmtnum(value, 10, 1, ljust, len, zpad);
  218. break;
  219. case 'x':
  220. if (longflag)
  221. {
  222. if (longlongflag)
  223. value = va_arg(args, long_long);
  224. else
  225. value = va_arg(args, long);
  226. }
  227. else
  228. value = va_arg(args, int);
  229. fmtnum(value, 16, 0, ljust, len, zpad);
  230. break;
  231. case 'X':
  232. if (longflag)
  233. {
  234. if (longlongflag)
  235. value = va_arg(args, long_long);
  236. else
  237. value = va_arg(args, long);
  238. }
  239. else
  240. value = va_arg(args, int);
  241. fmtnum(value, -16, 0, ljust, len, zpad);
  242. break;
  243. case 's':
  244. strvalue = va_arg(args, char *);
  245. if (maxwidth > 0 || !pointflag)
  246. {
  247. if (pointflag && len > maxwidth)
  248. len = maxwidth; /* Adjust padding */
  249. fmtstr(strvalue, ljust, len, zpad, maxwidth);
  250. }
  251. break;
  252. case 'c':
  253. ch = va_arg(args, int);
  254. dopr_outch(ch);
  255. break;
  256. case 'e':
  257. case 'E':
  258. case 'f':
  259. case 'g':
  260. case 'G':
  261. fvalue = va_arg(args, double);
  262. fmtfloat(fvalue, ch, ljust, len, maxwidth, pointflag);
  263. break;
  264. case '%':
  265. dopr_outch(ch);
  266. continue;
  267. default:
  268. dostr("???????", 0);
  269. }
  270. break;
  271. default:
  272. dopr_outch(ch);
  273. break;
  274. }
  275. }
  276. *output = 0;
  277. }
  278. static void
  279. fmtstr(char *value, int ljust, int len, int zpad, int maxwidth)
  280. {
  281. int padlen,
  282. strlen; /* amount to pad */
  283. if (value == 0)
  284. value = "<NULL>";
  285. for (strlen = 0; value[strlen]; ++strlen); /* strlen */
  286. if (strlen > maxwidth && maxwidth)
  287. strlen = maxwidth;
  288. padlen = len - strlen;
  289. if (padlen < 0)
  290. padlen = 0;
  291. if (ljust)
  292. padlen = -padlen;
  293. while (padlen > 0)
  294. {
  295. dopr_outch(' ');
  296. --padlen;
  297. }
  298. dostr(value, maxwidth);
  299. while (padlen < 0)
  300. {
  301. dopr_outch(' ');
  302. ++padlen;
  303. }
  304. }
  305. static void
  306. fmtnum(long_long value, int base, int dosign, int ljust, int len, int zpad)
  307. {
  308. int signvalue = 0;
  309. ulong_long uvalue;
  310. char convert[64];
  311. int place = 0;
  312. int padlen = 0; /* amount to pad */
  313. int caps = 0;
  314. /*
  315.  * DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad
  316.  * %dn", value, base, dosign, ljust, len, zpad ));
  317.  */
  318. uvalue = value;
  319. if (dosign)
  320. {
  321. if (value < 0)
  322. {
  323. signvalue = '-';
  324. uvalue = -value;
  325. }
  326. }
  327. if (base < 0)
  328. {
  329. caps = 1;
  330. base = -base;
  331. }
  332. do
  333. {
  334. convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
  335. [uvalue % (unsigned) base];
  336. uvalue = (uvalue / (unsigned) base);
  337. } while (uvalue);
  338. convert[place] = 0;
  339. if (len < 0)
  340. {
  341. /* this could happen with a "*" width spec */
  342. ljust = 1;
  343. len = -len;
  344. }
  345. padlen = len - place;
  346. if (padlen < 0)
  347. padlen = 0;
  348. if (ljust)
  349. padlen = -padlen;
  350. /*
  351.  * DEBUGP(( "str '%s', place %d, sign %c, padlen %dn",
  352.  * convert,place,signvalue,padlen));
  353.  */
  354. if (zpad && padlen > 0)
  355. {
  356. if (signvalue)
  357. {
  358. dopr_outch(signvalue);
  359. --padlen;
  360. signvalue = 0;
  361. }
  362. while (padlen > 0)
  363. {
  364. dopr_outch(zpad);
  365. --padlen;
  366. }
  367. }
  368. while (padlen > 0)
  369. {
  370. dopr_outch(' ');
  371. --padlen;
  372. }
  373. if (signvalue)
  374. dopr_outch(signvalue);
  375. while (place > 0)
  376. dopr_outch(convert[--place]);
  377. while (padlen < 0)
  378. {
  379. dopr_outch(' ');
  380. ++padlen;
  381. }
  382. }
  383. static void
  384. fmtfloat(double value, char type, int ljust, int len, int precision, int pointflag)
  385. {
  386. char fmt[32];
  387. char convert[512];
  388. int padlen = 0; /* amount to pad */
  389. /* we rely on regular C library's sprintf to do the basic conversion */
  390. if (pointflag)
  391. sprintf(fmt, "%%.%d%c", precision, type);
  392. else
  393. sprintf(fmt, "%%%c", type);
  394. sprintf(convert, fmt, value);
  395. if (len < 0)
  396. {
  397. /* this could happen with a "*" width spec */
  398. ljust = 1;
  399. len = -len;
  400. }
  401. padlen = len - strlen(convert);
  402. if (padlen < 0)
  403. padlen = 0;
  404. if (ljust)
  405. padlen = -padlen;
  406. while (padlen > 0)
  407. {
  408. dopr_outch(' ');
  409. --padlen;
  410. }
  411. dostr(convert, 0);
  412. while (padlen < 0)
  413. {
  414. dopr_outch(' ');
  415. ++padlen;
  416. }
  417. }
  418. static void
  419. dostr(char *str, int cut)
  420. {
  421. if (cut)
  422. {
  423. while (*str && cut-- > 0)
  424. dopr_outch(*str++);
  425. }
  426. else
  427. {
  428. while (*str)
  429. dopr_outch(*str++);
  430. }
  431. }
  432. static void
  433. dopr_outch(int c)
  434. {
  435. #ifdef NOT_USED
  436. if (iscntrl(c) && c != 'n' && c != 't')
  437. {
  438. c = '@' + (c & 0x1F);
  439. if (end == 0 || output < end)
  440. *output++ = '^';
  441. }
  442. #endif
  443. if (end == 0 || output < end)
  444. *output++ = c;
  445. else
  446. SnprfOverflow++;
  447. }