Canola  0.8.D001
lib/calculator/program_card_visit.cc
Go to the documentation of this file.
00001 //
00002 // canola - canon canola 1614p emulator
00003 // Copyright (C) 2011, 2012 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/calculator.h>
00019 #include <lib/program_card/functor.h>
00020 #include <lib/std_string_printf.h>
00021 #include <lib/sizeof.h>
00022 
00023 
00024 typedef std::list<int> int_list_t;
00025 
00026 static void
00027 add_flag(int_list_t &flags, int flag)
00028 {
00029     int_list_t::iterator it = std::find(flags.begin(), flags.end(), flag);
00030     if (it == flags.end())
00031         flags.push_back(flag);
00032 
00033 }
00034 
00035 
00036 void
00037 calculator::program_card_walk(program_card_functor &f)
00038     const
00039 {
00040     f.set_title(get_property("title"));
00041     f.set_style(get_property("style")); // do this first so can override
00042     if (have_property("arrow"))
00043         f.set_arrow(get_bool_property("arrow"));
00044     if (have_property("color"))
00045         f.set_color(get_property("color"));
00046     if (have_property("disassemble"))
00047         f.set_disassemble(get_bool_property("disassemble"));
00048     if (have_property("perforations"))
00049         f.set_perforations(get_bool_property("perforations"));
00050     if (have_property("trim-corners"))
00051         f.set_trim_corners(get_bool_property("trim-corners"));
00052 
00053     unsigned lo = 1;
00054     unsigned hi = 241;
00055     switch (program_selector)
00056     {
00057     case program_selector_i:
00058         hi = 121;
00059         break;
00060 
00061     case program_selector_ii:
00062         lo = 121;
00063         break;
00064 
00065     default:
00066     case program_selector_i_ii:
00067         break;
00068     }
00069 
00070     // Stop at the first $000 instruction
00071     {
00072         unsigned max = lo;
00073         while (max < hi && programme[max])
00074             ++max;
00075         hi = max;
00076     }
00077     f.set_steps(hi - lo);
00078 
00079     // look for SFJ and FJ
00080     {
00081         int_list_t sfj_list;
00082         int_list_t fj_list;
00083         int_list_t memory_list;
00084         for (unsigned pc = lo; pc < hi; ++pc)
00085         {
00086             opcode_t op = (opcode_t)programme[pc];
00087             assert(op < 128);
00088             switch (op)
00089             {
00090             case opcode_zero:
00091             case opcode_plus_equals:
00092             case opcode_minus_equals:
00093             case opcode_mul:
00094             case opcode_div:
00095             case opcode_sqrt:
00096             case opcode_ent:
00097                 break;
00098 
00099             case opcode_sj:
00100             case opcode_ej:
00101             case opcode_mj:
00102             case opcode_uj:
00103             case opcode_fj:
00104                 add_flag(fj_list, programme[++pc]);
00105                 break;
00106 
00107             case opcode_suj:
00108             case opcode_sfj:
00109                 add_flag(sfj_list, programme[++pc]);
00110                 break;
00111 
00112             case opcode_srj:
00113                 break;
00114 
00115             case opcode_m1:
00116             case opcode_m2:
00117             case opcode_m3:
00118             case opcode_m4:
00119             case opcode_m5:
00120             case opcode_m6:
00121             case opcode_m7:
00122             case opcode_m8:
00123             case opcode_m9:
00124             case opcode_m10:
00125             case opcode_m11:
00126             case opcode_m12:
00127             case opcode_m13:
00128             case opcode_m14:
00129                 add_flag(memory_list, op - (opcode_m1 - 1));
00130                 break;
00131 
00132             case opcode_mm1:
00133             case opcode_mm2:
00134                 add_flag(memory_list, op - (opcode_mm1 - 1));
00135                 break;
00136 
00137             case opcode_sm3:
00138             case opcode_sm4:
00139             case opcode_sm5:
00140             case opcode_sm6:
00141             case opcode_sm7:
00142             case opcode_sm8:
00143             case opcode_sm9:
00144             case opcode_sm10:
00145             case opcode_sm11:
00146             case opcode_sm12:
00147             case opcode_sm13:
00148             case opcode_sm14:
00149                 add_flag(memory_list, op - (opcode_sm3 - 3));
00150                 break;
00151 
00152             case opcode_rm1:
00153             case opcode_rm2:
00154             case opcode_rm3:
00155             case opcode_rm4:
00156             case opcode_rm5:
00157             case opcode_rm6:
00158             case opcode_rm7:
00159             case opcode_rm8:
00160             case opcode_rm9:
00161             case opcode_rm10:
00162             case opcode_rm11:
00163             case opcode_rm12:
00164             case opcode_rm13:
00165             case opcode_rm14:
00166                 add_flag(memory_list, op - (opcode_rm1 - 1));
00167                 break;
00168 
00169             case opcode_clear_indicator:
00170                 break;
00171 
00172             case opcode_cm1:
00173             case opcode_cm2:
00174             case opcode_cm3:
00175             case opcode_cm4:
00176             case opcode_cm5:
00177             case opcode_cm6:
00178             case opcode_cm7:
00179             case opcode_cm8:
00180             case opcode_cm9:
00181             case opcode_cm10:
00182             case opcode_cm11:
00183             case opcode_cm12:
00184             case opcode_cm13:
00185             case opcode_cm14:
00186                 add_flag(memory_list, op - (opcode_cm1 - 1));
00187                 break;
00188 
00189             case opcode_dot:
00190             case opcode_rv:
00191             case opcode_right:
00192             case opcode_chg_sign:
00193                 break;
00194 
00195             case opcode_round_down:
00196             case opcode_round_off:
00197             case opcode_round_up:
00198                 ++pc;
00199                 break;
00200 
00201             case opcode_print:
00202             case opcode_fd:
00203             case opcode_n0:
00204             case opcode_n1:
00205             case opcode_n2:
00206             case opcode_n3:
00207             case opcode_n4:
00208             case opcode_n5:
00209             case opcode_n6:
00210             case opcode_n7:
00211             case opcode_n8:
00212             case opcode_n9:
00213             case opcode_n10:
00214             case opcode_n11:
00215             case opcode_n12:
00216             case opcode_n13:
00217             case opcode_n14:
00218                 break;
00219 
00220             case opcode_extended_c:
00221             case opcode_extended_start:
00222             case opcode_extended_m3_tilde:
00223             case opcode_extended_sm3_tilde:
00224             case opcode_extended_rm3_tilde:
00225             case opcode_extended_cm3_tilde:
00226             case opcode_extended_off:
00227             case opcode_extended_program_print:
00228             case opcode_extended_display_print:
00229             case opcode_extended_paper_feed:
00230             case opcode_extended_rounding_switch_up:
00231             case opcode_extended_rounding_switch_off:
00232             case opcode_extended_rounding_switch_down:
00233             case opcode_extended_decimal_point_selector_0:
00234             case opcode_extended_decimal_point_selector_1:
00235             case opcode_extended_decimal_point_selector_2:
00236             case opcode_extended_decimal_point_selector_3:
00237             case opcode_extended_decimal_point_selector_4:
00238             case opcode_extended_decimal_point_selector_5:
00239             case opcode_extended_decimal_point_selector_6:
00240             case opcode_extended_decimal_point_selector_7:
00241             case opcode_extended_decimal_point_selector_8:
00242             case opcode_extended_decimal_point_selector_9:
00243             case opcode_extended_decimal_point_selector_10:
00244             case opcode_extended_decimal_point_selector_11:
00245             case opcode_extended_decimal_point_selector_12:
00246             case opcode_extended_decimal_point_selector_float:
00247             case opcode_extended_goto_000:
00248             case opcode_extended_goto_001:
00249             case opcode_extended_goto_002:
00250             case opcode_extended_goto_003:
00251             case opcode_extended_goto_004:
00252             case opcode_extended_goto_005:
00253             case opcode_extended_goto_006:
00254             case opcode_extended_goto_007:
00255             case opcode_extended_goto_008:
00256             case opcode_extended_goto_009:
00257             case opcode_extended_goto_010:
00258             case opcode_extended_goto_011:
00259             case opcode_extended_goto_012:
00260             case opcode_extended_goto_013:
00261             case opcode_extended_goto_014:
00262             case opcode_extended_goto_015:
00263             case opcode_extended_goto_100:
00264             case opcode_extended_goto_101:
00265             case opcode_extended_goto_102:
00266             case opcode_extended_goto_103:
00267             case opcode_extended_goto_104:
00268             case opcode_extended_goto_105:
00269             case opcode_extended_goto_106:
00270             case opcode_extended_goto_107:
00271             case opcode_extended_goto_108:
00272             case opcode_extended_goto_109:
00273             case opcode_extended_goto_110:
00274             case opcode_extended_goto_111:
00275             case opcode_extended_goto_112:
00276             case opcode_extended_goto_113:
00277             case opcode_extended_goto_114:
00278             case opcode_extended_goto_115:
00279             case opcode_extended_goto_200:
00280             case opcode_extended_goto_201:
00281             case opcode_extended_goto_202:
00282             case opcode_extended_goto_203:
00283             case opcode_extended_goto_204:
00284             case opcode_extended_goto_205:
00285             case opcode_extended_goto_206:
00286             case opcode_extended_goto_207:
00287             case opcode_extended_goto_208:
00288             case opcode_extended_goto_209:
00289             case opcode_extended_goto_210:
00290             case opcode_extended_goto_211:
00291             case opcode_extended_goto_212:
00292             case opcode_extended_goto_213:
00293             case opcode_extended_goto_214:
00294             case opcode_extended_goto_215:
00295             case opcode_extended_goto_300:
00296             case opcode_extended_goto_301:
00297             case opcode_extended_goto_302:
00298             case opcode_extended_goto_303:
00299             case opcode_extended_goto_304:
00300             case opcode_extended_goto_305:
00301             case opcode_extended_goto_306:
00302             case opcode_extended_goto_307:
00303             case opcode_extended_goto_308:
00304             case opcode_extended_goto_309:
00305             case opcode_extended_goto_310:
00306             case opcode_extended_goto_311:
00307             case opcode_extended_goto_312:
00308             case opcode_extended_goto_313:
00309             case opcode_extended_goto_314:
00310             case opcode_extended_goto_315:
00311             case opcode_extended_goto_400:
00312             case opcode_extended_goto_401:
00313             case opcode_extended_goto_402:
00314             case opcode_extended_goto_403:
00315             case opcode_extended_goto_404:
00316             case opcode_extended_goto_405:
00317             case opcode_extended_goto_406:
00318             case opcode_extended_goto_407:
00319             case opcode_extended_goto_408:
00320             case opcode_extended_goto_409:
00321             case opcode_extended_goto_410:
00322             case opcode_extended_goto_411:
00323             case opcode_extended_goto_412:
00324             case opcode_extended_goto_413:
00325             case opcode_extended_goto_414:
00326             case opcode_extended_goto_415:
00327             case opcode_extended_goto_500:
00328             case opcode_extended_goto_501:
00329             case opcode_extended_goto_502:
00330             case opcode_extended_goto_503:
00331             case opcode_extended_goto_504:
00332             case opcode_extended_goto_505:
00333             case opcode_extended_goto_506:
00334             case opcode_extended_goto_507:
00335             case opcode_extended_goto_508:
00336             case opcode_extended_goto_509:
00337             case opcode_extended_goto_510:
00338             case opcode_extended_goto_511:
00339             case opcode_extended_goto_512:
00340             case opcode_extended_goto_513:
00341             case opcode_extended_goto_514:
00342             case opcode_extended_goto_515:
00343             case opcode_extended_goto_600:
00344             case opcode_extended_goto_601:
00345             case opcode_extended_goto_602:
00346             case opcode_extended_goto_603:
00347             case opcode_extended_goto_604:
00348             case opcode_extended_goto_605:
00349             case opcode_extended_goto_606:
00350             case opcode_extended_goto_607:
00351             case opcode_extended_goto_608:
00352             case opcode_extended_goto_609:
00353             case opcode_extended_goto_610:
00354             case opcode_extended_goto_611:
00355             case opcode_extended_goto_612:
00356             case opcode_extended_goto_613:
00357             case opcode_extended_goto_614:
00358             case opcode_extended_goto_615:
00359             case opcode_extended_goto_700:
00360             case opcode_extended_goto_701:
00361             case opcode_extended_goto_702:
00362             case opcode_extended_goto_703:
00363             case opcode_extended_goto_704:
00364             case opcode_extended_goto_705:
00365             case opcode_extended_goto_706:
00366             case opcode_extended_goto_707:
00367             case opcode_extended_goto_708:
00368             case opcode_extended_goto_709:
00369             case opcode_extended_goto_710:
00370             case opcode_extended_goto_711:
00371             case opcode_extended_goto_712:
00372             case opcode_extended_goto_713:
00373             case opcode_extended_goto_714:
00374             case opcode_extended_goto_715:
00375                 break;
00376 
00377             default:
00378                 break;
00379             }
00380         }
00381         if (!sfj_list.empty())
00382         {
00383             sfj_list.sort();
00384             std::string text;
00385             bool first = true;
00386             for
00387             (
00388                 int_list_t::const_iterator it = sfj_list.begin();
00389                 it != sfj_list.end();
00390                 ++it
00391             )
00392             {
00393                 if (first)
00394                     first = false;
00395                 else
00396                     text += ", ";
00397                 text += opcode_raw_name((opcode_t)*it);
00398             }
00399             f.set_sfj_list(text);
00400         }
00401         if (!fj_list.empty())
00402         {
00403             fj_list.sort();
00404             std::string text;
00405             bool first = true;
00406             for
00407             (
00408                 int_list_t::const_iterator it = fj_list.begin();
00409                 it != fj_list.end();
00410                 ++it
00411             )
00412             {
00413                 if (first)
00414                     first = false;
00415                 else
00416                     text += ", ";
00417                 text += opcode_raw_name((opcode_t)*it);
00418             }
00419             f.set_fj_list(text);
00420         }
00421         if (!memory_list.empty())
00422         {
00423             memory_list.sort();
00424             std::string text;
00425             bool first = true;
00426             for
00427             (
00428                 int_list_t::const_iterator it = memory_list.begin();
00429                 it != memory_list.end();
00430                 ++it
00431             )
00432             {
00433                 if (first)
00434                     first = false;
00435                 else
00436                     text += ", ";
00437                 text += std_string_printf("%d", *it);
00438             }
00439             f.set_memory_list(text);
00440         }
00441     }
00442 
00443     unsigned ipc = f.instructions_per_card();
00444     assert(ipc > 0);
00445 
00446     unsigned card_count = (hi - lo + ipc - 1) / ipc;
00447     for (unsigned card_num = 1; card_num <= card_count; ++card_num)
00448     {
00449         unsigned start = lo + ipc * (card_num - 1);
00450         unsigned finish = start + ipc;
00451         if (finish > hi)
00452             finish = hi;
00453         f(card_num, card_count, programme + start, finish - start);
00454     }
00455 }
00456 
00457 
00458 bool
00459 calculator::have_property(const std::string &name)
00460     const
00461 {
00462     properties_t::const_iterator it = properties.find(name);
00463     return (it != properties.end());
00464 }
00465 
00466 
00467 std::string
00468 calculator::get_property(const std::string &name, const std::string &dflt)
00469     const
00470 {
00471     properties_t::const_iterator it = properties.find(name);
00472     if (it == properties.end())
00473         return dflt;
00474     return it->second;
00475 }
00476 
00477 
00478 bool
00479 calculator::get_bool_property(const std::string &name, bool dflt)
00480     const
00481 {
00482     properties_t::const_iterator it = properties.find(name);
00483     if (it == properties.end())
00484         return dflt;
00485 
00486     struct table_t
00487     {
00488         const char *name;
00489         bool value;
00490     };
00491 
00492     static const table_t table[] =
00493     {
00494         { "true", true },
00495         { "false", false },
00496         { "yes", true },
00497         { "no", false },
00498         { "1", true },
00499         { "0", false },
00500     };
00501 
00502     for (const table_t *tp = table; tp < ENDOF(table); ++tp)
00503     {
00504         if (it->second == tp->name)
00505             return tp->value;
00506     }
00507     return dflt;
00508 }