home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / other / am / am.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-30  |  19.2 KB  |  754 lines

  1. /************************************************************************/
  2. /*                                    */
  3. /* am - Amortization Schedule Generator                    */
  4. /*                                    */
  5. /* (c) Copyright 1987, 1992, 1993    Brett K. Carver            */
  6. /*                                    */
  7. /************************************************************************/
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <math.h>
  11.  
  12. #include "patchlevel.h"
  13.  
  14. /* these two constants may be changed at will */
  15. #define ARRAY_SIZE 128        /* special arrays size: -I, -E, -U    */
  16. #define SEP '-'            /* seperator for dates: 1/1/93 or 1-1-93*/
  17.  
  18. /* these constants should not be changed */
  19. #define FIELD_LENGTH 15        /* how wide are numbers: 123,456,789.12    */
  20. #define MAX_VAL 999999999.99    /* maximum dollar amount allowed    */
  21. #define S_LEN 100        /* length of input buffer string    */
  22. #define PLURAL(x) (x)!=1?"s":""    /* adds an 's' for plural items        */
  23.  
  24. #ifndef TRUE
  25. # define TRUE 1
  26. # define FALSE 0
  27. #endif
  28.  
  29. int    number;            /* number of payments            */
  30. double    amount;            /* amount of loan            */
  31. double    rate;            /* interest rate            */
  32. double    payment;        /* amount of monthly payment        */
  33. int    month, day, year;    /* starting date            */
  34. int    e_idx = 0;        /* index into extra payment arrays    */
  35. int    e_mon[ARRAY_SIZE];    /* months of extra payments        */
  36. double    e_pay[ARRAY_SIZE];    /* amounts of extra payments        */
  37. int    u_idx = 0;        /* index into unusual payment arrays    */
  38. int    u_mon[ARRAY_SIZE];    /* months of unusual payments        */
  39. double    u_pay[ARRAY_SIZE];    /* amounts of unusual payments        */
  40. int    i_idx = 0;        /* index into interest rate arrays    */
  41. int    i_mon[ARRAY_SIZE];    /* months of interest rates        */
  42. double    i_pay[ARRAY_SIZE];    /* amounts of interest rates        */
  43. int    list;            /* months to list for            */
  44. int    delta_day;        /* first month 30 +/- delta days    */
  45. int    balloon = FALSE;    /* last payment is a balloon payment    */
  46. int    format = FALSE;        /* include nroff formatting commands    */
  47. char    istr[S_LEN];        /* input buffer string            */
  48.  
  49. #define    def_number    360    /* default number of payments        */
  50. #define    def_amount    10000.0    /* default amount of loan        */
  51. #define    def_rate    10.0    /* default interest rate        */
  52. #define    def_payment    100.0    /* default amount of monthly payment    */
  53. #define def_start    "1-1-90"/* default starting date        */
  54. #define    def_list    0    /* default months to list for        */
  55.  
  56. char * usage_text[] = {
  57.     "\t-n\tnumber of payments (-n-30 is 30 years, 360 months):",
  58.     "\t\t\t=0 - till paid in full",
  59.     "\t\t\t>0 - number of months",
  60.     "\t\t\t<0 - number of years",
  61.     "\t-a\tamount of loan (<= $999,999,999.99)",
  62.     "\t-i\tinterest rate (-i10 is 10%)",
  63.     "\t-p\tmonthly payment amount:",
  64.     "\t\t\t=0 - computed based on number of payments",
  65. #if (SEP == '-')
  66.     "\t-s\tstart first payment on mm-dd-yy (-s12-15-93 is Dec 15 1993)",
  67. #else
  68.     "\t-s\tstart first payment on mm/dd/yy (-s12/15/93 is Dec 15 1993)",
  69. #endif
  70.     "\t-l\tlist loan for:",
  71.     "\t\t\t=0 - list all payments",
  72.     "\t\t\t>0 - number of months",
  73.     "\t\t\t<0 - number of years",
  74.     "\t-b\tmake last payment a balloon payment if ballance due",
  75.     "\t-I\tmonth:rate for new interest rate[s] (up to 128 allowed):",
  76.     "\t\t\t>0 - new interest rate (-e8:12 rate at 12% on month 8)",
  77.     "\t-E\tmonth:amount for extra payment[s] (up to 128 allowed):",
  78.     "\t\t\t>0 - extra principal payment amount (-e7:50 extra $50)",
  79.     "\t\t\t<0 - add to unpaid principal (-e5:-100 add $100)",
  80.     "\t-U\tmonth:unusual payment[s] (up to 128 allowed):",
  81.     "\t\t\t=0 - missed payment (-u9:0 missed payment on month 9)",
  82.     "\t\t\t>0 - non-standard payment amount (-u7:75 only paid $75)",
  83.     "\t-D\tchange first month by +/- days",
  84.     "\t\t\t>0 - month had more days than normal",
  85.     "\t\t\t<0 - month had less days than normal",
  86.     "\t-f\tOutput with nroff formatting commands",
  87.     0 };                    /* last entry MUST be null */
  88.  
  89. char *titles = "NUMBER   DATE           PAYMENT        INTEREST       PRINCIPAL         BALANCE";
  90.  
  91. /************************************************************************/
  92. /*                                    */
  93. /************************************************************************/
  94. char * add_commas(value)
  95. double value;
  96. {
  97. static char string[32];
  98. static char * sptr = &string[0];
  99. register int i, j, k;
  100. register int length;
  101. int negative;
  102.  
  103. negative = FALSE;
  104. if (value < 0) {
  105.     value = -value;
  106.     negative = TRUE;
  107.     }
  108.  
  109. if (value > MAX_VAL) {
  110.     fprintf(stderr, "Error:\ta value has exceeded $999,999,999.99,\n");
  111.     fprintf(stderr, "\tplease use another program for calculating the national debt.\n");
  112.     exit(1);
  113.     }
  114.  
  115. sprintf(sptr, "%.2f                ", value);
  116. length = strlen(sptr);    /* sprintf() doesn't return length on all unix's */
  117. length -= 16;        /* 1234567890123456 */
  118. length --;        /* make 0 relative  */
  119. string[FIELD_LENGTH] = '\000';
  120. j = FIELD_LENGTH - 1;
  121. k = 6;
  122.  
  123. for (i=length; i>=0; i--) {
  124.     if ((k--) == 0) {
  125.         string[j--] = ',';
  126.         k = 2;
  127.         }
  128.     string[j--] = string[i];
  129.     string[i] = ' ';
  130.     }
  131.  
  132. if (negative)
  133.     string[j--] = '-';
  134.  
  135. return(sptr);
  136. }
  137.  
  138. /************************************************************************/
  139. /*                                    */
  140. /************************************************************************/
  141. int get_int(text, def)
  142. char *text;
  143. int def;
  144. {
  145. int value;
  146.  
  147. fprintf(stderr, "%s [%d]: ", text, def);
  148. fgets(istr, S_LEN, stdin);
  149.  
  150. if (strlen(istr) <= 1)
  151.     return(def);
  152.  
  153. value = 0;    /* in case nothing scans */
  154. sscanf(istr, "%d", &value);
  155.  
  156. return(value);
  157. }
  158.  
  159. /************************************************************************/
  160. /*                                    */
  161. /************************************************************************/
  162. double get_double(text, def)
  163. char *text;
  164. double def;
  165. {
  166. double value;
  167.  
  168. fprintf(stderr, "%s [%.0f]: ", text, def);
  169. fgets(istr, S_LEN, stdin);
  170.  
  171. if (strlen(istr) <= 1)
  172.     return(def);
  173.  
  174. value = 0.0;    /* in case nothing scans */
  175. sscanf(istr, "%lf", &value);
  176.  
  177. return(value);
  178. }
  179.  
  180. /************************************************************************/
  181. /*                                    */
  182. /************************************************************************/
  183. dup_warning(param)
  184. int param;
  185. {
  186. fprintf(stderr, "Warning: duplicate '-%c' parameter\n", param);
  187. }
  188.  
  189. /************************************************************************/
  190. /*                                    */
  191. /************************************************************************/
  192. init(argc, argv)
  193. int argc;
  194. char *argv[];
  195. {
  196. extern char *optarg;
  197. extern int optind;
  198. int c;
  199. int error_flag    = FALSE;
  200. char z[2];            /* a sscanf temp */
  201. int got_number    = FALSE;
  202. int got_amount    = FALSE;
  203. int got_rate    = FALSE;
  204. int got_payment    = FALSE;
  205. int got_start    = FALSE;
  206. int got_list    = FALSE;
  207. int i;
  208.  
  209. while ((c = getopt(argc, argv, "n:a:i:p:s:l:bI:E:U:D:f?")) != EOF)
  210.     switch (c) {
  211.  
  212.         case 'n':
  213.             if (got_number)
  214.                 dup_warning(c);
  215.             sscanf(optarg, "%d", &number);
  216.             got_number = TRUE;
  217.             break;
  218.  
  219.         case 'a':
  220.             if (got_amount)
  221.                 dup_warning(c);
  222.             sscanf(optarg, "%lf", &amount);
  223.             if (amount <= 0.0) {
  224.                 fprintf(stderr, "Error: amount <= 0.0\n");
  225.                 error_flag = TRUE;
  226.                 }
  227.             if (amount > MAX_VAL) {
  228.                 fprintf(stderr,
  229.                     "Error: amount > 999,999,999.99\n");
  230.                 error_flag = TRUE;
  231.                 }
  232.             got_amount = TRUE;
  233.             break;
  234.  
  235.         case 'i':
  236.             if (got_rate)
  237.                 dup_warning(c);
  238.             sscanf(optarg, "%lf", &rate);
  239.             if (rate <= 0.0) {
  240.                 fprintf(stderr, "Error: rate <= 0.0\n");
  241.                 error_flag = TRUE;
  242.                 }
  243.             got_rate = TRUE;
  244.             break;
  245.  
  246.         case 'p':
  247.             if (got_payment)
  248.                 dup_warning(c);
  249.             sscanf(optarg, "%lf", &payment);
  250.             if (payment < 0.0) {
  251.                 fprintf(stderr, "Error: payment < 0.0\n");
  252.                 error_flag = TRUE;
  253.                 }
  254.             got_payment = TRUE;
  255.             break;
  256.  
  257.         case 's':
  258.             if (got_start)
  259.                 dup_warning(c);
  260.             sscanf(optarg, "%d%[- /]%d%[- /]%d",
  261.                         &month, z, &day, z, &year);
  262.             got_start = TRUE;
  263.             break;
  264.  
  265.         case 'l':
  266.             if (got_list)
  267.                 dup_warning(c);
  268.             sscanf(optarg, "%d", &list);
  269.             got_list = TRUE;
  270.             break;
  271.  
  272.         case 'b':
  273.             if (balloon)
  274.                 dup_warning(c);
  275.             balloon = TRUE;
  276.             break;
  277.  
  278.         case 'E':
  279.             if (e_idx >= ARRAY_SIZE) {
  280.                 fprintf(stderr, "Error: more than %d extra payments\n",
  281.                     ARRAY_SIZE);
  282.                 error_flag = TRUE;
  283.                 break;
  284.                 }
  285.             sscanf(optarg, "%d:%lf", &e_mon[e_idx], &e_pay[e_idx]);
  286.             if (e_mon[e_idx] <= 0) {
  287.                 fprintf(stderr,
  288.                     "Error: invalid extra payment month: %d\n",
  289.                     e_mon[e_idx]);
  290.                 error_flag = TRUE;
  291.                 }
  292.             if (e_pay[e_idx] == 0) {
  293.                 fprintf(stderr,
  294.                     "Warning: $0.00 extra payment for month: %d, ignored\n",
  295.                     e_mon[e_idx]);
  296.                 }
  297.             for (i=0; i<e_idx; i++)
  298.                 if (e_mon[i] == e_mon[e_idx]) {
  299.                     fprintf(stderr,
  300.                         "Error: duplicate extra payment month: %d\n",
  301.                         e_mon[e_idx]);
  302.                     error_flag = TRUE;
  303.                     }
  304.             e_idx++;
  305.             break;
  306.  
  307.         case 'U':
  308.             if (u_idx >= ARRAY_SIZE) {
  309.                 fprintf(stderr, "Error: more than %d unusual payments\n",
  310.                     ARRAY_SIZE);
  311.                 error_flag = TRUE;
  312.                 break;
  313.                 }
  314.             sscanf(optarg, "%d:%lf", &u_mon[u_idx], &u_pay[u_idx]);
  315.             if (u_mon[u_idx] <= 0) {
  316.                 fprintf(stderr,
  317.                     "Error: invalid unusual payment month: %d\n",
  318.                     u_mon[u_idx]);
  319.                 error_flag = TRUE;
  320.                 }
  321.             if (u_pay[u_idx] < 0) {
  322.                 fprintf(stderr,
  323.                     "Error: invalid unusual payment: %d:%.2f\n",
  324.                     u_mon[u_idx], u_pay[u_idx]);
  325.                 error_flag = TRUE;
  326.                 }
  327.             for (i=0; i<u_idx; i++)
  328.                 if (u_mon[i] == u_mon[u_idx]) {
  329.                     fprintf(stderr,
  330.                         "Error: duplicate unusual payment month: %d\n",
  331.                         u_mon[u_idx]);
  332.                     error_flag = TRUE;
  333.                     }
  334.             u_idx++;
  335.             break;
  336.  
  337.         case 'I':
  338.             if (i_idx >= ARRAY_SIZE) {
  339.                 fprintf(stderr, "Error: more than %d interest rate changes\n",
  340.                     ARRAY_SIZE);
  341.                 error_flag = TRUE;
  342.                 break;
  343.                 }
  344.             sscanf(optarg, "%d:%lf", &i_mon[i_idx], &i_pay[i_idx]);
  345.             i_pay[i_idx] /= 100.0;
  346.             i_pay[i_idx] /= 12.0;
  347.             if (i_mon[i_idx] <= 0) {
  348.                 fprintf(stderr,
  349.                     "Error: invalid interest rate change month: %d\n",
  350.                     i_mon[i_idx]);
  351.                 error_flag = TRUE;
  352.                 }
  353.             if (i_pay[i_idx] <= 0) {
  354.                 fprintf(stderr,
  355.                     "Error: invalid interest rate change: %d:%.2f\n",
  356.                     i_mon[i_idx], i_pay[i_idx]);
  357.                 error_flag = TRUE;
  358.                 }
  359.             for (i=0; i<i_idx; i++)
  360.                 if (i_mon[i] == i_mon[i_idx]) {
  361.                     fprintf(stderr,
  362.                         "Error: duplicate interest rate change month: %d\n",
  363.                         i_mon[i_idx]);
  364.                     error_flag = TRUE;
  365.                     }
  366.             i_idx++;
  367.             break;
  368.  
  369.         case 'D':
  370.             sscanf(optarg, "%d", &delta_day);
  371.             if ((delta_day < -30) || (delta_day > 30)) {
  372.                 fprintf(stderr, "Error: first month can only be +/- 30 days\n");
  373.                 error_flag = TRUE;
  374.                 }
  375.             break;
  376.  
  377.         case 'f':
  378.             if (format)
  379.                 dup_warning(c);
  380.             format = TRUE;
  381.             break;
  382.  
  383.         case '?':
  384.             error_flag = TRUE;
  385.             break;
  386.  
  387.         default:
  388.             error_flag = TRUE;
  389.             break;
  390.  
  391.         }
  392.  
  393. if (error_flag || optind < argc) {
  394.     char **text;
  395.  
  396.     fprintf(stderr, "\n%s: %s\n", argv[0], &ident[5]);
  397.     fprintf(stderr, "\t(c) 1987, 1992, 1993 - Brett K. Carver\n\n");
  398.     fprintf(stderr, "usage: %s [arguments]\n", argv[0]);
  399.     text = usage_text;
  400.     while (*text)
  401.         fprintf(stderr, "%s\n", *text++);
  402.     exit(1);
  403.     }
  404.  
  405. if (!got_number)
  406.     number = get_int("Enter number of payments (- = years, + = months, 0 = till paid)", def_number);
  407.  
  408. if (number < 0)
  409.     number *= -12;
  410.  
  411. if (!got_amount)
  412.     amount = get_double("Enter amount of loan", def_amount);
  413.  
  414. if (amount <= 0.0) {
  415.     fprintf(stderr, "Error: amount <= 0.0\n");
  416.     exit(1);
  417.     }
  418.  
  419. if (amount > MAX_VAL) {
  420.     fprintf(stderr, "Error: amount > 999,999,999.99\n");
  421.     exit(1);
  422.     }
  423.  
  424. if (!got_rate)
  425.     rate = get_double("Enter interest rate(%)", def_rate);
  426.  
  427. if (rate <= 0.0) {
  428.     fprintf(stderr, "Error: rate <= 0.0\n");
  429.     exit(1);
  430.     }
  431.  
  432. rate /= 100.0;
  433. rate /= 12.0;
  434.  
  435. if (!got_payment) {
  436.     if (number == 0)
  437.         payment = get_double("Enter amount of payment (required)",
  438.                     def_payment);
  439.     else
  440.         payment = get_double("Enter amount of payment (0 for computed)",
  441.                     0.0);
  442.     }
  443.  
  444. if (payment < 0.0) {
  445.     fprintf(stderr, "Error: payment < 0.0\n");
  446.     exit(1);
  447.     }
  448.  
  449. while ((payment < 0.01) && (number == 0)) {
  450.     fprintf(stderr, "Error: payment required (unable to compute):");
  451.     scanf("%lf", &payment);
  452.     }
  453.  
  454. if (payment < 0.01) {
  455.     /****************************************/
  456.     /*             A  *  R        */
  457.     /*        ----------------    */
  458.     /*    P  =             1        */
  459.     /*         1 - ----------        */
  460.     /*                     N        */
  461.     /*              (1 + R)        */
  462.     /****************************************/
  463.     payment = amount * rate /
  464.         (1.0 - (1.0 /
  465.             pow(1.0 + rate, (double)number)));
  466.     }
  467.  
  468. payment = ceil(payment * 100.0) / 100.0;
  469.  
  470. if (payment < rate * amount) {
  471.     fprintf(stderr, "Warning: payment < interest amount.\n");
  472.     }
  473.  
  474. if (!got_start) {
  475.     fprintf(stderr, "Starting month%cday%cyear [1%c1%c90]: ",
  476.         SEP, SEP, SEP, SEP);
  477.     fgets(istr, S_LEN, stdin);
  478.     if (strlen(istr) <= 1)
  479.         strcpy(istr, def_start);
  480.     sscanf(istr, "%d%[- /]%d%[- /]%d", &month, z, &day, z, &year);
  481.     }
  482.  
  483. year %= 100;
  484.  
  485. if (!got_list)
  486.     list = get_int("Number of payments to list (0 for all)", def_list);
  487.  
  488. if (list < 0)
  489.     list *= -12;
  490.  
  491. }
  492.  
  493. /************************************************************************/
  494. /*                                    */
  495. /************************************************************************/
  496. print_header()
  497. {
  498.  
  499. if (format) {
  500.     printf(".nf\n");            /* no fill        */
  501.     printf(".na\n");            /* no adjust        */
  502.     printf(".ll 80\n");            /* line length        */
  503.     printf(".lt 80\n");            /* title length        */
  504.     printf(".de hd\n");            /* define header    */
  505.     printf(".sp 4\n");
  506.     printf(".tl '\\fI%s\\fR'\n", titles);
  507.     printf("..\n");
  508.     printf(".de fo\n");            /* define footer    */
  509.     printf(".sp 2\n");
  510.     printf(".tl ''- %% -''\n");
  511.     printf(".bp\n");
  512.     printf("..\n");
  513.     printf(".wh 0 hd\n");            /* header trap        */
  514.     printf(".wh -4 fo\n");            /* footer trap        */
  515.     printf(".sp 3\n");
  516.     }
  517.  
  518. if (number == 0)
  519.     printf("Number of payments:   till paid\n");
  520. else
  521.     printf("Number of payments:       %5d\n", number);
  522.  
  523. printf("Amount of loan: %s\n", add_commas(amount));
  524. printf("Interest rate:       %8.2f %%\n", rate*100.0*12.0);
  525. printf("Payment amount: %s\n", add_commas(payment));
  526. printf("Starting date:         %.2d%c%.2d%c%.2d\n", month, SEP, day, SEP, year);
  527.  
  528. if (e_idx > 0)
  529.     printf("With %d extra payment%s defined.\n", e_idx, PLURAL(e_idx));
  530.  
  531. if (u_idx > 0)
  532.     printf("With %d unusual payment%s defined.\n", u_idx, PLURAL(u_idx));
  533.  
  534. if (i_idx > 0)
  535.     printf("With %d interest rage change%s defined.\n", i_idx,
  536.         PLURAL(i_idx));
  537.  
  538. if (delta_day != 0)
  539.     printf("With a first month of %d day%s.\n", 30+delta_day,
  540.         PLURAL(30+delta_day));
  541.  
  542. if (list != 0) {
  543.     if (list < number || number == 0)
  544.         number = list;
  545.     printf("Listing for %d payment%s, %.1f year%s.\n", number,
  546.         PLURAL(number), number/12.0, PLURAL(number/12.0));
  547.     }
  548. else    {
  549.     if (number != 0)
  550.         printf("Listing for %d payment%s, %.1f year%s.\n", number,
  551.             PLURAL(number), number/12.0, PLURAL(number/12.0));
  552.     else    {
  553.         printf("Listing till paid.\n");
  554.         number = 99999;
  555.         }
  556.     }
  557.  
  558. if (balloon)
  559.     printf("With a balloon final payment.\n");
  560.  
  561. if (format) {
  562.     printf(".sp 3\n");
  563.     printf("\\fI%s\\fR\n", titles);
  564.     }
  565. else {
  566.     printf("\n\n\n");
  567.     printf("%s\n", titles);
  568.     }
  569. }
  570.  
  571. /************************************************************************/
  572. /*                                    */
  573. /************************************************************************/
  574. print_totals(leader, t_pay, t_int, t_pcp)
  575. char *leader;
  576. double t_pay, t_int, t_pcp;
  577. {
  578.  
  579. printf("%s", leader);
  580.  
  581. if (format)
  582.     printf("\\fB");
  583.  
  584. printf("%s ", add_commas(t_pay));
  585. printf("%s ", add_commas(t_int));
  586. printf("%s",  add_commas(t_pcp));
  587.  
  588. if (format)
  589.     printf("\\fR");
  590.  
  591. printf("\n");
  592. }
  593.  
  594. /************************************************************************/
  595. /*                                    */
  596. /************************************************************************/
  597. main(argc, argv)
  598. int argc;
  599. char *argv[];
  600. {
  601. double interest;
  602. double principal;
  603. double pay;
  604. double t_interest    = 0.0;
  605. double t_principal    = 0.0;
  606. double t_payment    = 0.0;
  607. double gt_interest    = 0.0;
  608. double gt_principal    = 0.0;
  609. double gt_payment    = 0.0;
  610. int i, j;
  611.  
  612. init(argc, argv);
  613. print_header();
  614.  
  615. for (i=1; i<=number; i++) {
  616.  
  617.     for (j=0; j<i_idx; j++)
  618.         if (i == i_mon[j]) {        /* interest rate change */
  619.             rate = i_pay[j];
  620.             break;            /* found one, we're done */
  621.             }
  622.  
  623.     interest = rate * amount;
  624.  
  625.     if (delta_day != 0)
  626.         if (i == 1)
  627.             /* adjust first month to be days more/less than 30 */
  628.             interest += delta_day * (rate / 30.0) * amount;
  629.  
  630.     /* INTEREST */
  631.     /****************************************************************/
  632.     /* There are several ways one might round the interest due.    */
  633.     /* Un-comment a different method if that applies in your case.    */
  634.     /****************************************************************/
  635.     /* round up */
  636.     /* interest = ceil(interest * 100.0) / 100.0; */
  637.     /* normal rounding ( >= .5 < )*/
  638.     interest = floor(interest * 100.0 + 0.5) / 100.0;
  639.     /* round down (truncate) */
  640.     /* interest = floor(interest * 100.0) / 100.0; */
  641.  
  642.     principal = payment - interest;
  643.     pay = payment;
  644.  
  645.     for (j=0; j<u_idx; j++)
  646.         if (i == u_mon[j]) {        /* unusual payment defined */
  647.             if (u_pay[j] == 0) {        /* missed payment */
  648.                 principal = -interest;
  649.                 pay = interest = 0.0;
  650.                 }
  651.             else {                /* low payment */
  652.                 pay = u_pay[j];
  653.                 if (interest < pay)
  654.                     principal = pay - interest;
  655.                 else {
  656.                     principal = -(interest - pay);
  657.                     interest = pay;
  658.                     }
  659.                 }
  660.             break;            /* found one, we're done */
  661.             }
  662.  
  663.     for (j=0; j<e_idx; j++)
  664.         if (i == e_mon[j]) {        /* extra payment defined */
  665.             if (e_pay[j] < 0) {        /* penality */
  666.                 principal += e_pay[j];
  667.                 pay += e_pay[j];
  668.                 }
  669.             else {                /* extra principal */
  670.                 principal += e_pay[j];
  671.                 pay += e_pay[j];
  672.                 }
  673.             break;            /* found one, we're done */
  674.             }
  675.  
  676.     /* SPECIAL */
  677.     /********************************************************/
  678.     /* This is the place to do any special case handling    */
  679.     /* that can't be handled by the -e, -u, or -d arguments    */
  680.     /* It is triggered by a specific payment number (to be    */
  681.     /* filled in at the 'xx') and allows for modifying the    */
  682.     /* principal or payment amound for that month.        */
  683.     /*        >>>>>> USE WITH CARE <<<<<<        */
  684.     /********************************************************/
  685. /*    if (i == xx) {
  686.         principal += <some value>;
  687.         pay      += <some value>;
  688.         }                    */
  689.  
  690.     if (principal >= amount) {        /* loan paid off */
  691.         principal = amount;
  692.         pay = interest + principal;
  693.         number = 0;
  694.         }
  695.  
  696.     if (i == number && balloon) {        /* loan done, balloon */
  697.         principal = amount;
  698.         pay = interest + principal;
  699.         number = 0;
  700.         }
  701.  
  702.     amount -= principal;
  703.     printf("%4d   %.2d%c%.2d%c%.2d ", i, month, SEP, day, SEP, year);
  704.     printf("%s ", add_commas(pay));
  705.     printf("%s ", add_commas(interest));
  706.     printf("%s ", add_commas(principal));
  707.     printf("%s\n", add_commas(amount));
  708.     t_interest += interest;
  709.  
  710.     if (principal > 0)
  711.         t_principal += principal;
  712.  
  713.     if (pay > 0)
  714.         t_payment += pay;
  715.  
  716.     if (month == 12) {
  717.         print_totals("                ", t_payment, t_interest,
  718.                 t_principal);
  719.         gt_interest += t_interest;
  720.         gt_principal += t_principal;
  721.         gt_payment += t_payment;
  722.         t_interest = t_principal = t_payment = 0.0;
  723.         month = 0;
  724.         year += 1;
  725.  
  726.         if (year > 99)
  727.             year = 0;
  728.  
  729.         if (i < number) {
  730.             printf("\n");
  731.             if (format)
  732.                 printf(".ne 14\n"); /* need 14 lines per year */
  733.             else
  734.                 printf("%s\n", titles);
  735.             }
  736.         }
  737.     month += 1;
  738.     }
  739.  
  740. if (month != 1) {                /* pickup a partial year */
  741.     print_totals("                ", t_payment, t_interest, t_principal);
  742.     gt_interest += t_interest;
  743.     gt_principal += t_principal;
  744.     gt_payment += t_payment;
  745.     }
  746.  
  747. printf("\n");
  748. print_totals("loan totals:    ", gt_payment, gt_interest, gt_principal);
  749.  
  750. exit(0);
  751. }
  752.  
  753. /* end of file */
  754.