$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: lists.drrngrvy_at_[hidden]
Date: 2008-03-21 13:07:32
Author: drrngrvy
Date: 2008-03-21 13:07:31 EDT (Fri, 21 Mar 2008)
New Revision: 43756
URL: http://svn.boost.org/trac/boost/changeset/43756
Log:
* Added fcgi/amortization example
* Modified fcgi/echo example to make it a bit cleaner
Added:
   sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/
   sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/Jamfile.v2   (contents, props changed)
   sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.css   (contents, props changed)
   sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.js   (contents, props changed)
   sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.tpl   (contents, props changed)
   sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/main.cpp   (contents, props changed)
Text files modified: 
   sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/echo/main.cpp |    40 +++++++++++++++++++++++++++++-----------
   1 files changed, 29 insertions(+), 11 deletions(-)
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/Jamfile.v2	2008-03-21 13:07:31 EDT (Fri, 21 Mar 2008)
@@ -0,0 +1,52 @@
+#             Copyright (c) 2007 Darren Garvey
+#
+# Distributed under the Boost Software License, Version 1.0.
+#     (See accompanying file LICENSE_1_0.txt or copy 
+#        at http://www.boost.org/LICENSE_1_0.txt)
+
+# A symbolic name for this project.
+project boost.cgi.examples.fcgi.amortization ;
+
+import os ;
+
+if [ os.name ] = NT
+{
+  lib ctemplate : : <file>c:/cc/src/ctemplate/ctemplate-0.9/Release/libctemplate.lib ;
+}
+else
+{
+  lib ctemplate ;
+}
+
+
+exe fcgi_amort
+  :
+    main.cpp
+    /boost/regex/
+  :
+    <library>ctemplate
+  :
+    #<linkflags>-lctemplate
+  ;
+
+# Our install rule (builds binaries and copies them to <location>)
+install install
+ :
+   fcgi_amort
+   amortization.tpl
+ :
+ :
+   <location>$(fcgi-bin)
+ ;
+
+install install-extra
+ :
+   amortization.css
+   amortization.js
+ :
+ :
+   <location>$(htdocs)
+ ;
+
+# Only install example if you use `bjam install' or equivalent
+explicit install ;
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.css
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.css	2008-03-21 13:07:31 EDT (Fri, 21 Mar 2008)
@@ -0,0 +1,94 @@
+body,  table, input, select, textarea, .text {
+	font-family: Arial, Helvetica, sans-serif;	
+	font-size: 12px;	
+	color: #333333; 		
+}
+body {
+	background-color: #CCCCCC;
+}
+h1 {
+	font-family: Georgia, Times New Roman; 						
+	font-weight: bold; 						
+	font-size: 20px; 						
+	font-style: normal;
+	color: #4274B7; 								
+	border-bottom-color: #B1AFA2; 					
+}
+hr {
+	color: #B1AFA2;								
+}
+.ssl {
+	border: 1px solid #B1AFA2;					
+}
+a{
+	color: #315688;							
+}
+.color1 {
+	background-color: #BFA280;
+}
+.color2 {
+	background-color: #BFA280;
+}
+.nav {
+	background-color: #89A8E0;
+}
+.top_nav {
+	background-color: #4274B7;
+}
+.right_nav {
+	background-color: #FFFFFF;
+}
+.main_cell {
+	background-color: #FFFFFF;			
+}
+.td1 {
+	background-color: #F0EAE1;
+    padding: 0cm .1cm; 
+	font-weight: normal; 
+	color: #000000;
+}
+.td2 {
+	background-color: #FFFFFF;
+    padding: 0cm .1cm; 
+	font-weight: normal; 
+	color: #000000;
+}
+.row1 {
+	background-color: #F0EAE1;
+    padding: 0cm .1cm; 
+	font-weight: normal; 
+	color: #000000;
+    text-align: right
+}
+.row2 {
+	background-color: #FFFFFF;
+    padding: 0cm .1cm; 
+	font-weight: normal; 
+	color: #000000;
+    text-align: right
+}
+.tblbase {
+	background-color: #B1AFA2; 
+}
+.tblhead {
+	font-weight: bold;
+	color: #FFFFFF;
+	background-color: #315688;
+}
+
+.header a {
+	background-color: #315688;
+	color: #FFFFFF;
+}
+.header a:hover {
+	background-color: #4274B7;
+	color: #FFFFFF;
+}
+.button a {
+	background-color: #BFA280;
+	color: #FFFFFF;
+}
+.button a:hover {
+	background-color: #666666;
+	color: #FFFFFF;
+}
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.js
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.js	2008-03-21 13:07:31 EDT (Fri, 21 Mar 2008)
@@ -0,0 +1,234 @@
+function printable()
+{
+	document.temps.submit();
+	
+}
+
+function clearForm(form) {
+  form.income.value = "";
+  form.auto.value = "";  
+  form.rate.value="";
+  form.payment.value = "";
+  form.amount.value = "";
+}
+
+function housingRatio(income, insurance) {	
+	housing = eval(income * .28)
+  return housing;
+}
+
+function debtRatio(income, auto) {	
+	debt = eval(income * .36) - auto;
+  return debt;
+}
+
+function checkForm(toCheck) {	
+  isNum = true;
+  for (j = 0; j < toCheck.length; j++) {
+    if (((((toCheck.substring(j,j+1) < "0") || (toCheck.substring(j,j+1) > "9")) && (toCheck.substring(j,j+1) != ",")) 
+		|| (toCheck.substring(j,j+1) > "9")) && (toCheck.substring(j,j+1) != ".")){
+      isNum = false;
+      }
+    }
+  if ((isNum == false) || (toCheck.length == 0) || (toCheck == null)) {
+  alert("Please enter only numerical data in all fields.");
+  return false;
+  }
+  else {
+  return true;
+  }
+}     
+function computeForm(form) {
+	basicedit();
+
+	income = replaceChars(form.income.value);
+	income = replaceChar(income);
+	if (income <= "0"){ 
+		alert("You need to be employed to finance a house!")
+		form.payment.value = "0";
+		form.payment2.value = "0";
+		form.amount.value = "0";
+		form.amount2.value = "0";
+		return false;}	
+	auto = replaceChars(form.auto.value);
+	auto = replaceChar(auto);
+	var a = form.rate.value;
+	var a = replacePct(a);
+
+	if (a > 20 )	
+	{	
+		alert ("Interest Rate must not be greater than " + 20 + " percent");			
+		form.rate.value=addPct('20');		
+		a = form.rate.value;
+		a = replacePct(a);	
+	}
+	else
+	if (a < 1 )	
+	{	
+		alert ("Interest Rate must be greater than " + 1 + " percent");			
+		form.rate.value=addPct('1');		
+		a = form.rate.value;
+		a = replacePct(a);	
+	}			
+	
+if (checkForm(income) && checkForm(auto) && checkForm(a)){	
+    housingRatioResult = Math.round(housingRatio(income));
+    debtRatioResult = Math.round(debtRatio(income, auto));
+	
+	if (debtRatioResult <= "0") 
+	{
+		alert("Either your income is too low or your debt is too high!");
+		form.payment.value = "0";
+		form.payment2.value = "0";
+		form.amount.value = "0";
+		form.amount2.value = "0";
+		return false;
+	}	
+	
+      if (housingRatioResult>debtRatioResult) {
+		form.payment.value = formatCurrency(debtRatioResult);
+		form.payment2.value = formatCurrency(debtRatioResult);
+      }
+      else {
+		form.payment.value = formatCurrency(housingRatioResult);
+		form.payment2.value = formatCurrency(housingRatioResult); 
+      }
+	
+    
+    var c = debtRatioResult;	
+    var d = parseFloat(a / 1200); 
+    var f = parseFloat(1 + d);
+	var f2 = parseFloat(1 + d);
+    var g = parseFloat(Math.pow(f, 360));
+	var g2 = parseFloat(Math.pow(f2, 180));
+    var h = parseFloat(1 / g);
+	var h2 = parseFloat(1 / g2);
+    var i = parseFloat(1 - h);
+	var i2 = parseFloat(1 - h2);
+    var j = parseFloat(i / d);
+	var j2 = parseFloat(i2 / d);
+    var k = parseFloat(c * j);
+	var k2 = parseFloat(c * j2);
+    form.amount.value = formatCurrency(Math.round(k));
+	form.amount2.value = formatCurrency(Math.round(k2));
+
+
+}
+return;
+}
+
+
+function replaceChar(entry) {
+	out = "$"; 
+	add = ""; 
+	temp = "" + entry;
+	while (temp.indexOf(out)>-1) {
+		pos= temp.indexOf(out);
+		temp = "" + (temp.substring(0, pos) + add + 
+		temp.substring((pos + out.length), temp.length));
+	}
+	return temp;
+}
+
+function replacePct(entry) {
+	out = "%"; 
+	add = ""; 
+	temp = "" + entry;
+	while (temp.indexOf(out)>-1) {
+		pos= temp.indexOf(out);
+		temp = "" + (temp.substring(0, pos) + add + 
+		temp.substring((pos + out.length), temp.length));
+	}
+	return temp;
+}	
+	
+function replaceChars(entry) {
+	out = ","; 
+	add = ""; 
+	temp = "" + entry;
+	while (temp.indexOf(out)>-1) {
+		pos= temp.indexOf(out);
+		temp = "" + (temp.substring(0, pos) + add + 
+		temp.substring((pos + out.length), temp.length));
+	}
+	return temp;
+}
+
+function formatCurrency(num) {			
+			num=replaceChar(num);
+			num=replaceChars(num);
+		if ( checkForm(num));
+{
+			num = num.toString().replace(/$|,/g,'');
+			if(isNaN(num)) num = "0";
+			num = Math.floor(num).toString();
+		for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++) 
+			num = num.substring(0,num.length-(4*i+3))+','+num.substring(num.length-(4*i+3));
+			 
+	return ('$' + num );	
+}
+}
+
+function basicedit()
+{
+	if 	(!IsMoney(document.temps.income.value) || document.temps.income.value.length ==0)
+		document.temps.income.value='$3,500';
+		
+	if 	(!IsMoney(document.temps.auto.value) || document.temps.auto.value.length ==0)
+		document.temps.auto.value='../../btn-red27px-R.gif';		
+
+	if 	(!IsPct(document.temps.rate.value) || document.temps.rate.value.length ==0)
+		document.temps.rate.value='7.5%';		
+}
+
+function IsMoney(val)
+	{
+		var number="0123456789$,.";
+
+		for (var i=0;i<val.length;i++)
+		{
+			if (number.indexOf(val.charAt(i)) == -1)
+			{
+				return false;
+			}
+		}
+		return true;
+	}
+
+function IsNumber(val)
+	{
+		var number="0123456789.";
+
+		for (var i=0;i<val.length;i++)
+		{
+			if (number.indexOf(val.charAt(i)) == -1)
+			{
+				return false;
+			}
+		}
+		return true;
+	}
+	
+function IsPct(val)
+	{
+		var number="0123456789.%,";
+
+		for (var i=0;i<val.length;i++)
+		{
+			if (number.indexOf(val.charAt(i)) == -1)
+			{
+				return false;
+			}
+		}
+		return true;
+	}
+
+function addPct(pct) {
+			pct=replacePct(pct);
+			pct=parseFloat(pct);		
+		if (checkForm(pct));
+	{
+			return (pct + '%');
+		}
+}
+
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.tpl
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/amortization.tpl	2008-03-21 13:07:31 EDT (Fri, 21 Mar 2008)
@@ -0,0 +1,174 @@
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" href="/amortization.css">
+
+  <title>Fixed Mortgage Loan Calculator</title>
+  <script type="text/javascript" language="JavaScript1.2" src="/amortization.js"></script>
+</head>
+
+<body>
+
+{{!--Amortization form}}
+<form name="AmortBrowser" action="{{SCRIPT_NAME}}" method="post">
+  <input type="hidden" name="Amortize" value="1">
+  <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
+    <tr>
+      <td colspan=4 class=tblhead align=center>FIXED MORTGAGE LOAN CALCULATOR</td>
+    </tr>
+    <tr>
+      <td colspan=2 class=tblhead align=center>Loan Information</td>
+      <td colspan=2 class=tblhead align=center>Prepayment Information (optional)</td>
+    </tr>
+    <tr>
+      <td width="250" class="td1">Mortgage Amount</td>
+      <td class="td2">
+        <input name="LoanAmt" type="text" onBlur="this.value=formatCurrency(this.value);" value="{{LoanAmt}}" size="10">
+      </td>
+      <td width="250" class="td1">Prepayment Frequency</td>
+      <td class="td2">
+        <select name="PrePmtFreq" {{PrePmtFreqInvalid}}>{{PrePmtFreq}}</select>
+      </td>
+    </tr>
+    <tr>
+      <td class="td1">Interest (APR)</td>
+      <td class="td2">
+        <input name="YearlyIntRate" type="text" value="{{YearlyIntRate}}" size="10">
+      </td>
+      <td class="td1">Prepayment Amount</td>
+      <td class="td2">
+        <input name="PrePmtAmt" type="text" value="{{PrePmtAmt}}" size="17" {{PrePmtFreqInvalid}}>
+      </td>
+    </tr>
+    <tr>
+      {{!-- Length of Loan selection list }}
+      <td class="td1">Length of Loan</td>
+      <td class="td2">
+        <select name="TermYrs">
+          {{#SELECT_TERM_YEARS}}
+            <option value="{{TermYrs}}">{{TermYrs}} Years</option>
+          {{/SELECT_TERM_YEARS}}
+        </select>
+      </td>
+      <td class="td1">Start with Payment</td>
+      <td class="td2">
+        <input name="PrePmtBegin" type="text" value="{{PrePmtBegin}}" size="17">
+      </td>
+    </tr>
+    <tr>
+      <td class="td1"></td>
+      <td class="td2">
+        <input type="submit" value="Calculate">
+      </td>
+    </tr>
+
+    {{#NotAmortize}}
+    <tr>
+      <td colspan="4" class="td2"><span class="small">
+        DISCLAIMER: The figures above are based upon conventional program guidelines.<br>
+        Calculations by this tool are believed to be accurate, yet are not guaranteed. Further review is<br>
+        necessary to obtain an exact qualification.  If you have less than 20% equity in your home, a monthly<br>
+        mortgage insurance payment may be required.
+      </span></td>
+    </tr>
+    {{/NotAmortize}}
+
+  </table>
+</FORM>
+
+{{!--Prepayment summary table}}
+{{#PrePmtSummary}}
+  <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
+    <tr>
+      <td colspan=4 class=tblhead align=center>PREPAYMENT vs REGULAR PAYMENT</td>
+    </tr>
+    <tr>
+      <td colspan=2 class=tblhead align=center>Prepayment Results</td>
+      <td colspan=2 class=tblhead align=center>Regular Payment Results</td>
+    </tr>
+    <tr>
+      <td class="td1">Number of months to pay loan</td>
+      <td class="td2" width="125">
+        <center><b>{{PrePmt_iPmtNo}}</b></center>
+      </td>
+      <td class="td1"></td>
+      <td class="td2" width="125">
+        <center><b>{{RegPmt_iPmtNo}}</b></center>
+      </td>
+    </tr>
+    <tr>
+      <td class="td1">Total Interest Paid</td>
+      <td class="td2" align="right">{{PrePmt_TotalIntPd}}</td>
+      <td class="td1"></td>
+      <td class="td2" align="right">{{RegPmt_TotalIntPd}}</td>
+    </tr>
+    <tr>
+      <td width="250" class="td1">Total Payments</td>
+      <td class="td2" align="right">{{PrePmt_TotalPmts}}</td>
+      <td width="250" class="td1"></td>
+      <td class="td2" align="right">{{RegPmt_TotalPmts}}</td>
+    </tr>
+    <tr>
+      <td colspan="4" class="td2"><span class="small">
+        <br>
+        By applying the prepayments in the schedule above, you would <u>realize these savings</u>:
+        <ul>
+          <li>
+            You pay the <b>{{RegPmt_term_to_words}}</b> loan in <b>{{PrePmt_term_to_words}}</b>
+            <br><br>
+          <li>The total loan payments will be <b>{{PrePmt_TotalPmts}}</b> instead of <b>{{RegPmt_TotalPmts}}</b>
+        </ul>
+      </span></td>
+    </tr>
+  </table>
+  <br>
+{{/PrePmtSummary}}
+
+{{#RegPmtSummary}}
+  {{!--Regular Payment summary table}}
+  <table width="550" border="0" cellpadding="0" cellspacing="1" class="tblbase">
+    <tr>
+      <td colspan=4 class=tblhead align=center>REGULAR PAYMENT SUMMARY</td>
+    </tr>
+    <tr>
+      <td class="td1">Monthly Payment</td>
+      <td class="td2" width="125" align="right"><b>${{MonthlyPmt}}</b></td>
+    </tr>
+    <tr>
+      <td class="td1">Total Interest Paid</td>
+      <td class="td2" width="125" align="right">${{RegPmt_TotalIntPd}}</td>
+    </tr>
+    <tr>
+      <td class="td1">Total Payments</td>
+      <td class="td2" width="125" align="right">${{RegPmt_TotalPmts}}</td>
+    </tr>
+  </table>
+  <br>
+{{/RegPmtSummary}}
+
+{{!--Amortization table}}
+
+{{#Amortize}}
+  <table border=0 cellpadding=0 cellspacing=1 width=550 class="tblbase">
+    <tr>
+      <td colspan=6 class=tblhead align=center>AMORTIZATION TABLE</td>
+    </tr>
+    <td class=tblhead align=center>Payment</td>
+    <td class=tblhead align=center>Mo. Payment</td>
+    <td class=tblhead align=center>Interest Pd.</td>
+    <td class=tblhead align=center>Principal Pd.</td>
+    <td class=tblhead align=center>New Balance</td>
+    {{#PaymentEntry}}
+      <tr class=row{{ROW_TYPE}}>
+        <td ALIGN=CENTER>{{ROW_NUM}}</td>
+        <td>${{Payment}}</td>
+        <td>${{InterestPaid}}</td>
+        <td>${{PrincipalPaid}}</td>
+        <td>${{Balance}}</td>
+      </tr>
+    {{/PaymentEntry}}
+  </table>
+{{/Amortize}}
+
+</body>
+</html>
+
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/main.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/amortization/main.cpp	2008-03-21 13:07:31 EDT (Fri, 21 Mar 2008)
@@ -0,0 +1,249 @@
+//                     -- main.hpp --
+//
+//           Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+//
+// Amortization Calculator
+// -----------------------
+//
+// This file uses Google cTemplate to show the benefits of using an
+// HTML template engine. The code isn't commented, but should be 
+// reasonably self-explanatory.
+//
+// It is a very basic amortization calculator.
+//
+#include <iostream>
+#include <iomanip>
+#include <boost/cgi/fcgi.hpp>
+#include <boost/algorithm/string/regex.hpp>
+#include <google/template.h>
+#include <boost/high_resolution_timer.hpp>
+
+using namespace boost::fcgi;
+
+/// Convert a string like '$250,000' into one like '250000'.
+std::string string_from_currency(std::string amt)
+{
+  // this is much too hardcore, but it works fine...
+  boost::algorithm::erase_all_regex(amt, boost::regex("[$, ]"));
+  return amt;
+}
+
+/// This function fills the dictionary and sub-dictionaries with relevant values.
+template<typename Request>
+void fill_amortization_dictionary(google::TemplateDictionary& dict, Request& req)
+{
+  std::string tmp( req.POST("LoanAmt") );
+  dict.SetValue("LoanAmt", tmp.empty() ? "$250,000" : tmp);
+
+  tmp = req.POST("YearlyIntRate");
+  dict.SetValue("YearlyIntRate", tmp.empty() ? "6.000" : tmp);
+
+  boost::array<std::string, 8> year_opts
+    = {{ "5", "7", "10", "20", "30", "40", "50" }};
+    
+  BOOST_FOREACH(std::string& year, year_opts)
+  {
+    dict.SetValueAndShowSection("TermYrs", year, "SELECT_TERM_YEARS");
+  }
+
+  if (req.POST("Amortize").empty())
+    dict.ShowSection("NotAmortize");
+  else
+  {
+    double P = boost::lexical_cast<double>(string_from_currency(req.POST("LoanAmt")));
+    double i = boost::lexical_cast<double>(req.POST("YearlyIntRate")) / 1200;
+    double n = boost::lexical_cast<double>(req.POST("TermYrs")) * 12;
+    double monthly_payments = (P*i) / (1 - std::pow((1+i), -n));
+    
+    google::TemplateDictionary* sub_dict = dict.AddSectionDictionary("RegPmtSummary");
+    sub_dict->ShowSection("RegPmtSummary");
+    sub_dict->SetFormattedValue("MonthlyPmt", "%.2f", monthly_payments);
+
+    dict.ShowSection("Amortize");
+    dict.SetValue("SCRIPT_NAME", req.script_name());
+
+    double balance = P;
+    int row_num = 0;
+    double interest;
+    double principal_paid;
+    double total_interest = 0;
+    do{
+      google::TemplateDictionary* sub_dict2 = dict.AddSectionDictionary("PaymentEntry");
+      sub_dict2->ShowSection("PaymentEntry");
+      sub_dict2->SetFormattedValue("Payment", "%.2f", monthly_payments);
+      sub_dict2->SetIntValue("ROW_NUM", ++row_num);
+      sub_dict2->SetIntValue("ROW_TYPE", (row_num % 2) + 1);
+      interest = balance * i;
+      total_interest += interest;
+      sub_dict2->SetFormattedValue("InterestPaid", "%.2f", interest);
+      principal_paid = monthly_payments - interest;
+      sub_dict2->SetFormattedValue("PrincipalPaid", "%.2f", principal_paid);
+      balance -= principal_paid; // Note: balance can increase.
+      sub_dict2->SetFormattedValue("Balance", "%.2f", balance);
+
+    }while(balance > 0);
+
+    sub_dict->SetFormattedValue("RegPmt_TotalIntPd", "%.2f", total_interest);
+    sub_dict->SetFormattedValue("RegPmt_TotalPmts", "%.2f", total_interest + P);
+  }
+}
+
+template<typename Request>
+int write_amortization_template(Request& req, response& resp)
+{
+  google::TemplateDictionary dict("amortization");
+
+  fill_amortization_dictionary(dict, req);
+
+  google::Template* tmpl
+    = google::Template::GetTemplate("amortization.tpl", google::STRIP_WHITESPACE);
+
+  boost::high_resolution_timer t;
+
+  std::string h("Content-type: text/html\r\n\r\n");
+  write(req.client(), buffer(h));
+
+  std::string arg(req.GET("arg"));
+
+  if (arg == "1")
+  {
+    std::string output;
+    tmpl->Expand(&output, &dict);
+    resp<< output;
+  }else
+  if (arg == "2")
+  {
+    std::string output;
+    tmpl->Expand(&output, &dict);
+    write(req.client(), buffer(output));
+  }else
+  if (arg == "3")
+  {
+    std::string s;
+    std::vector<boost::asio::const_buffer> out;
+
+    tmpl->Expand(&s, &out, &dict);
+    write(req.client(), out);
+  }else
+  {
+    resp<< "Error!";
+    return 1;
+  }
+   //output.clear();
+      //<< "<b>" << t.elapsed() << "</b><p />"
+      //<< output << "<p /><p />"
+      //<< "<b>" << t.elapsed() << "</b><p />";
+  //}
+ 
+  //std::cout<<
+  //  "<pre>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nSTARTING OTHER THINGY\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n</pre>"
+  //  ;
+/*
+    std::string s;
+    std::vector<boost::asio::const_buffer> out;
+for(int i=0; i < 50000; ++i) {
+   // boost::high_resolution_timer t;
+
+    tmpl->Expand(&s, &out, &dict);
+    out.clear();
+    s.clear();
+    //std::cout<< "<b>" << t.elapsed() << "</b><p />";
+
+      //<< "<p /><p />"
+      //<< "<b>" << t.elapsed() << "</b><p />";
+  }
+ 
+
+  std::cerr<< "a took " << std::setiosflags(std::ios::fixed) << std::setprecision(5) << a/100000 << " secs<p />"
+           << "b took " << b/100000 << " secs<p />";
+
+  
+  std::cerr
+    << "Content-type: text/html\r\n\r\n"
+    << output << "<p /><p />";
+  
+  resp<< content_type("text/html");
+  resp.flush(req.client());
+  write(req.client(), buffer(output));
+  */
+  return 0;
+}
+
+int handle_request(acceptor& a)
+{
+  boost::system::error_code ec;
+
+  //std::ofstream of("/var/www/log/fcgi_reaccept.txt");
+  using std::endl;
+  //std::cerr<< "Eh?" << endl;
+  //of<< "Opening request" << endl;
+
+  request req(a.protocol_service());
+ 
+  int ret = 0;
+  int num = 0;
+  while(!ec && ret == 0)
+  {
+    response resp;
+    ++num;
+    //std::cerr<< endl << endl << "request num := " << num << endl << endl;
+    //of<< "Accepting now" << endl;
+    a.accept(req);
+    //of<< "Loading" << endl;
+    req.load(true);
+
+    resp<< content_type("text/html")
+        << "map size := " << req.POST().size() << "<p>";
+  
+    //of<< "Writing template" << endl;
+    ret = write_amortization_template(req, resp);
+
+    //of<< "Sending" << endl;
+    resp.send(req.client(), ec);
+    //of<< "Closing" << endl;
+    ret = ret ? ret : req.close(resp.status(), 0,  ec);
+    //of<< "ok. ec := " << ec.message() << endl;
+    //return 1;
+  }
+  return ret;
+}
+
+void accept_requests(acceptor& a)
+{
+  for(;;)
+  {
+    if (handle_request(a))
+      break;
+  }
+}
+
+int main()
+{
+  try{
+  //std::cout
+  //  << "Content-type: text/html\r\n\r\n";
+  using std::endl;
+    service s;
+  std::cerr<< "Eh1?" << endl;
+    acceptor a(s, true);
+    //a.assign(boost::asio::ip::tcp::v4(), 0);
+  std::cerr<< "Eh2?" << endl;
+
+    accept_requests(a);
+    
+    return 0;
+
+  }catch(boost::system::error_code& err){
+    std::cerr<< "CGI error(" << err.value() << "): " << err.message() << std::endl;
+  }catch(boost::system::system_error& err){
+    std::cerr<< "System error(" << err.code() << "): " << err.what() << std::endl;
+  }catch(...){
+    std::cerr<< "ERROR!! BOOM!" << std::endl;
+  }
+}
+
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/echo/main.cpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/echo/main.cpp	2008-03-21 13:07:31 EDT (Fri, 21 Mar 2008)
@@ -1,9 +1,25 @@
+//                    -- main.hpp --
+//
+//           Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+//    (See accompanying file LICENSE_1_0.txt or copy at
+//          http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+//
+//[fcgi_echo
+//
+// This example simply echoes all variables back to the user. ie.
+// the environment and the parsed GET, POST and cookie variables.
+// Note that GET and cookie variables come from the environment
+// variables QUERY_STRING and HTTP_COOKIE respectively.
+//
+
 #include <fstream>
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/program_options/environment_iterator.hpp>
 
 #include <boost/cgi/fcgi.hpp>
-#include <boost/cgi/return.hpp>
 
 using namespace std;
 using namespace boost::fcgi;
@@ -25,6 +41,7 @@
   }
 }
 
+/// This function accepts and handles a single request.
 template<typename Service, typename Acceptor, typename LogStream>
 int handle_request(Service& s, Acceptor& a, LogStream& of)
 {
@@ -58,6 +75,10 @@
   format_map(req.GET(), resp, "GET Variables");
   format_map(req.cookie(), resp, "Cookie Variables");
 
+  // Response headers can be added at any time before send/flushing it:
+  resp<< "<content-length == " << content_length(resp.content_length())
+      << content_length(resp.content_length());
+
   // This funky macro finishes up:
   return_(resp, req, 0);
   // It is equivalent to the below, where the third argument is represented by
@@ -77,29 +98,25 @@
   ofstream of(LOG_FILE);
   if (!of)
   {
-    std::cerr<< "Couldn't open file: \"" LOG_FILE "\"." << endl;
+    std::cerr<< "[fcgi] Couldn't open file: \"" LOG_FILE "\"." << endl;
     return 1;
   }
 
   of<< boost::posix_time::second_clock::local_time() << endl;
-  of<< "Going to start acceptor" << endl;
+  of<< "Going to start acceptor." << endl;
 
   // Make a `service` (more about this in other examples).
   service s;
   // Make an `acceptor` for accepting requests through.
   acceptor a(s);
 
-  // This next line may become void in the future.
-  a.assign(boost::asio::ip::tcp::v4(), 0);
-  of<< "[a] Assigned." << endl;
-
   // After the initial setup, we can enter a loop to handle one request at a
   // time until there's an error of some sort.
   int ret(0);
   for (;;)
   {
     ret = handle_request(s, a, of);
-    of<< "handle_requests() returned: " << ret << endl;
+    of<< "handle_request() returned: " << ret << endl;
     if (ret)
       break;
   }
@@ -107,13 +124,14 @@
   return ret;
 
 }catch(boost::system::system_error& se){
-  cerr<< "[hw] System error: " << se.what() << endl;
+  cerr<< "[fcgi] System error: " << se.what() << endl;
   return 1313;
 }catch(exception& e){
-  cerr<< "[hw] Exception: " << e.what() << endl;
+  cerr<< "[fcgi] Exception: " << e.what() << endl;
   return 666;
 }catch(...){
-  cerr<< "[hw] Uncaught exception!" << endl;
+  cerr<< "[fcgi] Uncaught exception!" << endl;
   return 667;
 }
 }
+//]