format.c
上传用户:weiliju62
上传日期:2007-01-06
资源大小:619k
文件大小:15k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)format.c 1.29 98/03/31 Copyright 1985 J. Schilling */
  2. /*
  3.  * format
  4.  * common code for printf fprintf & sprintf
  5.  *
  6.  * allows recursive printf with "%r", used in:
  7.  * error, comerr, comerrno, errmsg, errmsgno and the like
  8.  *
  9.  * Copyright (c) 1985 J. Schilling
  10.  */
  11. /*
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2, or (at your option)
  15.  * any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; see the file COPYING.  If not, write to
  24.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26. #include <mconfig.h>
  27. #include <vadefs.h>
  28. #include <strdefs.h>
  29. #include <stdxlib.h>
  30. #ifndef HAVE_STDLIB_H
  31. extern char *gcvt __PR((double, int, char *));
  32. #endif
  33. #include <standard.h>
  34. /*
  35.  * Some CPU's (e.g. PDP-11) cannot do logical shifts.
  36.  * They use rotate instead. Masking the low bits before,
  37.  * makes rotate work too.
  38.  */
  39. #define allmask(t) ((unsigned t)~((unsigned t)0))
  40. #define lowmask(t, x) ((unsigned t)~((unsigned t)((1 << (x))-1) ))
  41. #define rshiftmask(t, s)((allmask(t) & lowmask(t, s)) >> (s))
  42. #define CHARMASK makemask(char)
  43. #define SHORTMASK makemask(short)
  44. #define INTMASK makemask(int)
  45. #define LONGMASK makemask(long)
  46. #ifdef DIVLBYS
  47. extern long divlbys();
  48. extern long modlbys();
  49. #else
  50. #define divlbys(val, base) ((val)/(base))
  51. #define modlbys(val, base) ((val)%(base))
  52. #endif
  53. /*
  54.  * We use macros here to avoid the need to link to the international
  55.  * character routines.
  56.  * We don't need internationalization for our purpose.
  57.  */
  58. #define is_dig(c) (((c) >= '0') && ((c) <= '9'))
  59. #define is_cap(c) ((c) >= 'A' && (c) <= 'Z')
  60. #define to_cap(c) (is_cap(c) ? c : c - 'a' + 'A')
  61. #define cap_ty(c) (is_cap(c) ? 'L' : 'I')
  62. typedef unsigned int Uint;
  63. typedef unsigned short Ushort;
  64. typedef unsigned long Ulong;
  65. #ifdef HAVE_LONGLONG
  66. typedef unsigned long long Ullong;
  67. #endif
  68. typedef struct f_args {
  69. void (*outf) __PR((char, long)); /* Func from format(fun, arg) */
  70. long farg;     /* Arg from format (fun, arg) */
  71. int minusflag;
  72. int flags;
  73. int fldwidth;
  74. int signific;
  75. int lzero;
  76. char *buf;
  77. char *bufp;
  78. char fillc;
  79. char *prefix;
  80. int prefixlen;
  81. } f_args;
  82. #define MINUSFLG 1 /* '-' flag */
  83. #define PLUSFLG 2 /* '+' flag */
  84. #define SPACEFLG 4 /* ' ' flag */
  85. #define HASHFLG 8 /* '#' flag */
  86. LOCAL void prnum  __PR((Ulong, unsigned, f_args *));
  87. LOCAL void prdnum __PR((Ulong, f_args *));
  88. LOCAL void pronum __PR((Ulong, f_args *));
  89. LOCAL void prxnum __PR((Ulong, f_args *));
  90. LOCAL void prXnum __PR((Ulong, f_args *));
  91. LOCAL int prbuf  __PR((const char *, f_args *));
  92. LOCAL int prc    __PR((char, f_args *));
  93. LOCAL int prstring __PR((const char *, f_args *));
  94. #ifdef PROTOTYPES
  95. EXPORT int format( void (*fun)(char, long),
  96. long farg,
  97. const char *fmt,
  98. va_list args)
  99. #else
  100. EXPORT int format(fun, farg, fmt, args)
  101. register void (*fun)();
  102. register long farg;
  103. register char *fmt;
  104. va_list args;
  105. #endif
  106. {
  107. char buf[512];
  108. const char *sfmt;
  109. register int unsflag;
  110. register long val;
  111. register char type;
  112. register char mode;
  113. register char c;
  114. int count;
  115. int i;
  116. short sh;
  117. const char *str;
  118. double dval;
  119. Ulong res;
  120. char *rfmt;
  121. f_args fa;
  122. fa.outf = fun;
  123. fa.farg = farg;
  124. count = 0;
  125. /*
  126.  * Main loop over the format string.
  127.  * Increment and check for end of string is made here.
  128.  */
  129. for(; *fmt != ''; fmt++) {
  130. c = *fmt;
  131. while (c != '%') {
  132. if (c == '')
  133. return (count);
  134. (*fun)(c, farg);
  135. c = *(++fmt);
  136. count++;
  137. }
  138. /*
  139.  * We reached a '%' sign.
  140.  */
  141. buf[0] = '';
  142. fa.buf = fa.bufp = buf;
  143. fa.minusflag = 0;
  144. fa.flags = 0;
  145. fa.fldwidth = 0;
  146. fa.signific = -1;
  147. fa.lzero = 0;
  148. fa.fillc = ' ';
  149. fa.prefixlen = 0;
  150. sfmt = fmt;
  151. unsflag = FALSE;
  152. newflag:
  153. switch (*(++fmt)) {
  154. case '+':
  155. fa.flags |= PLUSFLG;
  156. goto newflag;
  157. case '-':
  158. fa.minusflag++;
  159. goto newflag;
  160. case ' ':
  161. /*
  162.  * If the space and the + flag are present,
  163.  * the space flag will be ignored.
  164.  */
  165. fa.flags |= SPACEFLG;
  166. goto newflag;
  167. case '#':
  168. fa.flags |= HASHFLG;
  169. goto newflag;
  170. case '0':
  171. /*
  172.  * '0' is a flag.
  173.  */
  174. fa.fillc = '0';
  175. goto newflag;
  176. }
  177. if (*fmt == '*') {
  178. fmt++;
  179. fa.fldwidth = va_arg(args, int);
  180. /*
  181.  * A negative fieldwith is a minus flag with a
  182.  * positive fieldwidth.
  183.  */
  184. if (fa.fldwidth < 0) {
  185. fa.fldwidth = -fa.fldwidth;
  186. /* fa.minusflag ^= 1;*/
  187. fa.minusflag = 1;
  188. }
  189. } else while (c = *fmt, is_dig(c)) {
  190. fa.fldwidth *= 10;
  191. fa.fldwidth += c - '0';
  192. fmt++;
  193. }
  194. if (*fmt == '.') {
  195. fmt++;
  196. fa.signific = 0;
  197. if (*fmt == '*') {
  198. fmt++;
  199. fa.signific = va_arg(args, int);
  200. if (fa.signific < 0)
  201. fa.signific = 0;
  202. } else while (c = *fmt, is_dig(c)) {
  203. fa.signific *= 10;
  204. fa.signific += c - '0';
  205. fmt++;
  206. }
  207. }
  208. if (strchr("UCSIL", *fmt)) {
  209. /*
  210.  * Enhancements to K&R and ANSI:
  211.  *
  212.  * got a type specifyer
  213.  */
  214. if (*fmt == 'U') {
  215. fmt++;
  216. unsflag = TRUE;
  217. }
  218. if (!strchr("CSILZODX", *fmt)) {
  219. /*
  220.  * Got only 'U'nsigned specifyer,
  221.  * use default type and mode.
  222.  */
  223. type = 'I';
  224. mode = 'D';
  225. fmt--;
  226. } else if (!strchr("CSIL", *fmt)) {
  227. /*
  228.  * no type, use default
  229.  */
  230. type = 'I';
  231. mode = *fmt;
  232. } else {
  233. /*
  234.  * got CSIL
  235.  */
  236. type = *fmt++;
  237. if (!strchr("ZODX", mode = *fmt)) {
  238. fmt--;
  239. mode = 'D';/* default mode */
  240. }
  241. }
  242. } else switch(*fmt) {
  243. case 'h':
  244. type = 'S'; /* convert to type */
  245. goto getmode;
  246. case 'l':
  247. type = 'L'; /* convert to type */
  248. getmode:
  249. if (!strchr("udioxX", *(++fmt))) {
  250. fmt--;
  251. mode = 'D';
  252. } else {
  253. mode = *fmt;
  254. if (mode != 'x')
  255. mode = to_cap(mode);
  256. if (mode == 'U')
  257. unsflag = TRUE;
  258. else if (mode == 'I') /*XXX */
  259. mode = 'D';
  260. }
  261. break;
  262. case 'x':
  263. mode = 'x';
  264. goto havemode;
  265. case 'u':
  266. unsflag = TRUE;
  267. case 'o': case 'O':
  268. case 'd': case 'D':
  269. case 'i': case 'I':
  270. case 'p':
  271. case 'X':
  272. case 'z': case 'Z':
  273. mode = to_cap(*fmt);
  274. havemode:
  275. type = cap_ty(*fmt);
  276. if (mode == 'I') /*XXX kann entfallen*/
  277. mode = 'D'; /*wenn besseres uflg*/
  278. break;
  279. case '%':
  280. count += prc('%', &fa);
  281. continue;
  282. case ' ':
  283. count += prbuf("", &fa);
  284. continue;
  285. case 'c':
  286. c = va_arg(args, int);
  287. count += prc(c, &fa);
  288. continue;
  289. case 's':
  290. str = va_arg(args, char *);
  291. count += prstring(str, &fa);
  292. continue;
  293. case 'b':
  294. str = va_arg(args, char *);
  295. fa.signific = va_arg(args, int);
  296. count += prstring(str, &fa);
  297. continue;
  298. #ifndef NO_FLOATINGPOINT
  299. case 'e':
  300. if (fa.signific == -1)
  301. fa.signific = 6;
  302. dval = va_arg(args, double);
  303. ftoes(buf, dval, 0, fa.signific);
  304. count += prbuf(buf, &fa);
  305. continue;
  306. case 'f':
  307. if (fa.signific == -1)
  308. fa.signific = 6;
  309. dval = va_arg(args, double);
  310. ftofs(buf, dval, 0, fa.signific);
  311. count += prbuf(buf, &fa);
  312. continue;
  313. case 'g':
  314. if (fa.signific == -1)
  315. fa.signific = 6;
  316. if (fa.signific == 0)
  317. fa.signific = 1;
  318. dval = va_arg(args, double);
  319. gcvt(dval, fa.signific, buf);
  320. count += prbuf(buf, &fa);
  321. continue;
  322. #else
  323. # ifdef USE_FLOATINGARGS
  324. case 'e':
  325. case 'f':
  326. case 'g':
  327. dval = va_arg(args, double);
  328. continue;
  329. # endif
  330. #endif
  331. case 'r': /* recursive printf */
  332. case 'R': /* recursive printf */
  333. rfmt  = va_arg(args, char *);
  334. /*
  335.  * I don't know any portable way to get an arbitrary
  336.  * C object from a var arg list so I use a
  337.  * system-specific routine __va_arg_list() that knows
  338.  * if 'va_list' is an array. You will not be able to
  339.  * assign the value of __va_arg_list() but it works
  340.  * to be used as an argument of a function.
  341.  * It is a requirement for recursive printf to be able
  342.  * to use this function argument. If your system
  343.  * defines va_list to be an array you need to know this
  344.  * via autoconf or another mechanism.
  345.  * It would be nice to have something like
  346.  * __va_arg_list() in stdarg.h
  347.  */
  348. count += format(fun, farg, rfmt, __va_arg_list(args));
  349. continue;
  350. case 'n':
  351. {
  352. int *ip = va_arg(args, int *);
  353. *ip = count;
  354. }
  355. continue;
  356. default: /* Unknown '%' format */
  357. sfmt++; /* Dont't print '%'   */
  358. count += fmt - sfmt;
  359. while (sfmt < fmt)
  360. (*fun)(*(sfmt++), farg);
  361. if (*fmt == '') {
  362. fmt--;
  363. continue;
  364. } else {
  365. (*fun)(*fmt, farg);
  366. count++;
  367. continue;
  368. }
  369. }
  370. /*
  371.  * print numbers:
  372.  * first prepare type 'C'har, 'S'hort, 'I'nt, or 'L'ong
  373.  */
  374. switch(type) {
  375. case 'C':
  376. c = va_arg(args, int);
  377. val = c; /* extend sign here */
  378. if (unsflag || mode != 'D')
  379. #ifdef DO_MASK
  380. val &= CHARMASK;
  381. #else
  382. val = (unsigned char)val;
  383. #endif
  384. break;
  385. case 'S':
  386. sh = va_arg(args, int);
  387. val = sh; /* extend sign here */
  388. if (unsflag || mode != 'D')
  389. #ifdef DO_MASK
  390. val &= SHORTMASK;
  391. #else
  392. val = (unsigned short)val;
  393. #endif
  394. break;
  395. case 'I':
  396. default:
  397. i = va_arg(args, int);
  398. val = i; /* extend sign here */
  399. if (unsflag || mode != 'D')
  400. #ifdef DO_MASK
  401. val &= INTMASK;
  402. #else
  403. val = (unsigned int)val;
  404. #endif
  405. break;
  406. case 'P':
  407. case 'L':
  408. val = va_arg(args, long);
  409. break;
  410. }
  411. /*
  412.  * Final print out, take care of mode:
  413.  * mode is one of: 'O'ctal, 'D'ecimal, or he'X'
  414.  * oder 'Z'weierdarstellung.
  415.  */
  416. fa.bufp = &buf[sizeof(buf)-1];
  417. *--fa.bufp = '';
  418. if (val == 0 && mode != 'D') {
  419. printzero:
  420. /*
  421.  * Printing '0' with fieldwidth 0 results in no chars.
  422.  */
  423. fa.lzero = -1;
  424. if (fa.signific >= 0)
  425. fa.fillc = ' ';
  426. count += prstring("0", &fa);
  427. continue;
  428. } else switch(mode) {
  429. case 'D':
  430. if (!unsflag && val < 0) {
  431. fa.prefix = "-";
  432. fa.prefixlen = 1;
  433. val = -val;
  434. } else if (fa.flags & PLUSFLG) {
  435. fa.prefix = "+";
  436. fa.prefixlen = 1;
  437. } else if (fa.flags & SPACEFLG) {
  438. fa.prefix = " ";
  439. fa.prefixlen = 1;
  440. }
  441. if (val == 0)
  442. goto printzero;
  443. case 'U':
  444. /* output a long unsigned decimal number */
  445. prdnum(val, &fa);
  446. break;
  447. case 'O':
  448. /* output a long octal number */
  449. if (fa.flags & HASHFLG) {
  450. fa.prefix = "0";
  451. fa.prefixlen = 1;
  452. }
  453. pronum(val & 07, &fa);
  454. if ((res = (val>>3) & rshiftmask(long, 3)) != 0)
  455. pronum(res, &fa);
  456. break;
  457. case 'p':
  458. case 'x':
  459. /* output a hex long */
  460. if (fa.flags & HASHFLG) {
  461. fa.prefix = "0x";
  462. fa.prefixlen = 2;
  463. }
  464. prxnum(val & 0xF, &fa);
  465. if ((res = (val>>4) & rshiftmask(long, 4)) != 0)
  466. prxnum(res, &fa);
  467. break;
  468. case 'P':
  469. case 'X':
  470. /* output a hex long */
  471. if (fa.flags & HASHFLG) {
  472. fa.prefix = "0X";
  473. fa.prefixlen = 2;
  474. }
  475. prXnum(val & 0xF, &fa);
  476. if ((res = (val>>4) & rshiftmask(long, 4)) != 0)
  477. prXnum(res, &fa);
  478. break;
  479. case 'Z':
  480. /* output a binary long */
  481. prnum(val & 0x1, 2, &fa);
  482. if ((res = (val>>1) & rshiftmask(long, 1)) != 0)
  483. prnum(res, 2, &fa);
  484. }
  485. fa.lzero = -1;
  486. /*
  487.  * If a precision (fielwidth) is specified
  488.  * on diouXx conversions, the '0' flag is ignored.
  489.  */
  490. if (fa.signific >= 0)
  491. fa.fillc = ' ';
  492. count += prbuf(fa.bufp, &fa);
  493. }
  494. return (count);
  495. }
  496. /*
  497.  * Routines to print (not negative) numbers in an arbitrary base
  498.  */
  499. LOCAL unsigned char dtab[]  = "0123456789abcdef";
  500. LOCAL unsigned char udtab[] = "0123456789ABCDEF";
  501. LOCAL void prnum(val, base, fa)
  502. register Ulong val;
  503. register unsigned base;
  504. f_args *fa;
  505. {
  506. register char *p = fa->bufp;
  507. do {
  508. *--p = dtab[modlbys(val, base)];
  509. val = divlbys(val, base);
  510. } while (val > 0);
  511. fa->bufp = p;
  512. }
  513. LOCAL void prdnum(val, fa)
  514. register Ulong val;
  515. f_args *fa;
  516. {
  517. register char *p = fa->bufp;
  518. do {
  519. *--p = dtab[modlbys(val, (unsigned)10)];
  520. val = divlbys(val, (unsigned)10);
  521. } while (val > 0);
  522. fa->bufp = p;
  523. }
  524. /*
  525.  * We may need to use division here too (PDP-11, non two's complement ...)
  526.  */
  527. LOCAL void pronum(val, fa)
  528. register Ulong val;
  529. f_args *fa;
  530. {
  531. register char *p = fa->bufp;
  532. do {
  533. *--p = dtab[val & 7];
  534. val >>= 3;
  535. } while (val > 0);
  536. fa->bufp = p;
  537. }
  538. LOCAL void prxnum(val, fa)
  539. register Ulong val;
  540. f_args *fa;
  541. {
  542. register char *p = fa->bufp;
  543. do {
  544. *--p = dtab[val & 15];
  545. val >>= 4;
  546. } while (val > 0);
  547. fa->bufp = p;
  548. }
  549. LOCAL void prXnum(val, fa)
  550. register Ulong val;
  551. f_args *fa;
  552. {
  553. register char *p = fa->bufp;
  554. do {
  555. *--p = udtab[val & 15];
  556. val >>= 4;
  557. } while (val > 0);
  558. fa->bufp = p;
  559. }
  560. /*
  561.  * Final buffer print out routine.
  562.  */
  563. LOCAL int prbuf(s, fa)
  564. register const char *s;
  565. f_args *fa;
  566. {
  567. register int diff;
  568. register int rfillc;
  569. register long arg = fa->farg;
  570. register void (*fun) __PR((char, long)) = fa->outf;
  571. register int count;
  572. register int lzero = 0;
  573. count = strlen(s);
  574. if (fa->lzero < 0 && count < fa->signific)
  575. lzero = fa->signific - count;
  576. diff = fa->fldwidth - lzero - count - fa->prefixlen;
  577. count += lzero;
  578. if (diff > 0)
  579. count += diff;
  580. if (fa->prefixlen && fa->fillc != ' ') {
  581. while (*fa->prefix != '')
  582. (*fun)(*fa->prefix++, arg);
  583. }
  584. if (!fa->minusflag) {
  585. rfillc = fa->fillc;
  586. while (--diff >= 0)
  587. (*fun)(rfillc, arg);
  588. }
  589. if (fa->prefixlen && fa->fillc == ' ') {
  590. while (*fa->prefix != '')
  591. (*fun)(*fa->prefix++, arg);
  592. }
  593. if (lzero > 0) {
  594. rfillc = '0';
  595. while (--lzero >= 0)
  596. (*fun)(rfillc, arg);
  597. }
  598. while (*s != '')
  599. (*fun)(*s++, arg);
  600. if (fa->minusflag) {
  601. rfillc = ' ';
  602. while (--diff >= 0)
  603. (*fun)(rfillc, arg);
  604. }
  605. return (count);
  606. }
  607. /*
  608.  * Print out one char, allowing prc('')
  609.  * Similar to prbuf()
  610.  */
  611. #ifdef PROTOTYPES
  612. LOCAL int prc(char c, f_args *fa)
  613. #else
  614. LOCAL int prc(c, fa)
  615. char c;
  616. f_args *fa;
  617. #endif
  618. {
  619. register int diff;
  620. register int rfillc;
  621. register long arg = fa->farg;
  622. register void (*fun) __PR((char, long)) = fa->outf;
  623. register int count;
  624. count = 1;
  625. diff = fa->fldwidth - 1;
  626. if (diff > 0)
  627. count += diff;
  628. if (!fa->minusflag) {
  629. rfillc = fa->fillc;
  630. while (--diff >= 0)
  631. (*fun)(rfillc, arg);
  632. }
  633. (*fun)(c, arg);
  634. if (fa->minusflag) {
  635. rfillc = ' ';
  636. while (--diff >= 0)
  637. (*fun)(rfillc, arg);
  638. }
  639. return (count);
  640. }
  641. /*
  642.  * String output routine.
  643.  * If fa->signific is >= 0, it uses only fa->signific chars.
  644.  * If fa->signific is 0, print no characters.
  645.  */
  646. LOCAL int prstring(s, fa)
  647. register const char *s;
  648. f_args *fa;
  649. {
  650. register char *bp;
  651. register int signific;
  652. if (s == NULL)
  653. return (prbuf("(NULL POINTER)", fa));
  654. if (fa->signific < 0)
  655. return (prbuf(s, fa));
  656. bp = fa->buf;
  657. signific = fa->signific;
  658. while (--signific >= 0 && *s != '')
  659. *bp++ = *s++;
  660. *bp = '';
  661. return (prbuf(fa->buf, fa));
  662. }