Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

soar_ecore_api.c

Go to the documentation of this file.
00001 
00042 #include "soarkernel.h"
00043 #include <time.h>
00044 #include "soar_ecore_api.h"
00045 #include "soar_ecore_utils.h"
00046 #include "rete.h"
00047 #include "sysdep.h"
00048 
00049 /* *************************************************************************
00050  * *************************************************************************
00051  *   
00052  * SECTION 3:    ACCESSING, MODIFYING & WATCHING THE AGENT'S STATE
00053  *
00054  *
00055  * *************************************************************************
00056  * *************************************************************************
00057  */
00058 
00059 /*
00060  *----------------------------------------------------------------------
00061  *
00062  * soar_ecSetDefaultWmeDepth
00063  *
00064  *       does what it says
00065  *
00066  *----------------------------------------------------------------------
00067  */
00068 void soar_ecSetDefaultWmeDepth(int depth)
00069 {
00070 
00071     current_agent(default_wme_depth) = depth;
00072 
00073 }
00074 
00075 /*
00076  *----------------------------------------------------------------------
00077  *
00078  * soar_ecOpenLog
00079  *
00080  *       does what it says
00081  *
00082  *----------------------------------------------------------------------
00083  */
00084 int soar_ecOpenLog(const char *filename, char *mode)
00085 {
00086 
00087     FILE *f;
00088 
00089     f = fopen(filename, mode);
00090 
00091     if (!f) {
00092         return -1;
00093     }
00094 
00095     /* Install callback */
00096     soar_cPushCallback(soar_agent,
00097                        LOG_CALLBACK,
00098                        (soar_callback_fn) cb_soar_PrintToFile, (soar_callback_data) f, (soar_callback_free_fn) fclose);
00099     soar_invoke_first_callback(soar_agent, LOG_CALLBACK, "**** log opened ****\n");
00100 
00101     return 0;
00102 
00103 }
00104 
00105 /*
00106  *----------------------------------------------------------------------
00107  *
00108  * soar_ecCloseLog
00109  *
00110  *       does what it says
00111  *
00112  *----------------------------------------------------------------------
00113  */
00114 int soar_ecCloseLog()
00115 {
00116 
00117     if (soar_exists_callback(soar_agent, LOG_CALLBACK)) {
00118         soar_invoke_first_callback(soar_agent, LOG_CALLBACK, "\n**** log closed ****\n");
00119         soar_cPopCallback(soar_agent, LOG_CALLBACK);
00120 
00121         return 0;
00122     }
00123 
00124     return -1;
00125 
00126 }
00127 
00128 /*
00129  *----------------------------------------------------------------------
00130  *
00131  * soar_ecCaptureInput
00132  *
00133  *       Captures the input sent to the agent during by external
00134  *       calls to add-wme and remove-wme
00135  *----------------------------------------------------------------------
00136  */
00137 #ifdef USE_CAPTURE_REPLAY
00138 int soar_ecCaptureInput(const char *filename)
00139 {
00140 
00141     FILE *f;
00142 
00143     if (filename == NIL) {
00144         /* Trying to close */
00145         if (!current_agent(capture_fileID)) {
00146             return -1;
00147         }
00148         fclose(current_agent(capture_fileID));
00149         current_agent(capture_fileID) = NIL;
00150         return 0;
00151     } else {
00152         if (current_agent(capture_fileID)) {
00153             return -2;
00154         }
00155         f = fopen(filename, "w");
00156         if (!f) {
00157             return -3;
00158         } else {
00159             current_agent(capture_fileID) = f;
00160             fprintf(f, "##soar captured input file.\n");
00161             return 0;
00162         }
00163     }
00164 }
00165 
00166 /*
00167  *----------------------------------------------------------------------
00168  *
00169  * soar_ecReplayInput
00170  *
00171  *       Replays the input previously captured using the CaptureInput 
00172  *       command
00173  *----------------------------------------------------------------------
00174  */
00175 int soar_ecReplayInput(const char *filename)
00176 {
00177 
00178     if (filename == NIL) {
00179         soar_cRemoveInputFunction(soar_agent, "replay-input");
00180 
00181     } else {
00182 
00183         /* Read in the contents of the file... */
00184         long begin, end;
00185         char input[1024];
00186         char id[1024];
00187         char attr[1024];
00188         char value[1024];
00189         int action;
00190         int numargs, cycle;
00191         int hashfreq, lasthash;
00192         unsigned long old_timetag, tt;
00193         int ndc;
00194         captured_action *c_action = NIL;
00195         int last_dc;
00196         int actions_in_dc = 0;
00197         int i;
00198         FILE *f;
00199         char header[80];
00200         soarapi_wme *sapiw;
00201 
00202         f = fopen(filename, "r");
00203         if (!f) {
00204             return -1;
00205         } else {
00206             fgets(header, 28, f);
00207             if (strcmp(header, "##soar captured input file.") != 0) {
00208                 return -2;
00209             }
00210 
00211             /* If we've made it here, things should be ok */
00212 
00213             soar_cAddInputFunction(soar_agent, replay_input_wme, NULL, NULL, "replay-input");
00214 
00215             ndc = -1;
00216             tt = 1;
00217             begin = ftell(f);
00218             while (!feof(f)) {
00219                 numargs = fscanf(f, "%i : %*d : %*s : %ld", &cycle, &old_timetag);
00220                 if (old_timetag > tt)
00221                     tt = old_timetag;
00222                 if (cycle > ndc)
00223                     ndc = cycle;
00224                 fgets(input, 1024, f);
00225             }
00226 
00227             end = ftell(f);     /* Save the location of the end of the file */
00228 
00229             hashfreq = (end - begin) / 10;
00230             lasthash = 0;
00231 
00232             /* print( "Max timetag is %d\n", tt ); */
00233             current_agent(replay_timetags) = (unsigned long *) allocate_memory(tt * sizeof(tt),
00234                                                                                current_agent(memory_for_usage)
00235                                                                                [MISCELLANEOUS_MEM_USAGE]);
00236 
00237             current_agent(dc_to_replay) = ndc;
00238             current_agent(replay_actions) = (captured_action **) allocate_memory(((ndc +
00239                                                                                    1) * sizeof(captured_action *)),
00240                                                                                  current_agent(memory_for_usage)
00241                                                                                  [MISCELLANEOUS_MEM_USAGE]);
00242 
00243             for (i = 0; i < ndc; i++) {
00244                 current_agent(replay_actions)[i] = NULL;
00245             }
00246 
00247             fseek(f, begin, SEEK_SET);
00248 
00249             /* Now fill in the actual actions */
00250             last_dc = -1;
00251             while (!feof(f)) {
00252                 numargs = fscanf(f, "%i : %i : %*s :", &cycle, &action);
00253 
00254                 if (numargs < 2)
00255                     break;
00256 
00257                 begin = ftell(f);       /* get the current position */
00258                 if (begin / hashfreq > lasthash) {
00259                     lasthash = begin / hashfreq;
00260                     print("+");
00261                 }
00262 
00263                 if (cycle != last_dc) {
00264                     current_agent(replay_actions)[cycle] =
00265                         (captured_action *) allocate_memory(sizeof(captured_action),
00266                                                             current_agent(memory_for_usage)[MISCELLANEOUS_MEM_USAGE]);
00267                     c_action = current_agent(replay_actions)[cycle];
00268 
00269                     if (current_agent(soar_verbose_flag) && last_dc != -1) {
00270                         print(" -- (%d actions)\n", actions_in_dc);
00271                     }
00272 
00273                     actions_in_dc = 1;
00274                     last_dc = cycle;
00275                     c_action->next = NULL;
00276 
00277                     if (current_agent(soar_verbose_flag))
00278                         print("Building Actions for Decision Cycle %d\n", cycle);
00279 
00280                 } else {
00281                     c_action->next = (captured_action *)
00282                         allocate_memory(sizeof(captured_action),
00283                                         current_agent(memory_for_usage)[MISCELLANEOUS_MEM_USAGE]);
00284 
00285                     c_action = c_action->next;
00286                     c_action->next = NULL;
00287                     actions_in_dc++;
00288                 }
00289 
00290                 c_action->dc = cycle;
00291                 c_action->action = action;
00292 
00293                 switch (action) {
00294 
00295                 case ADD_WME:
00296                     if (current_agent(soar_verbose_flag))
00297                         print("  -- Reading ADD Wme Action\n");
00298 
00299                     fscanf(f, "%ld : %s %s %s", &old_timetag, id, attr, value);
00300 
00301                     c_action->args = malloc(sizeof(soarapi_wme));
00302                     sapiw = (soarapi_wme *) c_action->args;
00303 
00304                     sapiw->id = savestring(id);
00305                     sapiw->attr = savestring(attr);
00306                     sapiw->value = savestring(value);
00307                     sapiw->timetag = old_timetag;
00308 
00309                     break;
00310 
00311                 case REMOVE_WME:
00312                     if (current_agent(soar_verbose_flag))
00313                         print("  -- Reading REMOVE Wme Action\n");
00314 
00315                     fscanf(f, " : %ld", &old_timetag);
00316                     c_action->args = malloc(sizeof(soarapi_wme));
00317                     ((soarapi_wme *) c_action->args)->timetag = old_timetag;
00318                     break;
00319 
00320                 default:
00321                     print("Warning: don't know what to do with an action type of %d\n", action);
00322                     break;
00323 
00324                 }
00325                 fgets(input, 1025, f);
00326 
00327             }
00328             if (current_agent(soar_verbose_flag))
00329                 print(" -- (%d actions)\n", actions_in_dc);
00330         }
00331         fclose(f);
00332     }
00333     return 0;
00334 }
00335 #endif
00336 
00337 /* REW: begin 09.15.96 */
00338 /*
00339  *----------------------------------------------------------------------
00340  *
00341  * soar_ecGDSPrint --
00342  *
00343  *----------------------------------------------------------------------
00344  */
00345 
00346 void soar_ecGDSPrint()
00347 {
00348     wme *w;
00349     Symbol *goal;
00350 
00351     print("********************* Current GDS **************************\n");
00352     print("stepping thru all wmes in rete, looking for any that are in a gds...\n");
00353     for (w = current_agent(all_wmes_in_rete); w != NIL; w = w->rete_next) {
00354         if (w->gds) {
00355             if (w->gds->goal) {
00356                 print_with_symbols("  For Goal  %y  ", w->gds->goal);
00357             } else {
00358                 print("  Old GDS value ");
00359             }
00360             print("(%lu: ", w->timetag);
00361             print_with_symbols("%y ^%y %y", w->id, w->attr, w->value);
00362             if (w->acceptable)
00363                 print_string(" +");
00364             print_string(")");
00365             print("\n");
00366         }
00367     }
00368     print("************************************************************\n");
00369     for (goal = current_agent(top_goal); goal != NIL; goal = goal->id.lower_goal) {
00370         print_with_symbols("  For Goal  %y  ", goal);
00371         if (goal->id.gds) {
00372             /* Loop over all the WMEs in the GDS */
00373             print("\n");
00374             for (w = goal->id.gds->wmes_in_gds; w != NIL; w = w->gds_next) {
00375                 print("                (%lu: ", w->timetag);
00376                 print_with_symbols("%y ^%y %y", w->id, w->attr, w->value);
00377                 if (w->acceptable)
00378                     print_string(" +");
00379                 print_string(")");
00380                 print("\n");
00381             }
00382 
00383         } else
00384             print(": No GDS for this goal.\n");
00385     }
00386 
00387     print("************************************************************\n");
00388 
00389 }
00390 
00391 /* REW: end   09.15.96 */
00392 
00393 void soar_ecExplainChunkTrace(char *chunk_name)
00394 {
00395 
00396     explain_chunk_str *chunk;
00397 
00398     chunk = find_chunk(current_agent(explain_chunk_list), chunk_name);
00399 /* AGR 564  In previous statement, current_agent(...) was added.  2-May-94 */
00400 
00401     if (chunk)
00402         explain_trace_chunk(chunk);
00403 }
00404 
00405 void soar_ecExplainChunkCondition(char *chunk_name, int cond_number)
00406 {
00407 
00408     explain_chunk_str *chunk;
00409     condition *ground;
00410 
00411     chunk = find_chunk(current_agent(explain_chunk_list), chunk_name);
00412 /* AGR 564  In previous statement, current_agent(...) was added.  2-May-94 */
00413 
00414     if (chunk == NULL)
00415         return;
00416 
00417     ground = find_ground(chunk, cond_number);
00418     if (ground == NIL)
00419         return;
00420 
00421     explain_trace(chunk_name, chunk->backtrace, ground);
00422 }
00423 
00424 void soar_ecExplainChunkConditionList(char *chunk_name)
00425 {
00426 
00427     explain_chunk_str *chunk;
00428     condition *cond, *ground;
00429     int i;
00430 
00431     chunk = find_chunk(current_agent(explain_chunk_list), chunk_name);
00432 /* AGR 564  In previous statement, current_agent(...) was added.  2-May-94 */
00433 
00434     if (chunk == NULL)
00435         return;
00436 
00437     /* First print out the production in "normal" form */
00438 
00439     print("(sp %s\n  ", chunk->name);
00440     print_condition_list(chunk->conds, 2, FALSE);
00441     print("\n-->\n   ");
00442     print_action_list(chunk->actions, 3, FALSE);
00443     print(")\n\n");
00444 
00445     /* Then list each condition and the associated "ground" WME */
00446 
00447     i = 0;
00448     ground = chunk->all_grounds;
00449 
00450     for (cond = chunk->conds; cond != NIL; cond = cond->next) {
00451         i++;
00452         print(" %2d : ", i);
00453         print_condition(cond);
00454         while (get_printer_output_column() < COLUMNS_PER_LINE - 40)
00455             print(" ");
00456 
00457         print(" Ground :");
00458         print_condition(ground);
00459         print("\n");
00460         ground = ground->next;
00461     }
00462 }
00463 
00464 /*
00465  *----------------------------------------------------------------------
00466  *
00467  * soar_ecPrintFiringsForProduction
00468  *
00469  *   Print the number of times the specified production has fired, or
00470  *   "No production named <name>" if the specified production is not
00471  *   defined.
00472  *
00473  *----------------------------------------------------------------------
00474  */
00475 void soar_ecPrintFiringsForProduction(const char *name)
00476 {
00477 
00478     production *p;
00479 
00480     p = name_to_production(name);
00481     if (p) {
00482         print("%6lu:  %s\n", p->firing_count, name);
00483     } else {
00484         print("No production named %s", name);
00485     }
00486 }
00487 
00488 /*
00489  *----------------------------------------------------------------------
00490  *
00491  * soar_ecPrintTopProductionFirings
00492  *
00493  *   Print the top <n> productions with respect to their frequency of
00494  *   firing or "*** No productions defined ***" if no productions are
00495  *   defined.
00496  *----------------------------------------------------------------------
00497  */
00498 void soar_ecPrintTopProductionFirings(int n)
00499 {
00500     int i;
00501     long num_prods;
00502     production *((*all_prods)[]), **ap_item, *p;
00503 
00504     num_prods = current_agent(num_productions_of_type)[DEFAULT_PRODUCTION_TYPE] +
00505         current_agent(num_productions_of_type)[USER_PRODUCTION_TYPE] +
00506         current_agent(num_productions_of_type)[CHUNK_PRODUCTION_TYPE];
00507 
00508     if (num_prods == 0) {
00509         print("*** No productions Defined ***\n");
00510         return;
00511     }
00512 
00513     /* --- make an array of pointers to all the productions --- */
00514     all_prods = allocate_memory(num_prods * sizeof(production *), MISCELLANEOUS_MEM_USAGE);
00515 
00516     /* MVP - 6-8-94 where is it freed ? */
00517 
00518     ap_item = &((*all_prods)[0]);
00519     for (p = current_agent(all_productions_of_type)[DEFAULT_PRODUCTION_TYPE]; p != NIL; p = p->next)
00520         *(ap_item++) = p;
00521     for (p = current_agent(all_productions_of_type)[USER_PRODUCTION_TYPE]; p != NIL; p = p->next)
00522         *(ap_item++) = p;
00523     for (p = current_agent(all_productions_of_type)[CHUNK_PRODUCTION_TYPE]; p != NIL; p = p->next)
00524         *(ap_item++) = p;
00525 
00526     /* --- now print out the results --- */
00527     if (n == 0) {
00528         /* print only the productions that have never fired. */
00529         ap_item = &((*all_prods)[0]);
00530         for (i = 0; i < num_prods; i++) {
00531             if ((*ap_item)->firing_count == 0) {
00532                 print_with_symbols("%y\n", (*ap_item)->name);
00533             }
00534             ap_item++;
00535         }
00536     } else {
00537         /* --- sort array according to firing counts --- */
00538         qsort(all_prods, num_prods, sizeof(production *), compare_firing_counts);
00539 
00540         if ((n < 0) || (n > num_prods)) {
00541             n = num_prods;
00542         }
00543 
00544         ap_item = &((*all_prods)[num_prods - 1]);
00545         while (n) {
00546             print("%6lu:  ", (*ap_item)->firing_count);
00547             print_with_symbols("%y\n", (*ap_item)->name);
00548             ap_item--;
00549             n--;
00550         }
00551     }
00552 
00553     /* MVP 6-8-94 also try this to plug memory leak */
00554     free_memory(all_prods, MISCELLANEOUS_MEM_USAGE);
00555 
00556 }
00557 
00558 void soar_exPrintMemoryPoolStatistics(void)
00559 {
00560     memory_pool *p;
00561 
00562 #ifdef MEMORY_POOL_STATS
00563     long total_items;
00564 #endif
00565 
00566     print("Memory pool statistics:\n\n");
00567 #ifdef MEMORY_POOL_STATS
00568     print("Pool Name        Used Items  Free Items  Item Size  Total Bytes\n");
00569     print("---------------  ----------  ----------  ---------  -----------\n");
00570 #else
00571     print("Pool Name        Item Size  Total Bytes\n");
00572     print("---------------  ---------  -----------\n");
00573 #endif
00574 
00575     for (p = current_agent(memory_pools_in_use); p != NIL; p = p->next) {
00576         print_string(p->name);
00577         print_spaces(MAX_POOL_NAME_LENGTH - strlen(p->name));
00578 #ifdef MEMORY_POOL_STATS
00579         print("  %10lu", p->used_count);
00580         total_items = p->num_blocks * p->items_per_block;
00581         print("  %10lu", total_items - p->used_count);
00582 #endif
00583         print("  %9lu", p->item_size);
00584         print("  %11lu\n", p->num_blocks * p->items_per_block * p->item_size);
00585     }
00586 }
00587 
00588 void soar_ecPrintMemoryStatistics(void)
00589 {
00590     unsigned long total;
00591     int i;
00592 
00593     total = 0;
00594     for (i = 0; i < NUM_MEM_USAGE_CODES; i++)
00595         total += current_agent(memory_for_usage)[i];
00596 
00597     print("%8lu bytes total memory allocated\n", total);
00598     print("%8lu bytes statistics overhead\n", current_agent(memory_for_usage)[STATS_OVERHEAD_MEM_USAGE]);
00599     print("%8lu bytes for strings\n", current_agent(memory_for_usage)[STRING_MEM_USAGE]);
00600     print("%8lu bytes for hash tables\n", current_agent(memory_for_usage)[HASH_TABLE_MEM_USAGE]);
00601     print("%8lu bytes for various memory pools\n", current_agent(memory_for_usage)[POOL_MEM_USAGE]);
00602     print("%8lu bytes for miscellaneous other things\n", current_agent(memory_for_usage)[MISCELLANEOUS_MEM_USAGE]);
00603 }
00604 
00605 void soar_ecPrintReteStatistics(void)
00606 {
00607 
00608 #ifdef TOKEN_SHARING_STATS
00609     print("Token additions: %lu   If no sharing: %lu\n",
00610           current_agent(token_additions), current_agent(token_additions_without_sharing));
00611 #endif
00612 
00613     print_node_count_statistics();
00614     print_null_activation_stats();
00615 }
00616 
00617 void soar_ecPrintSystemStatistics(void)
00618 {
00619 
00620     unsigned long wme_changes;
00621 
00622     /* REW: begin 28.07.96 */
00623 #ifndef NO_TIMING_STUFF
00624     double total_kernel_time, total_kernel_msec, derived_kernel_time, monitors_sum, input_function_time, input_phase_total_time, output_function_time, output_phase_total_time, determine_level_phase_total_time,       /* REW: end   05.05.97 */
00625      preference_phase_total_time, wm_phase_total_time, decision_phase_total_time, derived_total_cpu_time;
00626 
00627 #ifdef DETAILED_TIMING_STATS
00628     double match_time, match_msec;
00629     double ownership_time, chunking_time;
00630     double other_phase_kernel_time[6], other_total_kernel_time;
00631 #endif
00632 #endif
00633     /* REW: end 28.07.96 */
00634 
00635     /* MVP 6-8-94 */
00636     char hostname[MAX_LEXEME_LENGTH + 1];
00637     long current_time;
00638 
00639 #if !defined (THINK_C) && !defined (__SC__) && !defined(MACINTOSH) && !defined(WIN32) && !defined(_WINDOWS)
00640     if (gethostname(hostname, MAX_LEXEME_LENGTH)) {
00641 #endif
00642 
00643         strncpy(hostname, "[host name unknown]", MAX_LEXEME_LENGTH + 1);
00644         hostname[MAX_LEXEME_LENGTH] = 0;
00645 
00646 #if !defined (THINK_C) && !defined (__SC__) && !defined(MACINTOSH) && !defined(WIN32) && !defined(_WINDOWS)
00647     }
00648 #endif
00649 
00650     current_time = time(NULL);
00651 
00652 /* REW: begin 28.07.96 */
00653 /* See note in soarkernel.h for a description of the timers */
00654 #ifndef NO_TIMING_STUFF
00655     total_kernel_time = timer_value(&current_agent(total_kernel_time));
00656     total_kernel_msec = total_kernel_time * 1000.0;
00657 
00658     /* derived_kernel_time := Total of the time spent in the phases of the decision cycle, 
00659        excluding Input Function, Output function, and pre-defined callbacks. 
00660        This computed time should be roughly equal to total_kernel_time, 
00661        as determined above. */
00662 
00663 #ifndef KERNEL_TIME_ONLY
00664     derived_kernel_time = timer_value(&current_agent(decision_cycle_phase_timers[INPUT_PHASE]))
00665         + timer_value(&current_agent(decision_cycle_phase_timers[DETERMINE_LEVEL_PHASE]))
00666         + timer_value(&current_agent(decision_cycle_phase_timers[PREFERENCE_PHASE]))
00667         + timer_value(&current_agent(decision_cycle_phase_timers[WM_PHASE]))
00668         + timer_value(&current_agent(decision_cycle_phase_timers[OUTPUT_PHASE]))
00669         + timer_value(&current_agent(decision_cycle_phase_timers[DECISION_PHASE]));
00670 
00671     input_function_time = timer_value(&current_agent(input_function_cpu_time));
00672 
00673     output_function_time = timer_value(&current_agent(output_function_cpu_time));
00674 
00675     /* Total of the time spent in callback routines. */
00676     monitors_sum = timer_value(&current_agent(monitors_cpu_time[INPUT_PHASE]))
00677         + timer_value(&current_agent(monitors_cpu_time[DETERMINE_LEVEL_PHASE]))
00678         + timer_value(&current_agent(monitors_cpu_time[PREFERENCE_PHASE]))
00679         + timer_value(&current_agent(monitors_cpu_time[WM_PHASE]))
00680         + timer_value(&current_agent(monitors_cpu_time[OUTPUT_PHASE]))
00681         + timer_value(&current_agent(monitors_cpu_time[DECISION_PHASE]));
00682 
00683     derived_total_cpu_time = derived_kernel_time + monitors_sum + input_function_time + output_function_time;
00684 
00685     /* Total time spent in the input phase */
00686     input_phase_total_time = timer_value(&current_agent(decision_cycle_phase_timers[INPUT_PHASE]))
00687         + timer_value(&current_agent(monitors_cpu_time[INPUT_PHASE]))
00688         + timer_value(&current_agent(input_function_cpu_time));
00689 
00690     /* REW: begin 10.30.97 */
00691     determine_level_phase_total_time = timer_value(&current_agent(decision_cycle_phase_timers[DETERMINE_LEVEL_PHASE]))
00692         + timer_value(&current_agent(monitors_cpu_time[DETERMINE_LEVEL_PHASE]));
00693     /* REW: end   10.30.97 */
00694 
00695     /* Total time spent in the preference phase */
00696     preference_phase_total_time = timer_value(&current_agent(decision_cycle_phase_timers[PREFERENCE_PHASE]))
00697         + timer_value(&current_agent(monitors_cpu_time[PREFERENCE_PHASE]));
00698 
00699     /* Total time spent in the working memory phase */
00700     wm_phase_total_time = timer_value(&current_agent(decision_cycle_phase_timers[WM_PHASE]))
00701         + timer_value(&current_agent(monitors_cpu_time[WM_PHASE]));
00702 
00703     /* Total time spent in the output phase */
00704     output_phase_total_time = timer_value(&current_agent(decision_cycle_phase_timers[OUTPUT_PHASE]))
00705         + timer_value(&current_agent(monitors_cpu_time[OUTPUT_PHASE]))
00706         + timer_value(&current_agent(output_function_cpu_time));
00707 
00708     /* Total time spent in the decision phase */
00709     decision_phase_total_time = timer_value(&current_agent(decision_cycle_phase_timers[DECISION_PHASE]))
00710         + timer_value(&current_agent(monitors_cpu_time[DECISION_PHASE]));
00711 
00712     /* The sum of these six phase timers is exactly equal to the 
00713      * derived_total_cpu_time
00714      */
00715 
00716 #ifdef DETAILED_TIMING_STATS
00717 
00718     match_time = timer_value(&current_agent(match_cpu_time[INPUT_PHASE]))
00719         + timer_value(&current_agent(match_cpu_time[DETERMINE_LEVEL_PHASE]))
00720         + timer_value(&current_agent(match_cpu_time[PREFERENCE_PHASE]))
00721         + timer_value(&current_agent(match_cpu_time[WM_PHASE]))
00722         + timer_value(&current_agent(match_cpu_time[OUTPUT_PHASE]))
00723         + timer_value(&current_agent(match_cpu_time[DECISION_PHASE]));
00724 
00725     match_msec = 1000 * match_time;
00726 
00727     ownership_time = timer_value(&current_agent(ownership_cpu_time[INPUT_PHASE]))
00728         + timer_value(&current_agent(ownership_cpu_time[DETERMINE_LEVEL_PHASE]))
00729         + timer_value(&current_agent(ownership_cpu_time[PREFERENCE_PHASE]))
00730         + timer_value(&current_agent(ownership_cpu_time[WM_PHASE]))
00731         + timer_value(&current_agent(ownership_cpu_time[OUTPUT_PHASE]))
00732         + timer_value(&current_agent(ownership_cpu_time[DECISION_PHASE]));
00733 
00734     chunking_time = timer_value(&current_agent(chunking_cpu_time[INPUT_PHASE]))
00735         + timer_value(&current_agent(chunking_cpu_time[DETERMINE_LEVEL_PHASE]))
00736         + timer_value(&current_agent(chunking_cpu_time[PREFERENCE_PHASE]))
00737         + timer_value(&current_agent(chunking_cpu_time[WM_PHASE]))
00738         + timer_value(&current_agent(chunking_cpu_time[OUTPUT_PHASE]))
00739         + timer_value(&current_agent(chunking_cpu_time[DECISION_PHASE]));
00740 
00741     /* O-support time should go to 0 with o-support-mode 2 */
00742     /* o_support_time = 
00743        timer_value (&current_agent(o_support_cpu_time[INPUT_PHASE])) 
00744        + timer_value (&current_agent(o_support_cpu_time[DETERMINE_LEVEL_PHASE])) 
00745        + timer_value (&current_agent(o_support_cpu_time[PREFERENCE_PHASE])) 
00746        + timer_value (&current_agent(o_support_cpu_time[WM_PHASE])) 
00747        + timer_value (&current_agent(o_support_cpu_time[OUTPUT_PHASE])) 
00748        + timer_value (&current_agent(o_support_cpu_time[DECISION_PHASE])); */
00749 
00750     other_phase_kernel_time[INPUT_PHASE] = timer_value(&current_agent(decision_cycle_phase_timers[INPUT_PHASE]))
00751         - timer_value(&current_agent(match_cpu_time[INPUT_PHASE]))
00752         - timer_value(&current_agent(ownership_cpu_time[INPUT_PHASE]))
00753         - timer_value(&current_agent(chunking_cpu_time[INPUT_PHASE]));
00754 
00755     other_phase_kernel_time[DETERMINE_LEVEL_PHASE] =
00756         timer_value(&current_agent(decision_cycle_phase_timers[DETERMINE_LEVEL_PHASE]))
00757         - timer_value(&current_agent(match_cpu_time[DETERMINE_LEVEL_PHASE]))
00758         - timer_value(&current_agent(ownership_cpu_time[DETERMINE_LEVEL_PHASE]))
00759         - timer_value(&current_agent(chunking_cpu_time[DETERMINE_LEVEL_PHASE]));
00760 
00761     other_phase_kernel_time[PREFERENCE_PHASE] =
00762         timer_value(&current_agent(decision_cycle_phase_timers[PREFERENCE_PHASE]))
00763         - timer_value(&current_agent(match_cpu_time[PREFERENCE_PHASE]))
00764         - timer_value(&current_agent(ownership_cpu_time[PREFERENCE_PHASE]))
00765         - timer_value(&current_agent(chunking_cpu_time[PREFERENCE_PHASE]));
00766 
00767     other_phase_kernel_time[WM_PHASE] = timer_value(&current_agent(decision_cycle_phase_timers[WM_PHASE]))
00768         - timer_value(&current_agent(match_cpu_time[WM_PHASE]))
00769         - timer_value(&current_agent(ownership_cpu_time[WM_PHASE]))
00770         - timer_value(&current_agent(chunking_cpu_time[WM_PHASE]));
00771 
00772     other_phase_kernel_time[OUTPUT_PHASE] = timer_value(&current_agent(decision_cycle_phase_timers[OUTPUT_PHASE]))
00773         - timer_value(&current_agent(match_cpu_time[OUTPUT_PHASE]))
00774         - timer_value(&current_agent(ownership_cpu_time[OUTPUT_PHASE]))
00775         - timer_value(&current_agent(chunking_cpu_time[OUTPUT_PHASE]));
00776 
00777     other_phase_kernel_time[DECISION_PHASE] = timer_value(&current_agent(decision_cycle_phase_timers[DECISION_PHASE]))
00778         - timer_value(&current_agent(match_cpu_time[DECISION_PHASE]))
00779         - timer_value(&current_agent(ownership_cpu_time[DECISION_PHASE]))
00780         - timer_value(&current_agent(chunking_cpu_time[DECISION_PHASE]));
00781 
00782     other_total_kernel_time = other_phase_kernel_time[INPUT_PHASE]
00783         + other_phase_kernel_time[DETERMINE_LEVEL_PHASE]
00784         + other_phase_kernel_time[PREFERENCE_PHASE]
00785         + other_phase_kernel_time[WM_PHASE]
00786         + other_phase_kernel_time[OUTPUT_PHASE]
00787         + other_phase_kernel_time[DECISION_PHASE];
00788 
00789 #endif
00790 #endif
00791 #endif
00792 /* REW: end 28.07.96 */
00793 
00794     print("Soar %s on %s at %s\n", soar_version_string, hostname, ctime((const time_t *) &current_time));
00795 
00796     print("%lu productions (%lu default, %lu user, %lu chunks)\n",
00797           current_agent(num_productions_of_type)[DEFAULT_PRODUCTION_TYPE] +
00798           current_agent(num_productions_of_type)[USER_PRODUCTION_TYPE] +
00799           current_agent(num_productions_of_type)[CHUNK_PRODUCTION_TYPE],
00800           current_agent(num_productions_of_type)[DEFAULT_PRODUCTION_TYPE],
00801           current_agent(num_productions_of_type)[USER_PRODUCTION_TYPE],
00802           current_agent(num_productions_of_type)[CHUNK_PRODUCTION_TYPE]);
00803     print("   + %lu justifications\n", current_agent(num_productions_of_type)[JUSTIFICATION_PRODUCTION_TYPE]);
00804 
00805     /* REW: begin 28.07.96 */
00806 #ifndef NO_TIMING_STUFF
00807     /* The fields for the timers are 8.3, providing an upper limit of 
00808        approximately 2.5 hours the printing of the run time calculations.  
00809        Obviously, these will need to be increased if you plan on needing 
00810        run-time data for a process that you expect to take longer than 
00811        2 hours. :) */
00812 
00813 #ifndef KERNEL_TIME_ONLY
00814     print("                                                                |    Derived\n");
00815     print("Phases:      Input      DLP     Pref      W/M   Output Decision |     Totals\n");
00816     print("================================================================|===========\n");
00817 
00818     print("Kernel:   %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f | %10.3f\n",
00819           timer_value(&current_agent(decision_cycle_phase_timers[INPUT_PHASE])),
00820           timer_value(&current_agent(decision_cycle_phase_timers[DETERMINE_LEVEL_PHASE])),
00821           timer_value(&current_agent(decision_cycle_phase_timers[PREFERENCE_PHASE])),
00822           timer_value(&current_agent(decision_cycle_phase_timers[WM_PHASE])),
00823           timer_value(&current_agent(decision_cycle_phase_timers[OUTPUT_PHASE])),
00824           timer_value(&current_agent(decision_cycle_phase_timers[DECISION_PHASE])), derived_kernel_time);
00825 
00826 #ifdef DETAILED_TIMING_STATS
00827 
00828     print("====================  Detailed Timing Statistics  ==============|===========\n");
00829 
00830     print("   Match: %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f | %10.3f\n",
00831           timer_value(&current_agent(match_cpu_time[INPUT_PHASE])),
00832           timer_value(&current_agent(match_cpu_time[DETERMINE_LEVEL_PHASE])),
00833           timer_value(&current_agent(match_cpu_time[PREFERENCE_PHASE])),
00834           timer_value(&current_agent(match_cpu_time[WM_PHASE])),
00835           timer_value(&current_agent(match_cpu_time[OUTPUT_PHASE])),
00836           timer_value(&current_agent(match_cpu_time[DECISION_PHASE])), match_time);
00837 
00838     print("Own'ship: %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f | %10.3f\n",
00839           timer_value(&current_agent(ownership_cpu_time[INPUT_PHASE])),
00840           timer_value(&current_agent(ownership_cpu_time[DETERMINE_LEVEL_PHASE])),
00841           timer_value(&current_agent(ownership_cpu_time[PREFERENCE_PHASE])),
00842           timer_value(&current_agent(ownership_cpu_time[WM_PHASE])),
00843           timer_value(&current_agent(ownership_cpu_time[OUTPUT_PHASE])),
00844           timer_value(&current_agent(ownership_cpu_time[DECISION_PHASE])), ownership_time);
00845 
00846     print("Chunking: %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f | %10.3f\n",
00847           timer_value(&current_agent(chunking_cpu_time[INPUT_PHASE])),
00848           timer_value(&current_agent(chunking_cpu_time[DETERMINE_LEVEL_PHASE])),
00849           timer_value(&current_agent(chunking_cpu_time[PREFERENCE_PHASE])),
00850           timer_value(&current_agent(chunking_cpu_time[WM_PHASE])),
00851           timer_value(&current_agent(chunking_cpu_time[OUTPUT_PHASE])),
00852           timer_value(&current_agent(chunking_cpu_time[DECISION_PHASE])), chunking_time);
00853 
00854     print("   Other: %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f | %10.3f\n",
00855           other_phase_kernel_time[INPUT_PHASE],
00856           other_phase_kernel_time[DETERMINE_LEVEL_PHASE],
00857           other_phase_kernel_time[PREFERENCE_PHASE],
00858           other_phase_kernel_time[WM_PHASE],
00859           other_phase_kernel_time[OUTPUT_PHASE], other_phase_kernel_time[DECISION_PHASE], other_total_kernel_time);
00860 
00861     /* REW: begin 11.25.96 */
00862     print("Operand2: %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f | %10.3f\n",
00863           timer_value(&current_agent(gds_cpu_time[INPUT_PHASE])),
00864           timer_value(&current_agent(gds_cpu_time[DETERMINE_LEVEL_PHASE])),
00865           timer_value(&current_agent(gds_cpu_time[PREFERENCE_PHASE])),
00866           timer_value(&current_agent(gds_cpu_time[WM_PHASE])),
00867           timer_value(&current_agent(gds_cpu_time[OUTPUT_PHASE])),
00868           timer_value(&current_agent(gds_cpu_time[DECISION_PHASE])),
00869           timer_value(&current_agent(gds_cpu_time[INPUT_PHASE])) +
00870           timer_value(&current_agent(gds_cpu_time[DETERMINE_LEVEL_PHASE])) +
00871           timer_value(&current_agent(gds_cpu_time[PREFERENCE_PHASE])) +
00872           timer_value(&current_agent(gds_cpu_time[WM_PHASE])) +
00873           timer_value(&current_agent(gds_cpu_time[OUTPUT_PHASE])) +
00874           timer_value(&current_agent(gds_cpu_time[DECISION_PHASE])));
00875 
00876     /* REW: end   11.25.96 */
00877 
00878 #endif
00879 
00880     print("================================================================|===========\n");
00881     print("Input fn: %8.3f                                              | %10.3f\n",
00882           input_function_time, input_function_time);
00883 
00884     print("================================================================|===========\n");
00885     print("Outpt fn:                                     %8.3f          | %10.3f\n",
00886           output_function_time, output_function_time);
00887 
00888     print("================================================================|===========\n");
00889     print("Callbcks: %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f | %10.3f\n",
00890           timer_value(&current_agent(monitors_cpu_time[INPUT_PHASE])),
00891           timer_value(&current_agent(monitors_cpu_time[DETERMINE_LEVEL_PHASE])),
00892           timer_value(&current_agent(monitors_cpu_time[PREFERENCE_PHASE])),
00893           timer_value(&current_agent(monitors_cpu_time[WM_PHASE])),
00894           timer_value(&current_agent(monitors_cpu_time[OUTPUT_PHASE])),
00895           timer_value(&current_agent(monitors_cpu_time[DECISION_PHASE])), monitors_sum);
00896 
00897     print("================================================================|===========\n");
00898     print("Derived---------------------------------------------------------+-----------\n");
00899     print("Totals:   %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f | %10.3f\n\n",
00900           input_phase_total_time,
00901           determine_level_phase_total_time,
00902           preference_phase_total_time,
00903           wm_phase_total_time, output_phase_total_time, decision_phase_total_time, derived_total_cpu_time);
00904 
00905     if (!current_agent(stop_soar)) {
00906         /* Soar is still running, so this must have been invoked
00907          * from the RHS, therefore these timers need to be updated. */
00908         stop_timer(&current_agent(start_total_tv), &current_agent(total_cpu_time));
00909         stop_timer(&current_agent(start_kernel_tv), &current_agent(total_kernel_time));
00910         start_timer(&current_agent(start_total_tv));
00911         start_timer(&current_agent(start_kernel_tv));
00912     }
00913 
00914     print("Values from single timers:\n");
00915 #endif
00916 #endif
00917 #ifndef NO_TIMING_STUFF
00918 
00919 #ifdef WARN_IF_TIMERS_REPORT_ZERO
00920     /* If a warning has occured since the last init-soar, the warn flag will
00921      * have been set to FALSE, so such a warning is not spammed to the screen
00922      * But lets repeat it here.
00923      */
00924     if (!current_agent(warn_on_zero_timers))
00925         print(" Warning: one or more timers have reported zero during this run\n");
00926 #endif
00927 
00928 #ifndef PII_TIMERS
00929     print(" Kernel CPU Time: %11.3f sec. \n", total_kernel_time);
00930     print(" Total  CPU Time: %11.3f sec.\n\n", timer_value(&current_agent(total_cpu_time)));
00931 #else
00932     print(" Using PII Timers ... Assuming Processor Speed of %d MHZ\n", MHZ);
00933     print(" Kernel CPU Time: %11.5f sec. \n", total_kernel_time);
00934     print(" Total  CPU Time: %11.5f sec.\n\n", timer_value(&current_agent(total_cpu_time)));
00935 
00936 #endif
00937 
00938 #ifdef COUNT_KERNEL_TIMER_STOPS
00939     print(" Kernel CPU Timer Stops: %d\n", current_agent(kernelTimerStops));
00940     print(" Non-Kernel Timer Stops: %d\n", current_agent(nonKernelTimerStops));
00941 
00942 #endif
00943 #endif
00944 
00945 #if !defined(NO_TIMING_STUFF)
00946     print("%lu decision cycles (%.3f msec/dc)\n",
00947           current_agent(d_cycle_count),
00948           current_agent(d_cycle_count) ? total_kernel_msec / current_agent(d_cycle_count) : 0.0);
00949     print("%lu elaboration cycles (%.3f ec's per dc, %.3f msec/ec)\n",
00950           current_agent(e_cycle_count),
00951           current_agent(d_cycle_count) ? (double) current_agent(e_cycle_count) / current_agent(d_cycle_count) : 0,
00952           current_agent(e_cycle_count) ? total_kernel_msec / current_agent(e_cycle_count) : 0);
00953     /* REW: begin 09.15.96 */
00954 
00955 #ifndef SOAR_8_ONLY
00956     if (current_agent(operand2_mode))
00957 #endif
00958         print("%lu p-elaboration cycles (%.3f pe's per dc, %.3f msec/pe)\n",
00959               current_agent(pe_cycle_count),
00960               current_agent(d_cycle_count) ? (double) current_agent(pe_cycle_count) / current_agent(d_cycle_count) : 0,
00961               current_agent(pe_cycle_count) ? total_kernel_msec / current_agent(pe_cycle_count) : 0);
00962     /* REW: end 09.15.96 */
00963     print("%lu production firings (%.3f pf's per ec, %.3f msec/pf)\n",
00964           current_agent(production_firing_count),
00965           current_agent(e_cycle_count) ? (double) current_agent(production_firing_count) /
00966           current_agent(e_cycle_count) : 0.0,
00967           current_agent(production_firing_count) ? total_kernel_msec / current_agent(production_firing_count) : 0.0);
00968 
00969 #else
00970     print("%lu decision cycles\n", current_agent(d_cycle_count));
00971     print("%lu elaboration cycles \n", current_agent(e_cycle_count));
00972     print("%lu production firings \n", current_agent(production_firing_count));
00973 #endif                          /* !NO_TIMING_STUFF */
00974 
00975     wme_changes = current_agent(wme_addition_count) + current_agent(wme_removal_count);
00976     print("%lu wme changes (%lu additions, %lu removals)\n",
00977           wme_changes, current_agent(wme_addition_count), current_agent(wme_removal_count));
00978 #ifdef DETAILED_TIMING_STATS
00979     print("    match time: %.3f msec/wm change\n", wme_changes ? match_msec / wme_changes : 0.0);
00980 #endif
00981 
00982     print("WM size: %lu current, %.3f mean, %lu maximum\n",
00983           current_agent(num_wmes_in_rete),
00984           (current_agent(num_wm_sizes_accumulated) ?
00985            (current_agent(cumulative_wm_size) / current_agent(num_wm_sizes_accumulated)) :
00986            0.0), current_agent(max_wm_size));
00987 
00988 #ifndef NO_TIMING_STUFF
00989     print("\n");
00990     print("    *** Time/<x> statistics use the total kernel time from a ***\n");
00991     print("    *** single kernel timer.  Differences between this value ***\n");
00992     print("    *** and the derived total kernel time  are expected. See ***\n");
00993     print("    *** help  for the  stats command  for more  information. ***\n");
00994 #endif
00995     /* REW: end 28.07.96 */
00996 }
00997 
00998 #ifdef DC_HISTOGRAM
00999 /*
01000  *----------------------------------------------------------------------
01001  *
01002  * soar_ecPrintDCHistogram
01003  *
01004  *      This procedure prints the timing of decision cycles
01005  *
01006  * Results:
01007  *      Soar status code.
01008  *
01009  * Side effects:
01010  *
01011  *----------------------------------------------------------------------
01012  */
01013 int soar_ecPrintDCHistogram(void)
01014 {
01015 
01016     double total_k_time;
01017     int i, end;
01018 
01019     total_k_time = 0;
01020     end = current_agent(d_cycle_count) / current_agent(dc_histogram_freq);
01021     if (end > current_agent(dc_histogram_sz))
01022         end = current_agent(dc_histogram_sz);
01023 
01024     print("------------- D.C. Histogram --------------\n");
01025     print("Each Bucket encapsulates %d decision cycles\n", current_agent(dc_histogram_freq));
01026     print("%d Buckets have been filled during %d decision cycles\n", end, current_agent(d_cycle_count));
01027     print("-------------------------------------------\n");
01028     print("Bucket\t1st DC\tTime\n");
01029     for (i = 0; i < end; i++) {
01030 
01031         print("%d\t%d\t%8.5f\n", i, i * current_agent(dc_histogram_freq),
01032               timer_value(&current_agent(dc_histogram_tv)[i]));
01033 
01034         total_k_time += timer_value(&current_agent(dc_histogram_tv)[i]);
01035     }
01036     print("Total Time In Buckets:\t%8.5f\n", total_k_time);
01037 
01038     return SOAR_OK;
01039 }
01040 #endif
01041 
01042 #ifdef KT_HISTOGRAM
01043 /*
01044  *----------------------------------------------------------------------
01045  *
01046  * soar_ecPrintKTHistogram
01047  *
01048  *      This procedure prints the timing of decision cycles
01049  *
01050  * Results:
01051  *      Soar status code.
01052  *
01053  * Side effects:
01054  *
01055  *----------------------------------------------------------------------
01056  */
01057 int soar_ecPrintKTHistogram(void)
01058 {
01059     double total_k_time;
01060     int i, end;
01061 
01062     total_k_time = 0;
01063     end = current_agent(d_cycle_count);
01064     if (end > current_agent(dc_histogram_sz))
01065         end = current_agent(dc_histogram_sz);
01066 
01067     print("------------- K.T. Histogram --------------\n");
01068 
01069     print("Bucket\tTime\n");
01070     for (i = 0; i < end; i++) {
01071 
01072         print("%d\t%8.5f\n", i, timer_value(&current_agent(kt_histogram_tv)[i]));
01073 
01074         total_k_time += timer_value(&current_agent(kt_histogram_tv)[i]);
01075     }
01076     print("Total Time In Buckets:\t%8.5f\n", total_k_time);
01077 
01078     return SOAR_OK;
01079 }
01080 #endif
01081 
01082 void soar_ecPrintMemories(int num_to_print, int to_print[])
01083 {
01084     int i, num_prods;
01085     production_memory_use *temp, *first, *tempnext;
01086     production *prod;
01087     production_memory_use *print_memories_insert_in_list();
01088 
01089     print("\nMemory use for productions:\n\n");
01090 
01091     /* Start by doing ALL of them. */
01092     first = NULL;
01093     num_prods = 0;
01094 
01095     for (i = 0; i < NUM_PRODUCTION_TYPES; i++)
01096         if (to_print[i])
01097             for (prod = current_agent(all_productions_of_type)[i]; prod != NIL; prod = prod->next) {
01098                 temp = allocate_memory(sizeof(production_memory_use), MISCELLANEOUS_MEM_USAGE);
01099                 temp->next = NULL;
01100                 temp->name = prod->name;
01101 
01102                 temp->mem = count_rete_tokens_for_production(prod);
01103 
01104                 first = print_memories_insert_in_list(temp, first);
01105                 num_prods++;
01106             }
01107 
01108     i = 0;
01109     if (num_to_print < 0)
01110         num_to_print = num_prods;
01111 
01112     for (temp = first; ((temp != NULL) && (i < num_to_print)); temp = tempnext) {
01113         print_with_symbols("%y: ", temp->name);
01114         print("%d\n", temp->mem);
01115         tempnext = temp->next;
01116         free_memory(temp, MISCELLANEOUS_MEM_USAGE);
01117         i++;
01118     }
01119 }
01120 
01121 int soar_ecPrintAllProductionsOfType(int type, bool internal, bool print_fname, bool full_prod)
01122 {
01123 
01124     production *prod;
01125 
01126     /* we'll step through the list backwards, so chunks and justifications
01127      * are displayed in reverse cronological order.
01128      */
01129 
01130     if (type < 0 || type >= NUM_PRODUCTION_TYPES) {
01131         return -1;
01132     }
01133 
01134     for (prod = current_agent(all_productions_of_type)[type]; prod != NIL && prod->next != NIL; prod = prod->next)
01135         /* intentionally null */ ;
01136 
01137     while (prod != NIL) {
01138         /* Print it... */
01139         if (!full_prod) {
01140             print_with_symbols("%y  ", prod->name);
01141         }
01142         if (print_fname) {
01143             print_string("# sourcefile : ");
01144             if (prod->filename) {
01145                 print_string(prod->filename);
01146             } else {
01147                 print_string(" _unknown_ ");
01148             }
01149         }
01150         print("\n");
01151         if (full_prod) {
01152             print_production(prod, internal);
01153             print("\n");
01154         }
01155         prod = prod->prev;
01156     }
01157 
01158     return 0;
01159 }
01160 
01161 void soar_ecPrintAllProductionsWithInterruptSetting(enum soar_InterruptSetting interrupt_setting) {
01162     production *prod;
01163 
01164     /* we'll step through the list backwards, so chunks and justifications
01165      * are displayed in reverse cronological order.
01166      */
01167 
01168     int type;
01169     for (type = 0; type < NUM_PRODUCTION_TYPES; type++) {
01170         for (prod = current_agent(all_productions_of_type)[type]; prod != NIL && prod->next != NIL; prod = prod->next)
01171             /* intentionally null */ ;
01172 
01173         while (prod != NIL) {
01174             /* Print it... */
01175 
01176             if( (interrupt_setting == INTERRUPT_ON && prod->interrupt) || (interrupt_setting == INTERRUPT_OFF && !prod->interrupt) ) {
01177                 print("%s\n", prod->name->var.name);
01178             }
01179         
01180             prod = prod->prev;
01181         }
01182     }
01183 }
01184 
01185 int soar_ecAddWmeFilter(const char *szId, const char *szAttr, const char *szValue, bool adds, bool removes)
01186 {
01187 
01188     Symbol *id, *attr, *value;
01189     wme_filter *wf, *existing_wf;
01190     cons *c;
01191     int return_value;
01192 
01193     id = NIL;
01194     attr = NIL;
01195     value = NIL;
01196     return_value = 0;
01197 
01198     if (read_wme_filter_component(szId, &id)) {
01199         return_value = -1;
01200         goto error_out;
01201     }
01202     if (read_wme_filter_component(szAttr, &attr)) {
01203         return_value = -2;
01204         goto error_out;
01205     }
01206     if (read_wme_filter_component(szValue, &value)) {
01207         return_value = -3;
01208         goto error_out;
01209     }
01210 
01211     if (id && attr && value) {
01212         /* check to see if such a filter has already been added: */
01213         for (c = current_agent(wme_filter_list); c != NIL; c = c->rest) {
01214             existing_wf = (wme_filter *) c->first;
01215             if ((existing_wf->adds == adds) && (existing_wf->removes == removes)
01216                 && (existing_wf->id == id) && (existing_wf->attr == attr)
01217                 && (existing_wf->value == value)) {
01218 
01219                 print("Filter already exists.\n");
01220                 return_value = -4;
01221                 goto error_out; /* already exists */
01222             }
01223         }
01224 
01225         wf = allocate_memory(sizeof(wme_filter), MISCELLANEOUS_MEM_USAGE);
01226         wf->id = id;
01227         wf->attr = attr;
01228         wf->value = value;
01229         wf->adds = adds;
01230         wf->removes = removes;
01231 
01232         /* Rather than add refs for the new filter symbols and then remove refs 
01233          * for the identical symbols created from the string parameters, skip
01234          * the two nullifying steps altogether and just return immediately
01235          * after pushing the new filter:
01236          */
01237         push(wf, current_agent(wme_filter_list));       /* note: nested macro */
01238         return 0;
01239     }
01240   error_out:
01241     /* clean up symbols created from string parameters */
01242     if (id)
01243         symbol_remove_ref(id);
01244     if (attr)
01245         symbol_remove_ref(attr);
01246     if (value)
01247         symbol_remove_ref(value);
01248     return return_value;
01249 }
01250 
01251 int soar_ecRemoveWmeFilter(const char *szId, const char *szAttr, const char *szValue, bool adds, bool removes)
01252 {
01253     Symbol *id, *attr, *value;
01254     wme_filter *wf;
01255     int return_value = -4;
01256     cons *c;
01257     cons **prev_cons_rest;
01258 
01259     id = NIL;
01260     attr = NIL;
01261     value = NIL;
01262 
01263     if (read_wme_filter_component(szId, &id)) {
01264         return_value = -1;
01265         goto clean_up;
01266     }
01267     if (read_wme_filter_component(szAttr, &attr)) {
01268         return_value = -2;
01269         goto clean_up;
01270     }
01271     if (read_wme_filter_component(szValue, &value)) {
01272         return_value = -3;
01273         goto clean_up;
01274     }
01275 
01276     if (id && attr && value) {
01277         prev_cons_rest = &current_agent(wme_filter_list);
01278         for (c = current_agent(wme_filter_list); c != NIL; c = c->rest) {
01279             wf = (wme_filter *) c->first;
01280             if (((adds && wf->adds) || ((removes) && wf->removes))
01281                 && (wf->id == id) && (wf->attr == attr) && (wf->value == value)) {
01282                 *prev_cons_rest = c->rest;
01283                 symbol_remove_ref(id);
01284                 symbol_remove_ref(attr);
01285                 symbol_remove_ref(value);
01286                 free_memory(wf, MISCELLANEOUS_MEM_USAGE);
01287                 free_cons(c);
01288                 break;          /* assume that soar_ecAddWmeFilter did not add duplicates */
01289             }
01290             prev_cons_rest = &(c->rest);
01291         }
01292         if (c != NIL)
01293             return_value = 0;   /* filter was sucessfully removed */
01294     }
01295 
01296   clean_up:
01297     /* clean up symbols created from string parameters */
01298     if (id)
01299         symbol_remove_ref(id);
01300     if (attr)
01301         symbol_remove_ref(attr);
01302     if (value)
01303         symbol_remove_ref(value);
01304     return return_value;
01305 }
01306 
01307 int soar_ecResetWmeFilters(bool adds, bool removes)
01308 {
01309     wme_filter *wf;
01310     cons *c;
01311     cons **prev_cons_rest;
01312     bool didRemoveSome;
01313 
01314     didRemoveSome = FALSE;
01315     prev_cons_rest = &current_agent(wme_filter_list);
01316     for (c = current_agent(wme_filter_list); c != NIL; c = c->rest) {
01317         wf = (wme_filter *) c->first;
01318         if ((adds && wf->adds) || (removes && wf->removes)) {
01319             *prev_cons_rest = c->rest;
01320             print_with_symbols("Removed: (%y ^%y %y) ", wf->id, wf->attr, wf->value);
01321             print("%s %s\n", (wf->adds ? "adds" : ""), (wf->removes ? "removes" : ""));
01322             symbol_remove_ref(wf->id);
01323             symbol_remove_ref(wf->attr);
01324             symbol_remove_ref(wf->value);
01325             free_memory(wf, MISCELLANEOUS_MEM_USAGE);
01326             free_cons(c);
01327             didRemoveSome = TRUE;
01328         }
01329         prev_cons_rest = &(c->rest);
01330     }
01331     if (didRemoveSome)
01332         return 0;
01333     else
01334         return -1;
01335 }
01336 
01337 void soar_ecListWmeFilters(bool adds, bool removes)
01338 {
01339     wme_filter *wf;
01340     cons *c;
01341 
01342     for (c = current_agent(wme_filter_list); c != NIL; c = c->rest) {
01343         wf = (wme_filter *) c->first;
01344         if ((adds && wf->adds) || (removes && wf->removes)) {
01345             print_with_symbols("wme filter: (%y ^%y %y) ", wf->id, wf->attr, wf->value);
01346 
01347             print("%s %s\n", (wf->adds ? "adds" : ""), (wf->removes ? "removes" : ""));
01348         }
01349     }
01350 }
01351 
01352 int soar_ecSp(const char *rule, const char *sourceFile)
01353 {
01354 
01355     production *p;
01356 
01357     /* Use a callback instead? */
01358     /* ((agent *)clientData)->alternate_input_string = argv[1];
01359      * ((agent *)clientData)->alternate_input_suffix = ") ";
01360      *//* Soar-Bugs #54 TMH */
01361     soar_alternate_input(soar_agent, rule, ") ", TRUE);
01362     set_lexer_allow_ids(FALSE);
01363     get_lexeme();
01364     p = parse_production();
01365     set_lexer_allow_ids(TRUE);
01366     soar_alternate_input(soar_agent, NIL, NIL, FALSE);
01367 
01368     if (p) {
01369 
01370         if (sourceFile != NULL) {
01371             p->filename = make_memory_block_for_string(sourceFile);
01372         }
01373 
01374         if (current_agent(sysparams)[TRACE_LOADING_SYSPARAM])
01375             print("*");
01376 
01377         /* kjh CUSP(B14) begin */
01378         if (p->type == CHUNK_PRODUCTION_TYPE) {
01379 
01380             /* Extract chunk_count from chunk name.
01381              * It will always be the number before the first '*' or '\0' 
01382              * and after a '-'
01383              * (e.g. chunk-14*d8*tie*2 or chunk-123).
01384              * This hack eliminates long delays that would arise when generating
01385              *  new chunk names after having loaded in old chunks.  By extracting
01386              *  chunk_count here, the time spent looping and checking for pre-
01387              *  existing names is minimized.
01388              */
01389             char *chunk_name, *c;
01390             unsigned long this_chunk_count;
01391 
01392             chunk_name = p->name->sc.name;
01393             c = chunk_name;
01394             while (*c && (*c != '*'))
01395                 c++;
01396             do
01397                 c--;
01398             while (*c && (*c != '-'));
01399             c++;
01400             if (sscanf(c, "%lu", &this_chunk_count) != 1)
01401                 print("Warning: failed to extract chunk_num from chunk \"%s\"\n", chunk_name);
01402             else if (this_chunk_count > current_agent(chunk_count)) {
01403                 current_agent(chunk_count) = this_chunk_count;
01404                 print("updated chunk_num=%lu\n", current_agent(chunk_count));
01405             }
01406         }
01407         /* kjh CUSP(B14) end */
01408 
01409         return 0;               /* OK */
01410     } else {
01411         /* DJP : Modified to make all sp errors appear to be non-fatal */
01412         /*       This is necessary because currently warnings are causing */
01413         /*       Soar to stop loading files, which is clearly wrong.  */
01414         /*       E.g. ignoring production P1 because it's a duplicate of P2 */
01415 
01416         return -1;              /* Non Fatal Error */
01417 
01418         /* THIS MAY NEED A BETTER SOLUTION ??? -- KJC */
01419     }
01420 }
01421 
01422 void soar_ecPrintInternalSymbols(void)
01423 {
01424     print_string("\n--- Symbolic Constants: ---\n");
01425     do_for_all_items_in_hash_table(current_agent(sym_constant_hash_table), print_sym);
01426     print_string("\n--- Integer Constants: ---\n");
01427     do_for_all_items_in_hash_table(current_agent(int_constant_hash_table), print_sym);
01428     print_string("\n--- Floating-Point Constants: ---\n");
01429     do_for_all_items_in_hash_table(current_agent(float_constant_hash_table), print_sym);
01430     print_string("\n--- Identifiers: ---\n");
01431     do_for_all_items_in_hash_table(current_agent(identifier_hash_table), print_sym);
01432     print_string("\n--- Variables: ---\n");
01433     do_for_all_items_in_hash_table(current_agent(variable_hash_table), print_sym);
01434 }
01435 
01436 int soar_ecPrintPreferences(char *szId, char *szAttr, bool print_prod, wme_trace_type wtt)
01437 {
01438 
01439     Symbol *id, *attr;
01440     slot *s;
01441     preference *p;
01442     int i;
01443 
01444     if (read_id_or_context_var_from_string(szId, &id) == SOAR_ERROR) {
01445         print("Could not find the id '%s'\n", szId);
01446         return -1;
01447     }
01448     if (read_attribute_from_string(id, szAttr, &attr) == SOAR_ERROR) {
01449         print("Could not find the id,attribute pair: %s ^%s\n", szId, szAttr);
01450         return -2;
01451     }
01452 
01453     s = find_slot(id, attr);
01454     if (!s) {
01455         print("There are no preferences for %s ^%s.", szId, szAttr);
01456         return -3;
01457     }
01458 
01459     print_with_symbols("Preferences for %y ^%y:\n", id, attr);
01460 
01461     for (i = 0; i < NUM_PREFERENCE_TYPES; i++) {
01462         if (s->preferences[i]) {
01463             print("\n%ss:\n", preference_name[i]);
01464             for (p = s->preferences[i]; p; p = p->next) {
01465                 print_preference_and_source(p, print_prod, wtt);
01466             }
01467         }
01468     }
01469 
01470     return 0;
01471 }
01472 
01473 void soar_ecPrintProductionsBeingTraced()
01474 {
01475 
01476     cons *c;
01477 
01478     for (c = current_agent(productions_being_traced); c != NIL; c = c->rest)
01479         print_with_symbols(" %y\n", ((production *) (c->first))->name);
01480 }
01481 
01482 void soar_ecStopAllProductionTracing()
01483 {
01484 
01485     cons *c, *next;
01486 
01487     /*
01488      * We don't use c=c->rest in the increment step because 
01489      * remove_pwatch may release c as a side-effect.
01490      */
01491 
01492     for (c = current_agent(productions_being_traced); c != NIL; c = next) {
01493         production *prod;
01494 
01495         next = c->rest;
01496         prod = current_agent(productions_being_traced)->first;
01497         remove_pwatch(prod);
01498     }
01499 
01500 }
01501 
01502 int soar_ecBeginTracingProductions(int n, const char **names)
01503 {
01504 
01505     int i;
01506     production *prod;
01507 
01508     for (i = 0; i < n; i++) {
01509 
01510         prod = name_to_production(names[i]);
01511         if (prod) {
01512             add_pwatch(prod);
01513         } else {
01514             print("No Production named %s", names[i]);
01515             return (-1 - i);
01516         }
01517     }
01518     return 0;
01519 }
01520 
01521 int soar_ecStopTracingProductions(int n, const char **names)
01522 {
01523 
01524     int i;
01525     production *prod;
01526 
01527     for (i = 0; i < n; i++) {
01528 
01529         prod = name_to_production(names[i]);
01530         if (prod) {
01531             remove_pwatch(prod);
01532         } else {
01533             print("No Production named %s", names[i]);
01534             return (-1 - i);
01535         }
01536     }
01537     return 0;
01538 }
01539 
01540 void soar_ecPrintMatchSet(wme_trace_type wtt, ms_trace_type mst)
01541 {
01542     print_match_set(wtt, mst);
01543 }
01544 
01545 int soar_ecPrintMatchInfoForProduction(const char *name, wme_trace_type wtt)
01546 {
01547     production *p;
01548     struct rete_node_struct *p_node;
01549 
01550     p = name_to_production(name);
01551     if (!p) {
01552         return -1;
01553     }
01554 
01555     p_node = p->p_node;
01556     print_partial_match_information(p_node, wtt);
01557     return 0;
01558 }
01559 
01560 void soar_ecPrintMemoryPoolStatistics(void)
01561 {
01562     memory_pool *p;
01563 #ifdef MEMORY_POOL_STATS
01564     long total_items;
01565 #endif
01566 
01567     print("Memory pool statistics:\n\n");
01568 #ifdef MEMORY_POOL_STATS
01569     print("Pool Name        Used Items  Free Items  Item Size  Total Bytes\n");
01570     print("---------------  ----------  ----------  ---------  -----------\n");
01571 #else
01572     print("Pool Name        Item Size  Total Bytes\n");
01573     print("---------------  ---------  -----------\n");
01574 #endif
01575 
01576     for (p = current_agent(memory_pools_in_use); p != NIL; p = p->next) {
01577         print_string(p->name);
01578         print_spaces(MAX_POOL_NAME_LENGTH - strlen(p->name));
01579 #ifdef MEMORY_POOL_STATS
01580         print("  %10lu", p->used_count);
01581         total_items = p->num_blocks * p->items_per_block;
01582         print("  %10lu", total_items - p->used_count);
01583 #endif
01584         print("  %9lu", p->item_size);
01585         print("  %11lu\n", p->num_blocks * p->items_per_block * p->item_size);
01586     }
01587 }
01588 
01589 #ifdef  ATTENTION_LAPSE
01590 void soar_ecPrintAttentionLapseSettings(void)
01591 {
01592     print("Current attention-lapse setting:\n");
01593     print("   %s\n", current_agent(sysparams)[ATTENTION_LAPSE_ON_SYSPARAM] ? "-on" : "-off");
01594 
01595 }
01596 #endif                          /* ATTENTION_LAPSE */
01597 
01598 /*
01599  *----------------------------------------------------------------------
01600  *
01601  * soar_ecWatchLevel
01602  *
01603  *     Set the current Watch level, the higher the value, the 
01604  *     greater the verbosity.
01605  *
01606  *----------------------------------------------------------------------
01607  */
01608 int soar_ecWatchLevel(int level)
01609 {
01610 
01611     if (level > 5 || level < 0)
01612         return -1;
01613 
01614     set_sysparam(TRACE_CONTEXT_DECISIONS_SYSPARAM, FALSE);
01615     set_sysparam(TRACE_PHASES_SYSPARAM, FALSE);
01616     set_sysparam(TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM, FALSE);
01617     set_sysparam(TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM, FALSE);
01618     set_sysparam(TRACE_FIRINGS_OF_CHUNKS_SYSPARAM, FALSE);
01619     set_sysparam(TRACE_FIRINGS_OF_JUSTIFICATIONS_SYSPARAM, FALSE);
01620     set_sysparam(TRACE_WM_CHANGES_SYSPARAM, FALSE);
01621     set_sysparam(TRACE_FIRINGS_PREFERENCES_SYSPARAM, FALSE);
01622     set_sysparam(TRACE_OPERAND2_REMOVALS_SYSPARAM, FALSE);
01623 
01624     switch (level) {
01625     case 0:
01626         /* make sure everything is off */
01627         set_sysparam(TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM, NONE_WME_TRACE);
01628         set_sysparam(TRACE_CHUNK_NAMES_SYSPARAM, FALSE);
01629         set_sysparam(TRACE_JUSTIFICATION_NAMES_SYSPARAM, FALSE);
01630         set_sysparam(TRACE_CHUNKS_SYSPARAM, FALSE);
01631         set_sysparam(TRACE_JUSTIFICATIONS_SYSPARAM, FALSE);
01632         set_sysparam(TRACE_OPERAND2_REMOVALS_SYSPARAM, FALSE);
01633         break;
01634 
01635     case 5:
01636 
01637         set_sysparam(TRACE_FIRINGS_PREFERENCES_SYSPARAM, TRUE);
01638 
01639     case 4:
01640 
01641         set_sysparam(TRACE_WM_CHANGES_SYSPARAM, TRUE);
01642 
01643     case 3:
01644 
01645         set_sysparam(TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM, TRUE);
01646         set_sysparam(TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM, TRUE);
01647         set_sysparam(TRACE_FIRINGS_OF_CHUNKS_SYSPARAM, TRUE);
01648         set_sysparam(TRACE_FIRINGS_OF_JUSTIFICATIONS_SYSPARAM, TRUE);
01649 
01650     case 2:
01651 
01652         set_sysparam(TRACE_PHASES_SYSPARAM, TRUE);
01653 
01654     case 1:
01655 
01656         set_sysparam(TRACE_CONTEXT_DECISIONS_SYSPARAM, TRUE);
01657     }
01658 
01659     return 0;
01660 }

Generated on Thu Dec 11 13:00:21 2003 for Soar Kernel by doxygen 1.3.5