home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / tc.printf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  8.6 KB  |  394 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/tc.printf.c,v 3.10 1992/10/14 20:19:19 christos Exp $ */
  2. /*
  3.  * tc.printf.c: A public-domain, minimal printf/sprintf routine that prints
  4.  *           through the putchar() routine.  Feel free to use for
  5.  *           anything...  -- 7/17/87 Paul Placeway
  6.  */
  7. /*-
  8.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions and the following disclaimer.
  16.  * 2. Redistributions in binary form must reproduce the above copyright
  17.  *    notice, this list of conditions and the following disclaimer in the
  18.  *    documentation and/or other materials provided with the distribution.
  19.  * 3. All advertising materials mentioning features or use of this software
  20.  *    must display the following acknowledgement:
  21.  *    This product includes software developed by the University of
  22.  *    California, Berkeley and its contributors.
  23.  * 4. Neither the name of the University nor the names of its contributors
  24.  *    may be used to endorse or promote products derived from this software
  25.  *    without specific prior written permission.
  26.  *
  27.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  28.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  31.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  33.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  37.  * SUCH DAMAGE.
  38.  */
  39. #include "sh.h"
  40.  
  41. RCSID("$Id: tc.printf.c,v 3.10 1992/10/14 20:19:19 christos Exp $")
  42.  
  43. #ifdef lint
  44. #undef va_arg
  45. #define va_arg(a, b) (a ? (b) 0 : (b) 0)
  46. #endif
  47.  
  48. #define INF    32766        /* should be bigger than any field to print */
  49.  
  50. static char buf[128];
  51.  
  52. static    void    xaddchar    __P((int));
  53. static    void    doprnt        __P((void (*) __P((int)), const char *, va_list));
  54.  
  55. static void
  56. doprnt(addchar, sfmt, ap)
  57.     void    (*addchar)();
  58.     const char   *sfmt;
  59.     va_list ap;
  60. {
  61.     register char *bp;
  62.     register const char *f;
  63.     register Char *Bp;
  64.     register long l;
  65.     register unsigned long u;
  66.     register int i;
  67.     register int fmt;
  68.     register unsigned char pad = ' ';
  69.     int     flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
  70.     int     sign = 0;
  71.     int     attributes = 0;
  72.  
  73.  
  74.     f = sfmt;
  75.     for (; *f; f++) {
  76.     if (*f != '%') {    /* then just out the char */
  77.         (*addchar) ((int) (((unsigned char)*f) | attributes));
  78.     }
  79.     else {
  80.         f++;        /* skip the % */
  81.  
  82.         if (*f == '-') {    /* minus: flush left */
  83.         flush_left = 1;
  84.         f++;
  85.         }
  86.  
  87.         if (*f == '0' || *f == '.') {
  88.         /* padding with 0 rather than blank */
  89.         pad = '0';
  90.         f++;
  91.         }
  92.         if (*f == '*') {    /* field width */
  93.         f_width = va_arg(ap, int);
  94.         f++;
  95.         }
  96.         else if (Isdigit((unsigned char) *f)) {
  97.         f_width = atoi(f);
  98.         while (Isdigit((unsigned char) *f))
  99.             f++;    /* skip the digits */
  100.         }
  101.  
  102.         if (*f == '.') {    /* precision */
  103.         f++;
  104.         if (*f == '*') {
  105.             prec = va_arg(ap, int);
  106.             f++;
  107.         }
  108.         else if (Isdigit((unsigned char) *f)) {
  109.             prec = atoi((char *) f);
  110.             while (Isdigit((unsigned char) *f))
  111.             f++;    /* skip the digits */
  112.         }
  113.         }
  114.  
  115.         if (*f == '#') {    /* alternate form */
  116.         hash = 1;
  117.         f++;
  118.         }
  119.  
  120.         if (*f == 'l') {    /* long format */
  121.         do_long = 1;
  122.         f++;
  123.         }
  124.  
  125.         fmt = (unsigned char) *f;
  126.         if (fmt != 'S' && Isupper(fmt)) {
  127.         do_long = 1;
  128.         fmt = Tolower(fmt);
  129.         }
  130.         bp = buf;
  131.         switch (fmt) {    /* do the format */
  132.         case 'd':
  133.         if (do_long)
  134.             l = va_arg(ap, long);
  135.         else
  136.             l = (long) (va_arg(ap, int));
  137.         if (l < 0) {
  138.             sign = 1;
  139.             l = -l;
  140.         }
  141.         do {
  142.             *bp++ = l % 10 + '0';
  143.         } while ((l /= 10) > 0);
  144.         if (sign)
  145.             *bp++ = '-';
  146.         f_width = f_width - (bp - buf);
  147.         if (!flush_left)
  148.             while (f_width-- > 0) 
  149.             (*addchar) ((int) (pad | attributes));
  150.         for (bp--; bp >= buf; bp--) 
  151.             (*addchar) ((int) (((unsigned char) *bp) | attributes));
  152.         if (flush_left)
  153.             while (f_width-- > 0)
  154.             (*addchar) ((int) (' ' | attributes));
  155.         break;
  156.  
  157.         case 'o':
  158.         case 'x':
  159.         case 'u':
  160.         if (do_long)
  161.             u = va_arg(ap, unsigned long);
  162.         else
  163.             u = (unsigned long) (va_arg(ap, unsigned int));
  164.         if (fmt == 'u') {    /* unsigned decimal */
  165.             do {
  166.             *bp++ = u % 10 + '0';
  167.             } while ((u /= 10) > 0);
  168.         }
  169.         else if (fmt == 'o') {    /* octal */
  170.             do {
  171.             *bp++ = u % 8 + '0';
  172.             } while ((u /= 8) > 0);
  173.             if (hash)
  174.             *bp++ = '0';
  175.         }
  176.         else if (fmt == 'x') {    /* hex */
  177.             do {
  178.             i = u % 16;
  179.             if (i < 10)
  180.                 *bp++ = i + '0';
  181.             else
  182.                 *bp++ = i - 10 + 'a';
  183.             } while ((u /= 16) > 0);
  184.             if (hash) {
  185.             *bp++ = 'x';
  186.             *bp++ = '0';
  187.             }
  188.         }
  189.         i = f_width - (bp - buf);
  190.         if (!flush_left)
  191.             while (i-- > 0)
  192.             (*addchar) ((int) (pad | attributes));
  193.         for (bp--; bp >= buf; bp--)
  194.             (*addchar) ((int) (((unsigned char) *bp) | attributes));
  195.         if (flush_left)
  196.             while (i-- > 0)
  197.             (*addchar) ((int) (' ' | attributes));
  198.         break;
  199.  
  200.  
  201.         case 'c':
  202.         i = va_arg(ap, int);
  203.         (*addchar) ((int) (i | attributes));
  204.         break;
  205.  
  206.         case 'S':
  207. #ifdef SHORT_STRINGS
  208.         Bp = va_arg(ap, Char *);
  209.         if (!Bp) {
  210.             bp = NULL;
  211.             goto lcase_s;
  212.             }
  213.         f_width = f_width - Strlen(Bp);
  214.         if (!flush_left)
  215.             while (f_width-- > 0)
  216.             (*addchar) ((int) (pad | attributes));
  217.         for (i = 0; *Bp && i < prec; i++) {
  218.             (*addchar) ((int) ((unsigned char)*Bp | attributes));
  219.             Bp++;
  220.         }
  221.         if (flush_left)
  222.             while (f_width-- > 0)
  223.             (*addchar) ((int) (' ' | attributes));
  224.         break;
  225. #else
  226.         bp = va_arg(ap, Char *);
  227.         if (bp)
  228.             (void) strip((Char *) bp);
  229.         goto lcase_s;
  230. #endif /* SHORT_STRINGS */
  231.  
  232.         case 's':
  233.         bp = va_arg(ap, char *);
  234. lcase_s:
  235.         if (!bp)
  236.             bp = "(nil)";
  237.         f_width = f_width - strlen((char *) bp);
  238.         if (!flush_left)
  239.             while (f_width-- > 0)
  240.             (*addchar) ((int) (pad | attributes));
  241.         for (i = 0; *bp && i < prec; i++) {
  242.             (*addchar) ((int) (((unsigned char) *bp) | attributes));
  243.             bp++;
  244.         }
  245.         if (flush_left)
  246.             while (f_width-- > 0)
  247.             (*addchar) ((int) (' ' | attributes));
  248.  
  249.         break;
  250.  
  251.         case 'a':
  252.         attributes = va_arg(ap, int);
  253.         break;
  254.  
  255.         case '%':
  256.         (*addchar) ((int) ('%' | attributes));
  257.         break;
  258.  
  259.         default:
  260.         break;
  261.         }
  262.         flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
  263.         sign = 0;
  264.         pad = ' ';
  265.     }
  266.     }
  267. }
  268.  
  269.  
  270. static char *xstring;
  271. static void
  272. xaddchar(c)
  273.     int     c;
  274. {
  275.     *xstring++ = (char) c;
  276. }
  277.  
  278.  
  279. void
  280. /*VARARGS*/
  281. #if __STDC__
  282. xsprintf(char *str, char *fmt, ...)
  283. #else
  284. xsprintf(va_alist)
  285.     va_dcl
  286. #endif
  287. {
  288.     va_list va;
  289. #if __STDC__
  290.     va_start(va, fmt);
  291. #else
  292.     char *str, *fmt;
  293.  
  294.     va_start(va);
  295.     str = va_arg(va, char *);
  296.     fmt = va_arg(va, char *);
  297. #endif
  298.  
  299.     xstring = (char *) str;
  300.     doprnt(xaddchar, fmt, va);
  301.     va_end(va);
  302.     *xstring++ = '\0';
  303. }
  304.  
  305.  
  306. void
  307. /*VARARGS*/
  308. #if __STDC__
  309. xprintf(char *fmt, ...)
  310. #else
  311. xprintf(va_alist)
  312.     va_dcl
  313. #endif
  314. {
  315.     va_list va;
  316. #if __STDC__
  317.     va_start(va, fmt);
  318. #else
  319.     char   *fmt;
  320.  
  321.     va_start(va);
  322.     fmt = va_arg(va, char *);
  323. #endif
  324.     doprnt(xputchar, fmt, va);
  325.     va_end(va);
  326. }
  327.  
  328.  
  329. void
  330. xvprintf(fmt, va)
  331.     char   *fmt;
  332.     va_list va;
  333. {
  334.     doprnt(xputchar, fmt, va);
  335. }
  336.  
  337. void
  338. xvsprintf(str, fmt, va)
  339.     char   *str;
  340.     char   *fmt;
  341.     va_list va;
  342. {
  343.     xstring = (char *) str;
  344.     doprnt(xaddchar, fmt, va);
  345.     *xstring++ = '\0';
  346. }
  347.  
  348.  
  349.  
  350. #ifdef PURIFY
  351. /* Purify uses (some of..) the following functions to output memory-use
  352.  * debugging info.  Given all the messing with file descriptors that
  353.  * tcsh does, the easiest way I could think of to get it (Purify) to
  354.  * print anything was by replacing some standard functions with
  355.  * ones that do tcsh output directly - see dumb hook in doreaddirs()
  356.  * (sh.dir.c) -sg
  357.  */
  358. #define FILE int
  359. int 
  360. #if __STDC__
  361. fprintf(FILE *fp, const char* fmt, ...)
  362. #else
  363. fprintf(va_alist)
  364.     va_dcl
  365. #endif
  366. {
  367.     va_list va;
  368. #if __STDC__
  369.     va_start(va, fmt);
  370. #else
  371.     FILE *fp;
  372.     const char   *fmt;
  373.  
  374.     va_start(va);
  375.     fp = va_arg(va, FILE *);
  376.     fmt = va_arg(va, const char *);
  377. #endif
  378.     doprnt(xputchar, fmt, va);
  379.     va_end(va);
  380.     return 1;
  381. }
  382.  
  383. int 
  384. vfprintf(fp, fmt, va)
  385.     FILE *fp;
  386.     const char   *fmt;
  387.     va_list va;
  388. {
  389.     doprnt(xputchar, fmt, va);
  390.     return 1;
  391. }
  392.  
  393. #endif    /* PURIFY */
  394.