home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 125.img / PRO-C4.ZIP / BENCH1.ZIP / BENCH / FMTI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-28  |  5.9 KB  |  258 lines

  1. /* ==( bench/fmti.c )== */
  2.  
  3. /* ----------------------------------------------- */
  4. /* Pro-C  Copyright (C) 1988 - 1990 Vestronix Inc. */
  5. /* Modification to this source is not supported    */
  6. /* by Vestronix Inc.                               */
  7. /*            All Rights Reserved                  */
  8. /* ----------------------------------------------- */
  9. /* Written   Nig   1-Jan-87                        */
  10. /* Modified  Geo  11-Dec-89  See comments below    */
  11. /* ----------------------------------------------- */
  12. /* %W%  (%H% %T%) */
  13.  
  14. /*
  15.  *  Modifications
  16.  *
  17.  *  11-Dec-89  Geo - V2 version
  18.  *  25-Oct-89  Geo - 1.32 Merge
  19. */
  20.  
  21. # include <stdio.h>
  22. # include <bench.h>
  23.  
  24. /* Function prototypes */
  25. # ifdef ANSI
  26. static char fmtwd(char *, char *);
  27. static void reverse(char *);
  28. # else
  29. static void reverse();
  30. static char fmtwd();
  31. # endif
  32.  
  33. /* Mode variables */
  34. static char currency;
  35. static int currency_done;
  36. static int lbracket_done;
  37. static int rbracket_done;
  38. static int money = FALSE;
  39. static int negative = FALSE;
  40. static int sign_done;
  41.  
  42.  
  43. char *fmt_int(num, mask)
  44. int num;
  45. char *mask;
  46. {
  47.     return(fmt_lng((long)num, mask));
  48. }  /* fnt_int */
  49.  
  50. char *fmt_mny(num, mask)
  51. long num;
  52. char *mask;
  53. {
  54.     char *p;
  55.  
  56.     /* if first digit not at beginning, determine currency character */
  57.     if((p= strpbrk(mask, "Zz9")) != NULL && p != mask && !strchr("-+(,", *--p))
  58.         currency = *p;
  59.     else
  60.         currency = '\0';
  61.  
  62.     /* format as a long value, taking into account the special money modes */
  63.     money = TRUE;
  64.     p = fmt_lng(num, mask);
  65.     money = FALSE;
  66.  
  67.     return(p);
  68. }  /* fmt_mny */
  69.  
  70.  
  71. char *fmt_lng(num, mask)
  72. long num;
  73. char *mask;
  74. {
  75.     char c, *p, dc, *dp;
  76.     char numl[81], *numr;
  77.     static char maskl[41];
  78.     char *maskr;
  79.     int overflow = FALSE;
  80.     int ndps;
  81.  
  82.     /* break the mask into two parts, one for each side of the decimal */
  83.     strcpy(maskl, mask);
  84.     for(dp = maskl; (dc = *dp) != '\0' && dc != '.'; ++dp)
  85.         ;
  86.     if(dc != '\0')
  87.         *dp++ = '\0';
  88.  
  89.     maskr = dp;
  90.  
  91.     /* find out how many decimal places were requested */
  92.     for(p = maskr; (c = *p) == '9' || c == 'z' || c == 'Z'; ++p)
  93.         ;
  94.     ndps = (int)(p - maskr);
  95.  
  96.     /* convert the number to non-negative, and remember the sign */
  97.     if(negative = (num < 0L))
  98.         num = -num;
  99.  
  100.     /* let sprintf do the work of actually converting it */
  101.     sprintf(numl, "%*ld", ndps, num);
  102.  
  103.     /*
  104.     * As zortech doesn't like a sprintf of the form
  105.     * sprintf(numl, "%0*ld", ndps, num);
  106.     * we must do it as above, then pad with any required spaces.
  107.     */
  108.     p = numl;
  109.     while(*p == ' ')
  110.         *p++ = '0';
  111.  
  112.     /* break the number into two parts, one for each side of the decimal */
  113.     for(p = numl + strlen(numl), p[1] = '\0'; ndps; --p, --ndps)
  114.         p[0] = p[-1];
  115.     *p = '\0';
  116.     numr = ++p;
  117.  
  118.     /* remove any trailing 0s from the right of the decimal for now */
  119.     for(p += strlen(p) - 1; *p == '0'; --p)
  120.         ;
  121.     *++p = '\0';
  122.  
  123.     /* format each half separately, leaving the result in the mask argument */
  124.     /* note that both parts are formatted from the decimal point outward */
  125.     sign_done = currency_done = lbracket_done = rbracket_done = FALSE;
  126.  
  127.     /* the part to the right of the decimal cannot overflow */
  128.     (void)fmtwd(numr, maskr);
  129.  
  130.     reverse(numl);
  131.     reverse(maskl);
  132.     overflow = (fmtwd(numl, maskl) != '\0');
  133.     reverse(maskl);
  134.  
  135.     /* put the decimal point back in */
  136.     if(dc != '\0')
  137.         dp[-1] = '.';
  138.  
  139.     /* put in a sign if negative, there is none yet, and there is room */
  140.     if(negative && !sign_done) {
  141.         for(p = maskl; *p == ' '; ++p)
  142.             ;
  143.         if(p == maskl)
  144.             overflow = TRUE;
  145.         else
  146.             *--p = '-';
  147.     }
  148.  
  149.     /* set the overflow indicator if overflow occurred */
  150.     if(overflow)
  151.         *maskl = '?';
  152.  
  153.     return(maskl);
  154. }  /* fmt_lng */
  155.  
  156. static char fmtwd(num, mask)
  157. char *num, *mask;
  158. {
  159.     char mc, nc, *root;
  160.  
  161.     root = mask;
  162.     while((mc = *mask) != '\0') {
  163.         if(money && mc == currency) {
  164.             if(!currency_done) {
  165.                 char *p;
  166.  
  167.                 currency_done = TRUE;
  168.                 /* search back for a non-blank */
  169.                 for(p = mask; --p >= root && *p == ' '; )
  170.                     ;
  171.                 *mask = ' ';
  172.                 *++p = mc;
  173.             }
  174.         }
  175.         else switch (mc) {
  176.         case '9':
  177.         case 'Z':
  178.         case 'z':
  179.             /* copy in digit if any left, otherwise copy '0' or ' ' */
  180.             if((nc = *num) != '\0') {
  181.                 ++num;
  182.                 *mask = nc;
  183.             }
  184.             else
  185.                 *mask = (mc == '9') ? '0' : ' ';
  186.             break;
  187.         case '(':
  188.             /* treat as a bracket only if in money mode and first one */
  189.             if(money && !lbracket_done) {
  190.                 char *p;
  191.  
  192.                 sign_done = lbracket_done = TRUE;
  193.                 /* search back for a non-blank */
  194.                 for(p = mask; --p >= root && *p == ' '; )
  195.                     ;
  196.                 *mask = ' ';
  197.                 *++p = negative ? mc : ' ';
  198.             }
  199.             break;
  200.         case ')':
  201.             /* treat as a bracket only if in money mode and first one */
  202.             if(money && !rbracket_done) {
  203.                 char *p;
  204.  
  205.                 sign_done = rbracket_done = TRUE;
  206.                 /* search back for a non-blank */
  207.                 for(p = mask; --p >= root && *p == ' '; )
  208.                     ;
  209.                 *mask = ' ';
  210.                 *++p = negative ? mc : ' ';
  211.             }
  212.             break;
  213.         case '+':
  214.         case '-':
  215.             /* treat as a sign only if this is the first one encountered */
  216.             if (!sign_done
  217.             /* next line allows non-sign + or - inside a num eg. ZZZ-ZZZZ */
  218.             && ( *(mask-1) == '\0' || *(mask+1) == '\0' )
  219.             ) {
  220.                 char *p;
  221.  
  222.                 sign_done = TRUE;
  223.                 /* search back for a non-blank */
  224.                 for(p = mask; --p >= root && *p == ' '; )
  225.                     ;
  226.                 *mask = ' ';
  227.                 *++p = negative ? '-' : ((mc == '+') ? '+' : ' ');
  228.             }
  229.             break;
  230.         case ',':
  231.             /* don't want to delete comma if there is going to be a zero */
  232.             if(*num == '\0' && (mask[1] == 'z' || mask[1] == 'Z'))
  233.                 *mask = ' ';
  234.             break;
  235.         default:
  236.             /* simply leave the character as is */
  237.             break;
  238.         }
  239.         ++mask;
  240.     }
  241.  
  242.     /* return next character in number; this is used to detect overflow */
  243.     return(*num);
  244. }  /* fmtwd */
  245.  
  246. /* not a very general function, but it's only used in this file */
  247. static void reverse(str)
  248. char *str;
  249. {
  250.     char tmp, *estr;
  251.     for (estr = str + strlen(str) - 1; estr > str; estr--, str++) {
  252.         tmp = *estr;
  253.         *estr = *str;
  254.         *str = tmp;
  255.     }
  256. }  /* reverse */
  257.  
  258.