Canola  0.8.D001
test_calculator/calculator/test.cc
Go to the documentation of this file.
00001 //
00002 // canola - canon canola 1614p emulator
00003 // Copyright (C) 2011 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License, version 3, as
00007 // published by the Free Software Foundation.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program. If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include <lib/config.h>
00019 #include <libexplain/output.h>
00020 #include <libexplain/printf.h>
00021 #include <libexplain/putchar.h>
00022 
00023 #include <lib/std_string_printf.h>
00024 
00025 #include <test_calculator/calculator/test.h>
00026 
00027 
00028 calculator_test::~calculator_test()
00029 {
00030 }
00031 
00032 
00033 calculator_test::calculator_test()
00034 {
00035 }
00036 
00037 
00038 calculator::pointer
00039 calculator_test::create(void)
00040 {
00041     return pointer(new calculator_test());
00042 }
00043 
00044 
00045 void
00046 calculator_test::derived_print(const display &value)
00047 {
00048     class cursor_t
00049     {
00050     public:
00051         cursor_t() : icol(1), ocol(1) { };
00052 
00053         void
00054         putch(char c)
00055         {
00056             if (c == ' ')
00057                 ++icol;
00058             else
00059             {
00060                 while (ocol < icol)
00061                 {
00062                     putchar(' ');
00063                     ++ocol;
00064                 }
00065                 putchar(c);
00066                 ++icol;
00067                 ocol = icol;
00068             }
00069         }
00070 
00071         void
00072         putstr(const char *s)
00073         {
00074             for (;;)
00075             {
00076                 char c = *s++;
00077                 if (!c)
00078                     return;
00079                 putch(c);
00080             }
00081         }
00082 
00083         void
00084         set_column(int n)
00085         {
00086             assert(n > 17);
00087             if (n > icol)
00088                 icol = n;
00089         }
00090 
00091         void
00092         putch(int col, char c)
00093         {
00094             set_column(col);
00095             putch(c);
00096         }
00097 
00098         void
00099         putstr(int col, const char *s)
00100         {
00101             set_column(col);
00102             putstr(s);
00103         }
00104     private:
00105         int icol;
00106         int ocol;
00107     };
00108     cursor_t cursor;
00109 
00110     for (int dignum = 15; dignum >= 0; --dignum)
00111     {
00112         const display::tube_t &tube = value.tubes[dignum];
00113         if (tube.digit >= 10)
00114             cursor.putch(' ');
00115         else
00116             cursor.putch('0' + tube.digit);
00117         if (tube.dot)
00118             cursor.putch('.');
00119     }
00120     if (value.negative)
00121     {
00122         cursor.set_column(18);
00123         cursor.putch('-');
00124     }
00125     switch (value.column18)
00126     {
00127     case display::column18_blank:
00128         break;
00129 
00130     case display::column18_minus:
00131         if (!value.negative)
00132             cursor.putch(18, '-');
00133         break;
00134 
00135     case display::column18_ce:
00136         cursor.putstr(18, "CE");
00137         break;
00138 
00139     case display::column18_cm:
00140         cursor.putstr(18, "CM");
00141         break;
00142 
00143     case display::column18_e:
00144         cursor.putch(18, 'E');
00145         break;
00146 
00147     case display::column18_fj:
00148         cursor.putstr(18, "FJ");
00149         break;
00150 
00151     case display::column18_ej:
00152         cursor.putstr(18, "EJ");
00153         break;
00154 
00155     case display::column18_uj:
00156         cursor.putstr(18, "UJ");
00157         break;
00158 
00159     case display::column18_mj:
00160         cursor.putstr(18, "MJ");
00161         break;
00162 
00163     case display::column18_sj:
00164         cursor.putstr(18, "SJ");
00165         break;
00166 
00167     case display::column18_rv:
00168         cursor.putstr(18, "RV");
00169         break;
00170 
00171     case display::column18_sfj:
00172         cursor.putstr(18, "SFJ");
00173         break;
00174 
00175     case display::column18_suj:
00176         cursor.putstr(18, "SUJ");
00177         break;
00178 
00179     case display::column18_srj:
00180         cursor.putstr(18, "SRJ");
00181         break;
00182 
00183     case display::column18_right:
00184         cursor.putstr(18, "\u2192");
00185         break;
00186 
00187     case display::column18_cs:
00188         cursor.putstr(18, "CS");
00189         break;
00190 
00191     default:
00192         break;
00193     }
00194     switch (value.column19)
00195     {
00196     case display::column19_blank:
00197         break;
00198 
00199     case display::column19_plus_equals:
00200         cursor.putstr(19, "+=");
00201         break;
00202 
00203     case display::column19_minus_equals:
00204         cursor.putstr(19, "-=");
00205         break;
00206 
00207     case display::column19_times:
00208         cursor.putstr(19, "\u00D7");
00209         break;
00210 
00211     case display::column19_divide:
00212         cursor.putstr(19, "\u00F7");
00213         break;
00214 
00215     case display::column19_sqrt:
00216         cursor.putstr(19, "\u221A");
00217         break;
00218 
00219     case display::column19_m_plus:
00220         cursor.putstr(19, "M+");
00221         break;
00222 
00223     case display::column19_m_minus:
00224         cursor.putstr(19, "M-");
00225         break;
00226 
00227     case display::column19_rm:
00228         cursor.putstr(19, "RM");
00229         break;
00230 
00231     case display::column19_sm:
00232         cursor.putstr(19, "SM");
00233         break;
00234 
00235     case display::column19_print:
00236         cursor.putstr(19, "\u25CA");
00237         break;
00238 
00239     default:
00240         break;
00241     }
00242     switch (value.column20)
00243     {
00244     case display::column20_blank:
00245         break;
00246 
00247     case display::column20_n1:
00248         cursor.putch(20, '1');
00249         break;
00250 
00251     case display::column20_fd:
00252         cursor.putstr(20, "FD");
00253         break;
00254 
00255     case display::column20_round_up:
00256         cursor.putstr(20, "\u2191");
00257         break;
00258 
00259     case display::column20_round_off:
00260         cursor.putstr(20, "5/4");
00261         break;
00262 
00263     case display::column20_round_down:
00264         cursor.putstr(20, "\u2193");
00265         break;
00266 
00267     case display::column20_dot:
00268         cursor.putstr(20, ".");
00269         break;
00270 
00271     default:
00272         break;
00273     }
00274     switch (value.column21)
00275     {
00276     case display::column21_blank:
00277         break;
00278 
00279     case display::column21_n0:
00280     case display::column21_n1:
00281     case display::column21_n2:
00282     case display::column21_n3:
00283     case display::column21_n4:
00284     case display::column21_n5:
00285     case display::column21_n6:
00286     case display::column21_n7:
00287     case display::column21_n8:
00288     case display::column21_n9:
00289         cursor.putch(21, '0' + value.column21 - display::column21_n0);
00290         break;
00291 
00292     default:
00293         break;
00294     }
00295     explain_putchar_or_die('\n');
00296 }
00297 
00298 
00299 void
00300 calculator_test::derived_feed(void)
00301 {
00302     explain_putchar_or_die('\n');
00303 }
00304 
00305 
00306 void
00307 calculator_test::on_error_v(const char *fmt, va_list ap)
00308 {
00309     std::string text = std_string_printf_v(fmt, ap);
00310     explain_output_error_and_die("%s", text.c_str());
00311 }
00312 
00313 
00314 void
00315 calculator_test::run(void)
00316 {
00317     // finish running any program
00318     for (;;)
00319     {
00320         if (printer_finished_event_expected())
00321             printer_finished_event();
00322         else if (clock_tick_expected())
00323             clock_tick_event();
00324         else
00325             break;
00326     }
00327 }
00328 
00329 
00330 void
00331 calculator_test::derived_off(void)
00332 {
00333     exit(0);
00334 }
00335 
00336 
00337 void
00338 calculator_test::derived_update_display(const display &)
00339 {
00340 }
00341 
00342 
00343 void
00344 calculator_test::clock_tick_start_running(void)
00345 {
00346 }
00347 
00348 
00349 void
00350 calculator_test::printer_timer_start_running(void)
00351 {
00352 }
00353 
00354 
00355 void
00356 calculator_test::on_opcode(opcode_t op, const location::pointer &where)
00357 {
00358     calculator::on_opcode(op, where);
00359 
00360     // they could have "pressed" START
00361     // let it run for a few thousand instructions
00362     for (int j = 0; j < 5000; ++j)
00363     {
00364         if (printer_finished_event_expected())
00365             printer_finished_event();
00366         else if (clock_tick_expected())
00367             clock_tick_event();
00368         else
00369             break;
00370     }
00371 }