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

soarapiUtils.c

Go to the documentation of this file.
00001 /*
00002  * =======================================================================
00003  *  File:  soarCommandUtils.c
00004  *
00005  * This file includes the utility routines for supporting the
00006  * Soar Command set, which is found in soarCommands.c.  
00007  *
00008  * =======================================================================
00009  *
00010  *
00011  * Copyright 1995-2003 Carnegie Mellon University,
00012  *                                                                               University of Michigan,
00013  *                                                                               University of Southern California/Information
00014  *                                                                               Sciences Institute. All rights reserved.
00015  *                                                                              
00016  * Redistribution and use in source and binary forms, with or without
00017  * modification, are permitted provided that the following conditions are met:
00018  *
00019  * 1.   Redistributions of source code must retain the above copyright notice,
00020  *              this list of conditions and the following disclaimer. 
00021  * 2.   Redistributions in binary form must reproduce the above copyright notice,
00022  *              this list of conditions and the following disclaimer in the documentation
00023  *              and/or other materials provided with the distribution. 
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE SOAR CONSORTIUM ``AS IS'' AND ANY EXPRESS OR
00026  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00027  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00028  * EVENT SHALL THE SOAR CONSORTIUM  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00029  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00030  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00031  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00032  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00034  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  * The views and conclusions contained in the software and documentation are
00036  * those of the authors and should not be interpreted as representing official
00037  * policies, either expressed or implied, of Carnegie Mellon University, the
00038  * University of Michigan, the University of Southern California/Information
00039  * Sciences Institute, or the Soar consortium.
00040  * =======================================================================
00041  */
00042 
00043 #include "soarkernel.h"
00044 #include <ctype.h>
00045 #include <errno.h>
00046 
00047 #include <stdlib.h>
00048 #include <string.h>
00049 #include <time.h>
00050 #include <stdarg.h>
00051 
00052 #include "soarapi.h"
00053 #include "soarapiUtils.h"
00054 
00055 #define MAXPATHLEN 1024
00056 
00057 /* DJP 4/3/96 */
00058 #define dealloc_and_return(x,y) { deallocate_test(x) ; return (y) ; }
00059 
00060 char *preference_name[] = {
00061     "acceptable",
00062     "require",
00063     "reject",
00064     "prohibit",
00065     "reconsider",
00066     "unary indifferent",
00067     "unary parallel",
00068     "best",
00069     "worst",
00070     "binary indifferent",
00071     "binary parallel",
00072     "better",
00073     "worse"
00074 };
00075 
00076 int getInt(const char *string, int *i)
00077 {
00078 
00079     long l;
00080     char *c;
00081 
00082     if (*string == '\0')
00083         return SOAR_ERROR;
00084 
00085     l = strtol(string, &c, 10);
00086 
00087     if (*c == '\0') {
00088         *i = (int) l;
00089         return SOAR_OK;
00090     }
00091 
00092     return SOAR_ERROR;
00093 }
00094 
00095 Symbol *space_to_remove_from_cfps;
00096 
00097 bool cfps_removal_test_function(cons * c)
00098 {
00099     return (bool) (c->first == space_to_remove_from_cfps);
00100 }
00101 
00102 void do_print_for_production_name(const char *prod_name, bool internal, bool print_filename, bool full_prod)
00103 {
00104     Symbol *sym;
00105 
00106     sym = find_sym_constant(current_agent(lexeme).string);
00107     if (sym && sym->sc.production) {
00108         /* kjh CUSP(B11) begin *//* also Soar-Bugs #161 */
00109         if (print_filename) {
00110             if (full_prod)
00111                 print_string("# sourcefile : ");
00112             print("%s\n", sym->sc.production->filename);
00113         }
00114         /* KJC added so get at least some output for any named productions */
00115         if ((full_prod) || (!print_filename)) {
00116             print_production(sym->sc.production, internal);
00117             print("\n");
00118         }                       /* end CUSP B11 kjh */
00119     } else {
00120         print("No production named %s\n", prod_name);
00121         print_location_of_most_recent_lexeme();
00122     }
00123 }
00124 
00125 void do_print_for_wme(wme * w, int depth, bool internal)
00126 {
00127     tc_number tc;
00128 
00129     if (internal && (depth == 0)) {
00130         print_wme(w);
00131         /* print ("\n"); */
00132     } else {
00133         tc = get_new_tc_number();
00134         print_augs_of_id(w->id, depth, internal, 0, tc);
00135     }
00136 }
00137 
00138 void execute_go_selection(agent * the_agent,
00139                           long go_number,
00140                           enum go_type_enum go_type, Symbol * go_slot_attr, goal_stack_level go_slot_level)
00141 {
00142     switch (go_type) {
00143     case GO_PHASE:
00144         run_for_n_phases(go_number);
00145         break;
00146     case GO_ELABORATION:
00147         run_for_n_elaboration_cycles(go_number);
00148         break;
00149     case GO_DECISION:
00150         run_for_n_decision_cycles(go_number);
00151         break;
00152     case GO_STATE:
00153         run_for_n_selections_of_slot(go_number, the_agent->state_symbol);
00154         break;
00155     case GO_OPERATOR:
00156         run_for_n_selections_of_slot(go_number, the_agent->operator_symbol);
00157         break;
00158     case GO_SLOT:
00159         run_for_n_selections_of_slot_at_level(go_number, go_slot_attr, go_slot_level);
00160         break;
00161     case GO_OUTPUT:
00162         run_for_n_modifications_of_output(go_number);
00163         break;
00164     }
00165 }
00166 
00167 /* ===================================================================
00168                        Get Context Var Info
00169 
00170    This utility routine is used by interface routines that take context
00171    variable arguments (e.g., <s> for the current state).  It looks at
00172    the current lexeme (which must be of type VARIABLE_LEXEME), and
00173    checks to see if it's a context variable.  Returns:
00174 
00175     if lexeme is not a context variable, dest_attr_of_slot=NIL; else
00176       dest_attr_of_slot = {goal_symbol, problem_space_symbol, etc.}.
00177       dest_goal = goal identifier for the given slot (NIL if no such goal)
00178       dest_current_value = currently installed value (goal id itself for goals,
00179                            NIL if no installed value)
00180 =================================================================== */
00181 
00182 /* This routine was moved to command_utils.c for Tcl.  However, it cannot
00183  * reside outside the Soar kernel since it references lexeme.  This should
00184  * be rewritten to take a string argument and added to the Soar kernel
00185  * interface file (whatever that will be).
00186  */
00187 
00188 /*
00189  *----------------------------------------------------------------------
00190  *
00191  * print_current_learn_settings --
00192  *
00193  *      This procedure prints the current learn settings.
00194  *
00195  * Results:
00196  *      None.
00197  *
00198  * Side effects:
00199  *      Prints the current settings.
00200  *
00201  *----------------------------------------------------------------------
00202  */
00203 
00204 void print_current_learn_settings(void)
00205 {
00206     print("Current learn settings:\n");
00207 /* AGR MVL1 begin */
00208     if ((!current_agent(sysparams)[LEARNING_ONLY_SYSPARAM]) && (!current_agent(sysparams)[LEARNING_EXCEPT_SYSPARAM]))
00209         print("   %s\n", current_agent(sysparams)[LEARNING_ON_SYSPARAM] ? "-on" : "-off");
00210     else
00211         print("   %s\n", current_agent(sysparams)[LEARNING_ONLY_SYSPARAM] ? "-only" : "-except");
00212 
00213 /* AGR MVL1 end */
00214     print("   %s\n", current_agent(sysparams)[LEARNING_ALL_GOALS_SYSPARAM] ? "-all-levels" : "-bottom-up");
00215 
00216 }
00217 
00218 /*
00219  *----------------------------------------------------------------------
00220  *
00221  * print_multi_attribute_symbols --
00222  *
00223  *      This procedure prints a list of the symbols that are
00224  *      declared to have multi_attributes.
00225  *
00226  * Results:
00227  *      None.
00228  *
00229  * Side effects:
00230  *      Prints the list of symbols and the value of multi_attribute.
00231  *
00232  *----------------------------------------------------------------------
00233  */
00234 void print_multi_attribute_symbols(void)
00235 {
00236     multi_attribute *m = current_agent(multi_attributes);
00237 
00238     print("\n");
00239     if (!m) {
00240         print("No multi-attributes declared for this agent.\n");
00241     } else {
00242         print("Value\tSymbol\n");
00243         while (m) {
00244             print("%ld\t%s\n", m->value, symbol_to_string(m->symbol, TRUE, NIL, 0));
00245             m = m->next;
00246         }
00247     }
00248     print("\n");
00249 }
00250 
00251 /* kjh (CUSP-B7):  Add to soarCommandUtils.c after procedure
00252    "read_id_or_context_var_from_string" */
00253 
00254 /*
00255  *----------------------------------------------------------------------
00256  *
00257  * read_pref_detail_from_string --
00258  *
00259  *      This procedure parses a string to determine if it is a
00260  *      lexeme for the detail level indicator for the 'preferences'
00261  *      command.  If so, it sets the_lexeme and wme_trace_type accordingly
00262  *      and returns SOAR_OK; otherwise, it leaves those parameters untouched
00263  *      and returns SOAR_ERROR.
00264  *
00265  * Side effects:
00266  *      None.
00267  *
00268  *----------------------------------------------------------------------
00269  */
00270 
00271 int read_pref_detail_from_string(const char *the_lexeme, bool * print_productions, wme_trace_type * wtt)
00272 {
00273     if (!strncmp(the_lexeme, "-none", 3)
00274         || !strcmp(the_lexeme, "0")) {
00275         *print_productions = FALSE;
00276         *wtt = NONE_WME_TRACE;
00277     } else if (!strncmp(the_lexeme, "-names", 3)
00278                || !strcmp(the_lexeme, "1")) {
00279         *print_productions = TRUE;
00280         *wtt = NONE_WME_TRACE;
00281     } else if (!strncmp(the_lexeme, "-timetags", 2)
00282                || !strcmp(the_lexeme, "2")) {
00283         *print_productions = TRUE;
00284         *wtt = TIMETAG_WME_TRACE;
00285     } else if (!strncmp(the_lexeme, "-wmes", 2)
00286                || !strcmp(the_lexeme, "3")) {
00287         *print_productions = TRUE;
00288         *wtt = FULL_WME_TRACE;
00289     } else {
00290         return SOAR_ERROR;
00291     }
00292     return SOAR_OK;
00293 }
00294 
00295 /* ===================================================================
00296                 Read Pattern And Get Matching Wmes
00297 
00298    This routine reads a pattern and returns a list of all wmes that
00299    match it.  At entry, the current lexeme should be the "("; at exit,
00300    the current lexeme will be the ")".  If any error occurs or if no
00301    wmes match the pattern, the function returns NIL.
00302 
00303    pattern ::= ( {identifier | '*'} ^ { attribute | '*'} { value | '*' } [+])
00304 
00305 =================================================================== */
00306 
00307 /* This should be added to the Soar kernel.  It must be re-written to
00308  * take a string to parse.
00309  */
00310 
00311 int read_pattern_component(Symbol ** dest_sym)
00312 {
00313     /* --- Read and consume one pattern element.  Return 0 if error, 1 if "*",
00314        otherwise return 2 and set dest_sym to find_symbol() result. --- */
00315     if (strcmp(current_agent(lexeme).string, "*") == 0)
00316         return 1;
00317     switch (current_agent(lexeme).type) {
00318     case SYM_CONSTANT_LEXEME:
00319         *dest_sym = find_sym_constant(current_agent(lexeme).string);
00320         return 2;
00321     case INT_CONSTANT_LEXEME:
00322         *dest_sym = find_int_constant(current_agent(lexeme).int_val);
00323         return 2;
00324     case FLOAT_CONSTANT_LEXEME:
00325         *dest_sym = find_float_constant(current_agent(lexeme).float_val);
00326         return 2;
00327     case IDENTIFIER_LEXEME:
00328         *dest_sym = find_identifier(current_agent(lexeme).id_letter, current_agent(lexeme).id_number);
00329         return 2;
00330     case VARIABLE_LEXEME:
00331         *dest_sym = read_identifier_or_context_variable();
00332         if (*dest_sym)
00333             return 2;
00334         return 0;
00335     default:
00336         print("Expected identifier or constant in wme pattern\n");
00337         print_location_of_most_recent_lexeme();
00338         return 0;
00339     }
00340 }
00341 
00342 list *read_pattern_and_get_matching_wmes(void)
00343 {
00344     int parentheses_level;
00345     list *wmes;
00346     wme *w;
00347     Symbol *id, *attr, *value;
00348     int id_result, attr_result, value_result;
00349     bool acceptable;
00350 
00351     if (current_agent(lexeme).type != L_PAREN_LEXEME) {
00352         print("Expected '(' to begin wme pattern not string '%s' or char '%c'\n",
00353               current_agent(lexeme).string, current_agent(current_char));
00354         print_location_of_most_recent_lexeme();
00355         return NIL;
00356     }
00357     parentheses_level = current_lexer_parentheses_level();
00358 
00359     get_lexeme();
00360     id_result = read_pattern_component(&id);
00361     if (!id_result) {
00362         skip_ahead_to_balanced_parentheses(parentheses_level - 1);
00363         return NIL;
00364     }
00365     get_lexeme();
00366     if (current_agent(lexeme).type != UP_ARROW_LEXEME) {
00367         print("Expected ^ in wme pattern\n");
00368         print_location_of_most_recent_lexeme();
00369         skip_ahead_to_balanced_parentheses(parentheses_level - 1);
00370         return NIL;
00371     }
00372     get_lexeme();
00373     attr_result = read_pattern_component(&attr);
00374     if (!attr_result) {
00375         skip_ahead_to_balanced_parentheses(parentheses_level - 1);
00376         return NIL;
00377     }
00378     get_lexeme();
00379     value_result = read_pattern_component(&value);
00380     if (!value_result) {
00381         skip_ahead_to_balanced_parentheses(parentheses_level - 1);
00382         return NIL;
00383     }
00384     get_lexeme();
00385     if (current_agent(lexeme).type == PLUS_LEXEME) {
00386         acceptable = TRUE;
00387         get_lexeme();
00388     } else {
00389         acceptable = FALSE;
00390     }
00391     if (current_agent(lexeme).type != R_PAREN_LEXEME) {
00392         print("Expected ')' to end wme pattern\n");
00393         print_location_of_most_recent_lexeme();
00394         skip_ahead_to_balanced_parentheses(parentheses_level - 1);
00395         return NIL;
00396     }
00397     {
00398         int i = 0;
00399         wmes = NIL;
00400         for (w = current_agent(all_wmes_in_rete); w != NIL; w = w->rete_next) {
00401             if ((id_result == 1) || (id == w->id))
00402                 if ((attr_result == 1) || (attr == w->attr))
00403                     if ((value_result == 1) || (value == w->value))
00404                         if (acceptable == w->acceptable) {
00405                             push(w, wmes);
00406                             i++;
00407                         }
00408 
00409         }
00410         /* printf( "--- FOUND %d matching wmes\n", i ); */
00411     }
00412     return wmes;
00413 }
00414 
00415 void cb_appendToSoarResultResult(agent * the_agent, soar_callback_data data, soar_call_data call_data)
00416 {
00417 
00418     the_agent = the_agent;
00419 
00420     appendSoarResultResult(((soarResult *) data), (char *) call_data);
00421 
00422 }
00423 
00424 /*
00425  *----------------------------------------------------------------------
00426  *
00427  * soar_agent_already_defined --
00428  *
00429  *      This procedure determines if a Soar agent name is
00430  *      already in use.
00431  *
00432  * Results:
00433  *      Returns a boolean indication of whether the agent
00434  *      name is already defined or not.
00435  *
00436  * Side effects:
00437  *      None.
00438  *
00439  *----------------------------------------------------------------------
00440  */
00441 
00442 bool soar_agent_already_defined(char *name)
00443 {
00444     cons *c;                    /* Cons cell index            */
00445     agent *the_agent;           /* Agent index                */
00446 
00447     for (c = all_soar_agents; c != NIL; c = c->rest) {
00448         the_agent = (agent *) c->first;
00449         if (!strcmp(the_agent->name, name)) {
00450             return TRUE;
00451         }
00452     }
00453 
00454     return FALSE;
00455 }
00456 
00457 typedef struct binding_structure {
00458     Symbol *from, *to;
00459 } Binding;
00460 
00461 Symbol *get_binding(Symbol * f, list * bindings)
00462 {
00463     cons *c;
00464 
00465     for (c = bindings; c != NIL; c = c->rest) {
00466         if (((Binding *) c->first)->from == f)
00467             return ((Binding *) c->first)->to;
00468     }
00469     return NIL;
00470 }
00471 
00472 void reset_old_binding_point(list ** bindings, list ** current_binding_point)
00473 {
00474     cons *c, *c_next;
00475 
00476     c = *bindings;
00477     while (c != *current_binding_point) {
00478         c_next = c->rest;
00479         free_memory(c->first, MISCELLANEOUS_MEM_USAGE);
00480         free_cons(c);
00481         c = c_next;
00482     }
00483 
00484     bindings = current_binding_point;
00485 }
00486 
00487 void free_binding_list(list * bindings)
00488 {
00489     cons *c;
00490 
00491     for (c = bindings; c != NIL; c = c->rest)
00492         free_memory(c->first, MISCELLANEOUS_MEM_USAGE);
00493     free_list(bindings);
00494 }
00495 
00496 void print_binding_list(list * bindings)
00497 {
00498     cons *c;
00499 
00500     for (c = bindings; c != NIL; c = c->rest)
00501         print_with_symbols("   (%y -> %y)\n", ((Binding *) c->first)->from, ((Binding *) c->first)->to);
00502 }
00503 
00504 bool symbols_are_equal_with_bindings(Symbol * s1, Symbol * s2, list ** bindings)
00505 {
00506     Binding *b;
00507     Symbol *bvar;
00508 
00509     /* SBH/MVP 7-5-94 */
00510     if ((s1 == s2) && (s1->common.symbol_type != VARIABLE_SYMBOL_TYPE))
00511         return TRUE;
00512 
00513     /* "*" matches everything. */
00514     if ((s1->common.symbol_type == SYM_CONSTANT_SYMBOL_TYPE) && (!strcmp(s1->sc.name, "*")))
00515         return TRUE;
00516     if ((s2->common.symbol_type == SYM_CONSTANT_SYMBOL_TYPE) && (!strcmp(s2->sc.name, "*")))
00517         return TRUE;
00518 
00519     if ((s1->common.symbol_type != VARIABLE_SYMBOL_TYPE) || (s2->common.symbol_type != VARIABLE_SYMBOL_TYPE))
00520         return FALSE;
00521     /* Both are variables */
00522     bvar = get_binding(s1, *bindings);
00523     if (bvar == NIL) {
00524         b = (Binding *) allocate_memory(sizeof(Binding), MISCELLANEOUS_MEM_USAGE);
00525         b->from = s1;
00526         b->to = s2;
00527         push(b, *bindings);
00528         return TRUE;
00529     } else if (bvar == s2) {
00530         return TRUE;
00531     } else
00532         return FALSE;
00533 }
00534 
00535 /* ----------------------------------------------------------------
00536    Returns TRUE iff the two tests are identical given a list of bindings.
00537    Augments the bindings list if necessary.
00538 ---------------------------------------------------------------- */
00539 
00540 /* DJP 4/3/96 -- changed t2 to test2 in declaration */
00541 bool tests_are_equal_with_bindings(test t1, test test2, list ** bindings)
00542 {
00543     cons *c1, *c2;
00544     complex_test *ct1, *ct2;
00545     bool goal_test, impasse_test;
00546 
00547     /* DJP 4/3/96 -- The problem here is that sometimes test2 was being copied      */
00548     /*               and sometimes it wasn't.  If it was copied, the copy was never */
00549     /*               deallocated.  There's a few choices about how to fix this.  I  */
00550     /*               decided to just create a copy always and then always           */
00551     /*               deallocate it before returning.  Added a macro to do that.     */
00552 
00553     test t2;
00554 
00555     /* t1 is from the pattern given to "pf"; t2 is from a production's condition list. */
00556     if (test_is_blank_test(t1)) {
00557         return (bool) (test_is_blank_test(test2));
00558     }
00559 
00560     /* If the pattern doesn't include "(state", but the test from the
00561        production does, strip it out of the production's. */
00562     if ((!test_includes_goal_or_impasse_id_test(t1, TRUE, FALSE)) &&
00563         test_includes_goal_or_impasse_id_test(test2, TRUE, FALSE)) {
00564         goal_test = FALSE;
00565         impasse_test = FALSE;
00566         t2 = copy_test_removing_goal_impasse_tests(test2, &goal_test, &impasse_test);
00567     } else {
00568         t2 = copy_test(test2);  /* DJP 4/3/96 -- Always make t2 into a copy */
00569     }
00570 
00571     if (test_is_blank_or_equality_test(t1)) {
00572         if (!(test_is_blank_or_equality_test(t2) && !(test_is_blank_test(t2)))) {
00573             dealloc_and_return(t2, FALSE);
00574         } else {
00575             if (symbols_are_equal_with_bindings(referent_of_equality_test(t1), referent_of_equality_test(t2), bindings)) {
00576                 dealloc_and_return(t2, TRUE);
00577             } else {
00578                 dealloc_and_return(t2, FALSE);
00579             }
00580         }
00581     }
00582 
00583     ct1 = complex_test_from_test(t1);
00584     ct2 = complex_test_from_test(t2);
00585 
00586     if (ct1->type != ct2->type) {
00587         dealloc_and_return(t2, FALSE);
00588     }
00589 
00590     switch (ct1->type) {
00591     case GOAL_ID_TEST:
00592         dealloc_and_return(t2, TRUE);
00593     case IMPASSE_ID_TEST:
00594         dealloc_and_return(t2, TRUE);
00595 
00596     case DISJUNCTION_TEST:
00597         for (c1 = ct1->data.disjunction_list, c2 = ct2->data.disjunction_list; ((c1 != NIL) && (c2 != NIL));
00598              c1 = c1->rest, c2 = c2->rest) {
00599             if (c1->first != c2->first) {
00600                 dealloc_and_return(t2, FALSE);
00601             }
00602         }
00603         if (c1 == c2) {
00604             dealloc_and_return(t2, TRUE);       /* make sure they both hit end-of-list */
00605         }
00606         dealloc_and_return(t2, FALSE);
00607 
00608     case CONJUNCTIVE_TEST:
00609         for (c1 = ct1->data.conjunct_list, c2 = ct2->data.conjunct_list; ((c1 != NIL) && (c2 != NIL));
00610              c1 = c1->rest, c2 = c2->rest) {
00611             if (!tests_are_equal_with_bindings(c1->first, c2->first, bindings)) {
00612                 dealloc_and_return(t2, FALSE);
00613             }
00614         }
00615         if (c1 == c2) {
00616             dealloc_and_return(t2, TRUE);       /* make sure they both hit end-of-list */
00617         }
00618         dealloc_and_return(t2, FALSE);
00619 
00620     default:                   /* relational tests other than equality */
00621         if (symbols_are_equal_with_bindings(ct1->data.referent, ct2->data.referent, bindings)) {
00622             dealloc_and_return(t2, TRUE);
00623         }
00624         dealloc_and_return(t2, FALSE);
00625     }
00626 }
00627 
00628 bool conditions_are_equal_with_bindings(condition * c1, condition * c2, list ** bindings)
00629 {
00630     if (c1->type != c2->type)
00631         return FALSE;
00632     switch (c1->type) {
00633     case POSITIVE_CONDITION:
00634     case NEGATIVE_CONDITION:
00635         if (!tests_are_equal_with_bindings(c1->data.tests.id_test, c2->data.tests.id_test, bindings))
00636             return FALSE;
00637         if (!tests_are_equal_with_bindings(c1->data.tests.attr_test, c2->data.tests.attr_test, bindings))
00638 
00639             return FALSE;
00640         if (!tests_are_equal_with_bindings(c1->data.tests.value_test, c2->data.tests.value_test, bindings))
00641             return FALSE;
00642         if (c1->test_for_acceptable_preference != c2->test_for_acceptable_preference)
00643             return FALSE;
00644         return TRUE;
00645 
00646     case CONJUNCTIVE_NEGATION_CONDITION:
00647         for (c1 = c1->data.ncc.top, c2 = c2->data.ncc.top; ((c1 != NIL) && (c2 != NIL)); c1 = c1->next, c2 = c2->next)
00648             if (!conditions_are_equal_with_bindings(c1, c2, bindings))
00649                 return FALSE;
00650         if (c1 == c2)
00651             return TRUE;        /* make sure they both hit end-of-list */
00652         return FALSE;
00653     }
00654     return FALSE;               /* unreachable, but without it, gcc -Wall warns here */
00655 }
00656 
00657 /* Routine for LHS. */
00658 void read_pattern_and_get_matching_productions(list ** current_pf_list, bool show_bindings,
00659                                                bool just_chunks, bool no_chunks)
00660 {
00661     condition *c, *clist, *top, *bottom, *pc;
00662     int i;
00663     production *prod;
00664     list *bindings, *current_binding_point;
00665     bool match, match_this_c;
00666 
00667     bindings = NIL;
00668     current_binding_point = NIL;
00669 
00670 /*  print("Parsing as a lhs...\n"); */
00671     clist = (condition *) parse_lhs();
00672     if (!clist) {
00673         print("Error: not a valid condition list.\n");
00674         current_pf_list = NIL;
00675         return;
00676     }
00677 /*
00678   print("Valid condition list:\n");
00679   print_condition_list(clist,0,FALSE);
00680   print("\nMatches:\n");
00681 */
00682 
00683     /* For the moment match against productions of all types (user,chunk,default, justification).     Later on the type should be a parameter.
00684      */
00685 
00686     for (i = 0; i < NUM_PRODUCTION_TYPES; i++)
00687         if ((i == CHUNK_PRODUCTION_TYPE && !no_chunks) || (i != CHUNK_PRODUCTION_TYPE && !just_chunks))
00688             for (prod = current_agent(all_productions_of_type)[i]; prod != NIL; prod = prod->next) {
00689 
00690                 /* Now the complicated part. */
00691                 /* This is basically a full graph-match.  Like the rete.  Yikes! */
00692                 /* Actually it's worse, because there are so many different KINDS of
00693                    conditions (negated, >/<, acc prefs, ...) */
00694                 /* Is there some way I could *USE* the rete for this?  -- for lhs
00695                    positive conditions, possibly.  Put some fake stuff into WM
00696                    (i.e. with make-wme's), see what matches all of them, and then
00697                    yank out the fake stuff.  But that won't work for RHS or for
00698                    negateds.       */
00699 
00700                 /* Also note that we need bindings for every production.  Very expensive
00701                    (but don't necc. need to save them -- maybe can just print them as we go). */
00702 
00703                 match = TRUE;
00704                 p_node_to_conditions_and_nots(prod->p_node, NIL, NIL, &top, &bottom, NIL, NIL);
00705 
00706                 free_binding_list(bindings);
00707                 bindings = NIL;
00708 
00709                 for (c = clist; c != NIL; c = c->next) {
00710                     match_this_c = FALSE;
00711                     current_binding_point = bindings;
00712 
00713                     for (pc = top; pc != NIL; pc = pc->next) {
00714                         if (conditions_are_equal_with_bindings(c, pc, &bindings)) {
00715                             match_this_c = TRUE;
00716                             break;
00717                         } else {
00718                             /* Remove new, incorrect bindings. */
00719                             reset_old_binding_point(&bindings, &current_binding_point);
00720                             bindings = current_binding_point;
00721                         }
00722                     }
00723                     if (!match_this_c) {
00724                         match = FALSE;
00725                         break;
00726                     }
00727                 }
00728                 deallocate_condition_list(top); /* DJP 4/3/96 -- Never dealloced */
00729                 if (match) {
00730                     push(prod, (*current_pf_list));
00731                     if (show_bindings) {
00732                         print_with_symbols("%y, with bindings:\n", prod->name);
00733                         print_binding_list(bindings);
00734                     } else
00735                         print_with_symbols("%y\n", prod->name);
00736                 }
00737             }
00738     if (bindings)
00739         free_binding_list(bindings);    /* DJP 4/3/96 -- To catch the last production */
00740 }
00741 
00742 bool funcalls_match(list * fc1, list * fc2)
00743 {
00744     /* I have no idea how to do this. */
00745 
00746     /* voigtjr: neither do I, so I'm just going to shut up the compiler 
00747        warnings with these next two lines */
00748     fc1 = fc1;
00749     fc2 = fc2;
00750 
00751     return FALSE;
00752 }
00753 
00754 bool actions_are_equal_with_bindings(action * a1, action * a2, list ** bindings)
00755 {
00756     if (a1->type == FUNCALL_ACTION) {
00757         if ((a2->type == FUNCALL_ACTION)) {
00758             if (funcalls_match(rhs_value_to_funcall_list(a1->value), rhs_value_to_funcall_list(a2->value))) {
00759                 return TRUE;
00760             } else
00761                 return FALSE;
00762         } else
00763             return FALSE;
00764     }
00765     if (a2->type == FUNCALL_ACTION)
00766         return FALSE;
00767 
00768     /* Both are make_actions. */
00769 
00770     if (a1->preference_type != a2->preference_type)
00771         return FALSE;
00772 
00773     if (!symbols_are_equal_with_bindings(rhs_value_to_symbol(a1->id), rhs_value_to_symbol(a2->id), bindings))
00774         return FALSE;
00775 
00776     if ((rhs_value_is_symbol(a1->attr)) && (rhs_value_is_symbol(a2->attr))) {
00777         if (!symbols_are_equal_with_bindings(rhs_value_to_symbol(a1->attr), rhs_value_to_symbol(a2->attr), bindings))
00778             return FALSE;
00779     } else {
00780         if ((rhs_value_is_funcall(a1->attr)) && (rhs_value_is_funcall(a2->attr))) {
00781             if (!funcalls_match(rhs_value_to_funcall_list(a1->attr), rhs_value_to_funcall_list(a2->attr)))
00782                 return FALSE;
00783         }
00784     }
00785 
00786     /* Values are different. They are rhs_value's. */
00787 
00788     if ((rhs_value_is_symbol(a1->value)) && (rhs_value_is_symbol(a2->value))) {
00789         if (symbols_are_equal_with_bindings(rhs_value_to_symbol(a1->value), rhs_value_to_symbol(a2->value), bindings))
00790             return TRUE;
00791         else
00792             return FALSE;
00793     }
00794     if ((rhs_value_is_funcall(a1->value)) && (rhs_value_is_funcall(a2->value))) {
00795         if (funcalls_match(rhs_value_to_funcall_list(a1->value), rhs_value_to_funcall_list(a2->value)))
00796             return TRUE;
00797         else
00798             return FALSE;
00799     }
00800     return FALSE;
00801 }
00802 
00803 /* Routine for RHS. */
00804 void read_rhs_pattern_and_get_matching_productions(list ** current_pf_list, bool show_bindings,
00805                                                    bool just_chunks, bool no_chunks)
00806 {
00807     action *a, *alist, *pa;
00808     int i;
00809     production *prod;
00810     list *bindings, *current_binding_point;
00811     bool match, match_this_a, parsed_ok;
00812     action *rhs;
00813     condition *top_cond, *bottom_cond;
00814 
00815     bindings = NIL;
00816     current_binding_point = NIL;
00817 
00818 /*  print("Parsing as a rhs...\n"); */
00819     parsed_ok = parse_rhs(&alist);
00820     if (!parsed_ok) {
00821         print("Error: not a valid rhs.\n");
00822         current_pf_list = NIL;
00823         return;
00824     }
00825 
00826 /*
00827   print("Valid RHS:\n");
00828   print_action_list(alist,0,FALSE);
00829   print("\nMatches:\n");
00830 */
00831 
00832     for (i = 0; i < NUM_PRODUCTION_TYPES; i++)
00833         if ((i == CHUNK_PRODUCTION_TYPE && !no_chunks) || (i != CHUNK_PRODUCTION_TYPE && !just_chunks))
00834             for (prod = current_agent(all_productions_of_type)[i]; prod != NIL; prod = prod->next) {
00835                 match = TRUE;
00836 
00837                 free_binding_list(bindings);
00838                 bindings = NIL;
00839 
00840                 p_node_to_conditions_and_nots(prod->p_node, NIL, NIL, &top_cond, &bottom_cond, NIL, &rhs);
00841                 deallocate_condition_list(top_cond);
00842                 for (a = alist; a != NIL; a = a->next) {
00843                     match_this_a = FALSE;
00844                     current_binding_point = bindings;
00845 
00846                     for (pa = rhs; pa != NIL; pa = pa->next) {
00847                         if (actions_are_equal_with_bindings(a, pa, &bindings)) {
00848                             match_this_a = TRUE;
00849                             break;
00850                         } else {
00851                             /* Remove new, incorrect bindings. */
00852                             reset_old_binding_point(&bindings, &current_binding_point);
00853                             bindings = current_binding_point;
00854                         }
00855                     }
00856                     if (!match_this_a) {
00857                         match = FALSE;
00858                         break;
00859                     }
00860                 }
00861                 deallocate_action_list(rhs);
00862                 if (match) {
00863                     push(prod, (*current_pf_list));
00864                     if (show_bindings) {
00865                         print_with_symbols("%y, with bindings:\n", prod->name);
00866                         print_binding_list(bindings);
00867                     } else
00868                         print_with_symbols("%y\n", prod->name);
00869                 }
00870             }
00871     if (bindings)
00872         free_binding_list(bindings);    /* DJP 4/3/96 -- To catch the last production */
00873 }
00874 
00875 /*
00876 Soar_TextWidgetPrintData *
00877 Soar_MakeTextWidgetPrintData (Tcl_Interp * interp, char * widget_name)
00878 {
00879   Soar_TextWidgetPrintData * data;
00880 
00881   data = (Soar_TextWidgetPrintData *) 
00882          malloc (sizeof (Soar_TextWidgetPrintData));
00883   data->interp = interp;
00884   data->text_widget = savestring(widget_name);
00885 
00886   return data;
00887 }
00888 
00889 */
00890 
00891 /*
00892 extern void Soar_FreeTextWidgetPrintData (Soar_TextWidgetPrintData * data)
00893 {
00894   free((void *) data->text_widget);
00895   free((void *) data);
00896 }
00897 
00898 */
00899 /* kjh(CUSP-B2) begin */
00900 extern Symbol *make_symbol_for_current_lexeme(void);
00901 
00902 /*
00903  *----------------------------------------------------------------------
00904  *
00905  * print_current_watch_settings --
00906  *
00907  *      This procedure prints the current watch settings.
00908  *
00909  * Results:
00910  *      None.
00911  *
00912  * Side effects:
00913  *      Prints the current watch settings.
00914  *
00915  *----------------------------------------------------------------------
00916  */
00917 
00918 void print_current_watch_settings(void)
00919 {
00920 /* Added this to avoid segfault on Solaris when attempt to print NULL */
00921     /*char *a = NULL; */
00922 
00923     print("Current watch settings:\n");
00924     print("  Decisions:  %s\n", current_agent(sysparams)[TRACE_CONTEXT_DECISIONS_SYSPARAM] ? "on" : "off");
00925     print("  Phases:  %s\n", current_agent(sysparams)[TRACE_PHASES_SYSPARAM] ? "on" : "off");
00926     print("  Production firings/retractions\n");
00927     print("    default productions:  %s\n",
00928           current_agent(sysparams)[TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM] ? "on" : "off");
00929     print("    user productions:  %s\n", current_agent(sysparams)[TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM] ? "on" : "off");
00930     print("    chunks:  %s\n", current_agent(sysparams)[TRACE_FIRINGS_OF_CHUNKS_SYSPARAM] ? "on" : "off");
00931     print("    justifications:  %s\n",
00932           current_agent(sysparams)[TRACE_FIRINGS_OF_JUSTIFICATIONS_SYSPARAM] ? "on" : "off");
00933     print("    WME detail level:  %d\n", current_agent(sysparams)[TRACE_FIRINGS_WME_TRACE_TYPE_SYSPARAM]);
00934     print("  Working memory changes:  %s\n", current_agent(sysparams)[TRACE_WM_CHANGES_SYSPARAM] ? "on" : "off");
00935     print("  Preferences generated by firings/retractions:  %s\n",
00936           current_agent(sysparams)[TRACE_FIRINGS_PREFERENCES_SYSPARAM] ? "on" : "off");
00937     /*  don't print these individually...see chunk-creation
00938      *  print ("  Chunk names:  %s\n",
00939      *      current_agent(sysparams)[TRACE_CHUNK_NAMES_SYSPARAM] ? "on" : "off");
00940      *  print ("  Justification names:  %s\n",
00941      *      current_agent(sysparams)[TRACE_JUSTIFICATION_NAMES_SYSPARAM] ? "on" : "off");
00942      *  print ("  Chunks:  %s\n",
00943      *      current_agent(sysparams)[TRACE_CHUNKS_SYSPARAM] ? "on" : "off");
00944      *  print ("  Justifications:  %s\n",
00945      *      current_agent(sysparams)[TRACE_JUSTIFICATIONS_SYSPARAM] ? "on" : "off");
00946      */
00947     print("\n");
00948     if (current_agent(sysparams)[TRACE_CHUNKS_SYSPARAM]) {
00949         print("  Learning:  -fullprint  (watch creation of chunks/just.)\n");
00950     } else {
00951         print("  Learning:  %s  (watch creation of chunks/just.)\n",
00952               current_agent(sysparams)[TRACE_CHUNK_NAMES_SYSPARAM] ? "-print" : "-noprint");
00953     }
00954     print("  Backtracing:  %s\n", current_agent(sysparams)[TRACE_BACKTRACING_SYSPARAM] ? "on" : "off");
00955 
00956     print("  Loading:  %s\n", current_agent(sysparams)[TRACE_LOADING_SYSPARAM] ? "on" : "off");
00957 
00958         print("  Indifferent-selection:  %s\n", current_agent(sysparams)[TRACE_INDIFFERENT_SYSPARAM] ? "on" : "off");
00959 
00960     print("\n");
00961 }
00962 
00963 /*
00964  *----------------------------------------------------------------------
00965  *
00966  * set_watch_setting --
00967  *
00968  *      This procedure parses an argument to a watch variable to
00969  *      determine if "on" or "off" has been selected.
00970  *
00971  * Results:
00972  *      Tcl status code.
00973  *
00974  * Side effects:
00975  *      Sets the desired paramater to the indicated setting.
00976  *
00977  *----------------------------------------------------------------------
00978  */
00979 
00980 int set_watch_setting(int dest_sysparam_number, const char *param, const char *arg, soarResult * res)
00981 {
00982     if (arg == NULL) {
00983         setSoarResultResult(res, "Missing setting for watch parameter %s", param);
00984         return SOAR_ERROR;
00985     }
00986 
00987     if (!strcmp("-on", arg)) {
00988         set_sysparam(dest_sysparam_number, TRUE);
00989     } else if (!strcmp("-off", arg)) {
00990         set_sysparam(dest_sysparam_number, FALSE);
00991     } else if (!strncmp("-inclusive", arg, 3)) {
00992         soar_ecWatchLevel(dest_sysparam_number);
00993     } else {
00994         setSoarResultResult(res, "Unrecognized setting for watch parameter %s: %s", param, arg);
00995         return SOAR_ERROR;
00996     }
00997     return SOAR_OK;
00998 }
00999 
01000 /*
01001  *----------------------------------------------------------------------
01002  *
01003  * set_watch_prod_group_setting --
01004  *
01005  *      This procedure parses an argument to a watch production-type to
01006  *      determine if "print" or "noprint" has been selected.
01007  *
01008  * Results:
01009  *      Tcl status code.
01010  *
01011  * Side effects:
01012  *      Sets the desired prod-group to the indicated setting.
01013  *
01014  *----------------------------------------------------------------------
01015  */
01016 
01017 int set_watch_prod_group_setting(int prodgroup, const char *prodtype, const char *arg, soarResult * res)
01018 {
01019     if (arg == NULL) {
01020         setSoarResultResult(res, "Missing setting for watch %s", prodtype);
01021         return SOAR_ERROR;
01022     }
01023 
01024     if (!strcmp("-print", arg)) {
01025         switch (prodgroup) {
01026         case 0:
01027             set_sysparam(TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM, TRUE);
01028             set_sysparam(TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM, TRUE);
01029             set_sysparam(TRACE_FIRINGS_OF_CHUNKS_SYSPARAM, TRUE);
01030             set_sysparam(TRACE_FIRINGS_OF_JUSTIFICATIONS_SYSPARAM, TRUE);
01031             break;
01032         case 1:
01033             set_sysparam(TRACE_FIRINGS_OF_CHUNKS_SYSPARAM, TRUE);
01034             break;
01035         case 2:
01036             set_sysparam(TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM, TRUE);
01037             break;
01038         case 3:
01039             set_sysparam(TRACE_FIRINGS_OF_JUSTIFICATIONS_SYSPARAM, TRUE);
01040             break;
01041         case 4:
01042             set_sysparam(TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM, TRUE);
01043             break;
01044         }
01045     } else if (!strcmp("-noprint", arg)) {
01046         switch (prodgroup) {
01047         case 0:
01048             set_sysparam(TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM, FALSE);
01049             set_sysparam(TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM, FALSE);
01050             set_sysparam(TRACE_FIRINGS_OF_CHUNKS_SYSPARAM, FALSE);
01051             set_sysparam(TRACE_FIRINGS_OF_JUSTIFICATIONS_SYSPARAM, FALSE);
01052             break;
01053         case 1:
01054             set_sysparam(TRACE_FIRINGS_OF_CHUNKS_SYSPARAM, FALSE);
01055             break;
01056         case 2:
01057             set_sysparam(TRACE_FIRINGS_OF_DEFAULT_PRODS_SYSPARAM, FALSE);
01058             break;
01059         case 3:
01060             set_sysparam(TRACE_FIRINGS_OF_JUSTIFICATIONS_SYSPARAM, FALSE);
01061             break;
01062         case 4:
01063             set_sysparam(TRACE_FIRINGS_OF_USER_PRODS_SYSPARAM, FALSE);
01064             break;
01065         }
01066     } else if (!strcmp("-fullprint", arg)) {
01067         setSoarResultResult(res, "Sorry, -fullprint not yet implemented for watch productions");
01068         return SOAR_ERROR;
01069     } else {
01070         setSoarResultResult(res,
01071                             "Unrecognized setting for watch %s: %s.  Use -print|-noprint|-fullprint", prodtype, arg);
01072         return SOAR_ERROR;
01073     }
01074     return SOAR_OK;
01075 }
01076 
01077 /*
01078  *----------------------------------------------------------------------
01079  *
01080  * parse_run_command--
01081  *
01082  *      This procedure parses an argv array and sets the agent parameters.
01083  *
01084  *      The syntax being parsed is:
01085  *          run [n] [units] [-self]
01086  *
01087  *              [n] is an integer, which defaults to 1 if a unit is 
01088  *                  specified; if no units, [n] defaults to forever.
01089  *              [units]:
01090  *                 d - decision cycles
01091  *                 e - elaboration cycles
01092  *                 p - phases
01093  *                 s - state
01094  *                 o - operator selection
01095  *               out - run by decision cycles until output generated
01096  *                <s>- current level of subgoaling
01097  *               <ss>- superstate's level of subgoaling
01098  *              <sss>- supersuperstate's level of subgoaling
01099  *                <o>- operator selection AT THIS LEVEL of subgoaling
01100  *                        or current level of subgoaling terminated
01101  *               <so>- superoperator selection (or THAT subgoaling terminated)
01102  *              <sso>- supersuperoperator selection (or subgoaling terminated)
01103  * 
01104  *              [-self] to run only the current agent interp.
01105  *                      (flag only returned, RunCmd processes it)
01106  *
01107  * Results:
01108  *      Returns the agent parameters and the Tcl return code.
01109  *
01110  * Side effects:
01111  *      None.
01112  *
01113  *----------------------------------------------------------------------
01114  */
01115 int parse_run_command(int argc, const char *argv[],
01116                       long *go_number,
01117                       enum go_type_enum *go_type,
01118                       Symbol * *go_slot_attr, goal_stack_level * go_slot_level, bool * self_only, soarResult * res)
01119 {
01120     Symbol *g, *attr, *value;
01121     int i;
01122     bool no_number = TRUE;
01123 
01124     for (i = 1; i < argc; i++) {
01125         get_lexeme_from_string(argv[i]);
01126 
01127         if (current_agent(lexeme).type == INT_CONSTANT_LEXEME) {
01128             *go_number = current_agent(lexeme).int_val;
01129             no_number = FALSE;
01130         } else if (current_agent(lexeme).type == SYM_CONSTANT_LEXEME) {
01131             if (!strcmp("forever", argv[i])) {
01132                 *go_number = -1;
01133             } else if (!strcmp("p", argv[i])) {
01134                 *go_type = GO_PHASE;
01135                 if (no_number) {
01136                     *go_number = 1;
01137                     no_number = FALSE;
01138                 }
01139             } else if (!strcmp("e", argv[i])) {
01140                 *go_type = GO_ELABORATION;
01141                 if (no_number) {
01142                     *go_number = 1;
01143                     no_number = FALSE;
01144                 }
01145             } else if (!strcmp("d", argv[i])) {
01146                 *go_type = GO_DECISION;
01147                 if (no_number) {
01148                     *go_number = 1;
01149                     no_number = FALSE;
01150                 }
01151             } else if (!strcmp("s", argv[i])) {
01152                 *go_type = GO_STATE;
01153                 if (no_number) {
01154                     *go_number = 1;
01155                     no_number = FALSE;
01156                 }
01157             } else if (!strcmp("o", argv[i])) {
01158                 *go_type = GO_OPERATOR;
01159                 if (no_number) {
01160                     *go_number = 1;
01161                     no_number = FALSE;
01162                 }
01163             } else if (!strcmp("out", argv[i])) {
01164                 *go_type = GO_OUTPUT;
01165                 if (no_number) {
01166                     *go_number = 1;
01167                     no_number = FALSE;
01168                 }
01169             } else if (!strcmp("-self", argv[i])) {
01170                 *self_only = TRUE;
01171             } else {
01172                 setSoarResultResult(res, "Unrecognized argument to run command: %s", argv[i]);
01173                 return SOAR_ERROR;
01174             }
01175         } else if (current_agent(lexeme).type == VARIABLE_LEXEME) {
01176             get_context_var_info(&g, &attr, &value);
01177             if (!attr) {
01178                 setSoarResultResult(res,
01179                                     "Expected <s>, <o>, <ss>, <so>, <sss>, or <sso> as variable in run command, not %s",
01180                                     argv[i]);
01181                 return SOAR_ERROR;
01182             }
01183 
01184             if (!g) {
01185                 setSoarResultResult(res,
01186                                     "There is either no superstate, or no supersuperstate (whichever you specified, %s) of the current level",
01187                                     argv[i]);
01188                 return SOAR_ERROR;
01189             }
01190             *go_type = GO_SLOT;
01191             *go_slot_level = g->id.level;
01192             *go_slot_attr = attr;
01193             if (no_number) {
01194                 *go_number = 1;
01195                 no_number = FALSE;
01196             }
01197         } else {
01198             setSoarResultResult(res, "Unrecognized argument to run command: %s", argv[i]);
01199             return SOAR_ERROR;
01200         }
01201     }
01202 
01203     /* if there were no units and no number given as args to run, 
01204      * then run forever.
01205      */
01206     if (no_number) {
01207         *go_number = -1;
01208     }
01209 
01210     return SOAR_OK;
01211 
01212 }
01213 
01214 int parse_go_command(int argc, char *argv[],
01215                      long *go_number,
01216                      enum go_type_enum *go_type,
01217                      Symbol * *go_slot_attr, goal_stack_level * go_slot_level, soarResult * res)
01218 {
01219     Symbol *g, *attr, *value;
01220     int i;
01221 
01222     for (i = 1; i < argc; i++) {
01223         get_lexeme_from_string(argv[i]);
01224 
01225         if (current_agent(lexeme).type == INT_CONSTANT_LEXEME) {
01226             *go_number = current_agent(lexeme).int_val;
01227         } else if (current_agent(lexeme).type == SYM_CONSTANT_LEXEME) {
01228             if (!strcmp("forever", argv[i])) {
01229                 *go_number = -1;
01230             } else if (!strcmp("p", argv[i])) {
01231                 *go_type = GO_PHASE;
01232             } else if (!strcmp("e", argv[i])) {
01233                 *go_type = GO_ELABORATION;
01234             } else if (!strcmp("d", argv[i])) {
01235                 *go_type = GO_DECISION;
01236             } else if (!strcmp("s", argv[i])) {
01237                 *go_type = GO_STATE;
01238             } else if (!strcmp("o", argv[i])) {
01239                 *go_type = GO_OPERATOR;
01240             } else {
01241                 setSoarResultResult(res, "Unrecognized argument to go command: %s", argv[i]);
01242                 return SOAR_ERROR;
01243             }
01244         } else if (current_agent(lexeme).type == VARIABLE_LEXEME) {
01245             get_context_var_info(&g, &attr, &value);
01246             if (!attr) {
01247                 setSoarResultResult(res, "Expected a context variable in go command, not %s", argv[i]);
01248                 return SOAR_ERROR;
01249             }
01250 
01251             if (!g) {
01252                 setSoarResultResult(res, "Goal stack level %s does not exist", argv[i]);
01253                 return SOAR_ERROR;
01254             }
01255 
01256             *go_type = GO_SLOT;
01257             *go_slot_level = g->id.level;
01258             *go_slot_attr = attr;
01259         } else {
01260             setSoarResultResult(res, "Unrecognized argument to go command: %s", argv[i]);
01261             return SOAR_ERROR;
01262         }
01263     }
01264 
01265     return SOAR_OK;
01266 }
01267 
01268 /*
01269  *----------------------------------------------------------------------
01270  *
01271  * parse_memory_stats --
01272  *
01273  *      This procedure parses an argv array and prints the selected
01274  *      statistics.
01275  *
01276  *      The syntax being parsed is:
01277  *         stats -rete <mtype>
01278  *         <mtype> ::= -total
01279  *                     -overhead
01280  *                     -strings
01281  *                     -hash-table
01282  *                     -pool [-total | pool-name [<aspect>]]
01283  *                     -misc
01284  *        <aspect> ::= -used                   |M
01285  *                     -free                   |M
01286  *                     -item-size
01287  *                     -total-bytes
01288  *
01289  *          The items marked |M are available only when Soar has
01290  *          been compiled with the MEMORY_POOL_STATS option.
01291  *
01292  * Results:
01293  *      Returns the statistic and Tcl return code.
01294  *
01295  * Side effects:
01296  *      None.
01297  *
01298  *----------------------------------------------------------------------
01299  */
01300 
01301 int parse_memory_stats(int argc, const char *argv[], soarResult * res)
01302 {
01303     if (argc == 2) {
01304         soar_ecPrintMemoryStatistics();
01305         soar_ecPrintMemoryPoolStatistics();
01306 
01307         return SOAR_OK;
01308     }
01309 
01310     if (!strcmp("-total", argv[2])) {
01311         unsigned long total;
01312         int i;
01313 
01314         total = 0;
01315         for (i = 0; i < NUM_MEM_USAGE_CODES; i++)
01316             total += current_agent(memory_for_usage)[i];
01317 
01318                 print("%lu", total);
01319         /*setSoarResultResult(res, "%lu", total);*/
01320     } else if (!strcmp("-overhead", argv[2])) {
01321                 print("%lu", current_agent(memory_for_usage)[STATS_OVERHEAD_MEM_USAGE]);
01322         /*setSoarResultResult(res, "%lu", current_agent(memory_for_usage)[STATS_OVERHEAD_MEM_USAGE]);*/
01323     } else if (!strcmp("-strings", argv[2])) {
01324                 print("%lu", current_agent(memory_for_usage)[STRING_MEM_USAGE]);
01325         /*setSoarResultResult(res, "%lu", current_agent(memory_for_usage)[STRING_MEM_USAGE]);*/
01326     } else if (!strcmp("-hash-table", argv[2])) {
01327                 print("%lu", current_agent(memory_for_usage)[HASH_TABLE_MEM_USAGE]);
01328         /*setSoarResultResult(res, "%lu", current_agent(memory_for_usage)[HASH_TABLE_MEM_USAGE]);*/
01329     } else if (!strcmp("-pool", argv[2])) {     /* Handle pool stats */
01330         if (argc == 3) {
01331             soar_ecPrintMemoryPoolStatistics();
01332         } else if (!strcmp("-total", argv[3])) {
01333                         print("%lu", current_agent(memory_for_usage)[POOL_MEM_USAGE]);
01334             /*setSoarResultResult(res, "%lu", current_agent(memory_for_usage)[POOL_MEM_USAGE]);*/
01335         } else {                /* Match pool name or invalid item */
01336             memory_pool *p;
01337             memory_pool *pool_found = NIL;
01338 
01339             for (p = current_agent(memory_pools_in_use); p != NIL; p = p->next) {
01340                 if (!strcmp(argv[3], p->name)) {
01341                     pool_found = p;
01342                     break;
01343                 }
01344             }
01345 
01346             if (!pool_found) {
01347                 setSoarResultResult(res, "Unrecognized pool name: stats -memory -pool %s", argv[4]);
01348                 return SOAR_ERROR;
01349             }
01350 
01351             if (argc == 4) {
01352 #ifdef MEMORY_POOL_STATS
01353                 long total_items;
01354 #endif
01355                 print("Memory pool statistics:\n\n");
01356 #ifdef MEMORY_POOL_STATS
01357                 print("Pool Name        Used Items  Free Items  Item Size  Total Bytes\n");
01358                 print("---------------  ----------  ----------  ---------  -----------\n");
01359 #else
01360                 print("Pool Name        Item Size  Total Bytes\n");
01361                 print("---------------  ---------  -----------\n");
01362 #endif
01363 
01364                 print_string(pool_found->name);
01365                 print_spaces(MAX_POOL_NAME_LENGTH - strlen(pool_found->name));
01366 #ifdef MEMORY_POOL_STATS
01367                 print("  %10lu", pool_found->used_count);
01368                 total_items = pool_found->num_blocks * pool_found->items_per_block;
01369                 print("  %10lu", total_items - pool_found->used_count);
01370 #endif
01371                 print("  %9lu", pool_found->item_size);
01372                 print("  %11lu\n", pool_found->num_blocks * pool_found->items_per_block * pool_found->item_size);
01373             } else if (argc == 5) {     /* get pool attribute */
01374                 long total_items;
01375 
01376                 total_items = pool_found->num_blocks * pool_found->items_per_block;
01377 
01378                 if (!strcmp("-item-size", argv[4])) {
01379                                         print("%lu", pool_found->item_size);
01380                     /*setSoarResultResult(res, "%lu", pool_found->item_size);*/
01381                 }
01382 #ifdef MEMORY_POOL_STATS
01383                 else if (!strcmp("-used", argv[4])) {
01384                                         print("%lu", pool_found->used_count);
01385                     /*setSoarResultResult(res, "%lu", pool_found->used_count);*/
01386                 } else if (!strcmp("-free", argv[4])) {
01387                                         print("%lu", total_items - pool_found->used_count);
01388                     /*setSoarResultResult(res, "%lu", total_items - pool_found->used_count);*/
01389                 }
01390 #endif
01391                 else if (!strcmp("-total-bytes", argv[4])) {
01392                                         print("%lu",
01393                           pool_found->num_blocks * pool_found->items_per_block * pool_found->item_size);
01394                     /*setSoarResultResult(res, "%lu",
01395                                         pool_found->num_blocks * pool_found->items_per_block * pool_found->item_size);*/
01396                 } else {
01397                     setSoarResultResult(res, "Unrecognized argument to stats: -memory -pool %s %s", argv[3], argv[4]);
01398                     return SOAR_ERROR;
01399                 }
01400             } else {
01401                 setSoarResultResult(res,
01402                                     "Too many arguments, should be: stats -memory -pool [-total | pool-name [<aspect>]]");
01403                 return SOAR_ERROR;
01404             }
01405         }
01406     } else if (!strcmp("-misc", argv[2])) {
01407                 print("%lu", current_agent(memory_for_usage)[MISCELLANEOUS_MEM_USAGE]);
01408         /*setSoarResultResult(res, "%lu", current_agent(memory_for_usage)[MISCELLANEOUS_MEM_USAGE]);*/
01409     } else {
01410         setSoarResultResult(res, "Unrecognized argument to stats: -memory %s", argv[2]);
01411         return SOAR_ERROR;
01412     }
01413 
01414     return SOAR_OK;
01415 }
01416 
01417 /*
01418  *----------------------------------------------------------------------
01419  *
01420  * parse_rete_stats --
01421  *
01422  *      This procedure parses an argv array and prints the selected
01423  *      statistics.
01424  *
01425  *      The syntax being parsed is:
01426  *          stats -rete <rtype> <qualifier>
01427  *          <rtype> ::= unhashed memory
01428  *                      memory
01429  *                      unhashed mem-pos
01430  *                      mem-pos
01431  *                      unhashed negative
01432  *                      negative
01433  *                      unhashed positive
01434  *                      positive
01435  *                      dummy top
01436  *                      dummy matches
01437  *                      nconj. neg.
01438  *                      conj. neg. partner
01439  *                      production
01440  *                      total
01441  *          <qualifier> ::= -actual | -if-no-merging | -if-no-sharing
01442  *
01443  * Results:
01444  *      Returns the statistic and Tcl return code.
01445  *
01446  * Side effects:
01447  *      None.
01448  *
01449  *----------------------------------------------------------------------
01450  */
01451 
01452 int parse_rete_stats(int argc, const char *argv[], soarResult * res)
01453 {
01454     unsigned long data;
01455 
01456     if (argc == 2) {
01457         soar_ecPrintReteStatistics();
01458         return SOAR_OK;
01459     }
01460 
01461     if (argc == 3) {
01462         setSoarResultResult(res, "Too few arguments, should be: stats -rete [type qualifier]");
01463         return SOAR_ERROR;
01464     }
01465 
01466     if (argc > 4) {
01467         setSoarResultResult(res, "Too many arguments, should be: stats -rete [type qualifier]");
01468         return SOAR_ERROR;
01469     }
01470 
01471     if (get_node_count_statistic(argv[2], (char *) argv[3] + 1, &data)) {
01472                 print("%lu", data);
01473         /*setSoarResultResult(res, "%lu", data);*/
01474     } else {
01475         setSoarResultResult(res, "Unrecognized argument to stats: -rete %s %s", argv[2], argv[3]);
01476         return SOAR_ERROR;
01477     }
01478     return SOAR_OK;
01479 }
01480 
01481 /*
01482  *----------------------------------------------------------------------
01483  *
01484  * parse_system_stats --
01485  *
01486  *      This procedure parses an argv array and prints the selected
01487  *      statistics.
01488  *
01489  *      The syntax being parsed is:
01490  *         stats -system <stype>
01491  *         <stype> ::= -default-production-count
01492  *                     -user-production-count
01493  *                     -chunk-count
01494  *                     -justification-count
01495  *                     -all-productions-count
01496  *                     -dc-count
01497  *                     -ec-count
01498  *                     -ecs/dc
01499  *                     -firings-count
01500  *                     -firings/ec
01501  *                     -wme-change-count
01502  *                     -wme-addition-count
01503  *                     -wme-removal-count
01504  *                     -wme-count
01505  *                     -wme-avg-count
01506  *                     -wme-max-count
01507  *                     -total-time             |T
01508  *                     -ms/dc                  |T
01509  *                     -ms/ec                  |T
01510  *                     -ms/firing              |T
01511  *                     -ms/wme-change          |T
01512  *                     -match-time             |D
01513  *                     -ownership-time         |D
01514  *                     -chunking-time          |D
01515  *
01516  *         The items marked |T are available when Soar has been
01517  *         compiled with the NO_TIMING_STUFF flag NOT SET and 
01518  *         the items marked |D are available when Soar has been
01519  *         compiled with the DETAILED_TIMING_STATS flag SET.
01520  *
01521  * Results:
01522  *      Returns the statistic and Tcl return code.
01523  *
01524  * Side effects:
01525  *      None.
01526  *
01527  *----------------------------------------------------------------------
01528  */
01529 
01530 int parse_system_stats(int argc, const char *argv[], soarResult * res)
01531 {
01532 #ifndef NO_TIMING_STUFF
01533     double total_kernel_time, total_kernel_msec;
01534 
01535 #ifdef DETAILED_TIMING_STATS
01536     double time;
01537 #endif
01538 #endif
01539 
01540     if (argc > 3) {
01541         setSoarResultResult(res, "Too many arguments, should be: stats -system [<type>]");
01542         return SOAR_ERROR;
01543     }
01544 
01545     total_kernel_time = timer_value(&current_agent(total_kernel_time));
01546     total_kernel_msec = total_kernel_time * 1000.0;
01547 
01548     if (argc <= 2) {            /* Invoked as stats or stats -system */
01549         soar_ecPrintSystemStatistics();
01550     } else {
01551         if (!strcmp("-default-production-count", argv[2])) {
01552                         print("%lu", current_agent(num_productions_of_type)[DEFAULT_PRODUCTION_TYPE]);
01553             /*setSoarResultResult(res, "%lu", current_agent(num_productions_of_type)[DEFAULT_PRODUCTION_TYPE]);*/
01554         } else if (!strcmp("-user-production-count", argv[2])) {
01555             print("%lu", current_agent(num_productions_of_type)[USER_PRODUCTION_TYPE]);
01556                         /*setSoarResultResult(res, "%lu", current_agent(num_productions_of_type)[USER_PRODUCTION_TYPE]);*/
01557 
01558         } else if (!strcmp("-chunk-count", argv[2])) {
01559                         print("%lu", current_agent(num_productions_of_type)[CHUNK_PRODUCTION_TYPE]);
01560             /*setSoarResultResult(res, "%lu", current_agent(num_productions_of_type)[CHUNK_PRODUCTION_TYPE]);*/
01561         } else if (!strcmp("-justification-count", argv[2])) {
01562                         print("%lu", current_agent(num_productions_of_type)[JUSTIFICATION_PRODUCTION_TYPE]);
01563             /*setSoarResultResult(res, "%lu", current_agent(num_productions_of_type)[JUSTIFICATION_PRODUCTION_TYPE]);*/
01564         } else if (!strcmp("-all-productions-count", argv[2])) {
01565             print("%lu", current_agent(num_productions_of_type)[DEFAULT_PRODUCTION_TYPE]
01566                                 + current_agent(num_productions_of_type)[USER_PRODUCTION_TYPE]
01567                                 + current_agent(num_productions_of_type)[CHUNK_PRODUCTION_TYPE]);
01568 
01569                         /*setSoarResultResult(res, "%lu", current_agent(num_productions_of_type)[DEFAULT_PRODUCTION_TYPE]
01570                                 + current_agent(num_productions_of_type)[USER_PRODUCTION_TYPE]
01571                                 + current_agent(num_productions_of_type)[CHUNK_PRODUCTION_TYPE]);*/
01572 
01573         } else if (!strcmp("-dc-count", argv[2])) {
01574                         print("%lu", current_agent(d_cycle_count));
01575             /*setSoarResultResult(res, "%lu", current_agent(d_cycle_count));*/
01576         } else if (!strcmp("-ec-count", argv[2])) {
01577                         print("%lu", current_agent(e_cycle_count));
01578             /*setSoarResultResult(res, "%lu", current_agent(e_cycle_count));*/
01579         } else if (!strcmp("-ecs/dc", argv[2])) {
01580             print("%.3f", (current_agent(d_cycle_count)
01581                                               ? ((double) current_agent(e_cycle_count)
01582                                                  / current_agent(d_cycle_count))
01583                                               : 0.0));
01584                         /*setSoarResultResult(res, "%.3f", (current_agent(d_cycle_count)
01585                                               ? ((double) current_agent(e_cycle_count)
01586                                                  / current_agent(d_cycle_count))
01587                                               : 0.0));*/
01588         } else if (!strcmp("-firings-count", argv[2])) {
01589                         print("%lu", current_agent(production_firing_count));
01590             /*setSoarResultResult(res, "%lu", current_agent(production_firing_count));*/
01591         } else if (!strcmp("-firings/ec", argv[2])) {
01592                         print("%.3f", (current_agent(e_cycle_count)
01593                                               ? ((double) current_agent(production_firing_count)
01594                                                  / current_agent(e_cycle_count))
01595                                               : 0.0));
01596             /*setSoarResultResult(res, "%.3f", (current_agent(e_cycle_count)
01597                                               ? ((double) current_agent(production_firing_count)
01598                                                  / current_agent(e_cycle_count))
01599                                               : 0.0));*/
01600         } else if (!strcmp("-wme-change-count", argv[2])) {
01601             print("%lu", current_agent(wme_addition_count)
01602                                 + current_agent(wme_removal_count));
01603                         /*setSoarResultResult(res, "%lu", current_agent(wme_addition_count)
01604                                 + current_agent(wme_removal_count));*/
01605         } else if (!strcmp("-wme-addition-count", argv[2])) {
01606                         print("%lu", current_agent(wme_addition_count));
01607             /*setSoarResultResult(res, "%lu", current_agent(wme_addition_count));*/
01608         } else if (!strcmp("-wme-removal-count", argv[2])) {
01609                         print("%lu", current_agent(wme_removal_count));
01610             /*setSoarResultResult(res, "%lu", current_agent(wme_removal_count));*/
01611         } else if (!strcmp("-wme-count", argv[2])) {
01612             setSoarResultResult(res, "%lu", current_agent(num_wmes_in_rete));
01613         } else if (!strcmp("-wme-avg-count", argv[2])) {
01614                         print("%.3f", (current_agent(num_wm_sizes_accumulated)
01615                                               ? (current_agent(cumulative_wm_size)
01616                                                  / current_agent(num_wm_sizes_accumulated))
01617                                               : 0.0));
01618             /*setSoarResultResult(res, "%.3f", (current_agent(num_wm_sizes_accumulated)
01619                                               ? (current_agent(cumulative_wm_size)
01620                                                  / current_agent(num_wm_sizes_accumulated))
01621                                               : 0.0));*/
01622         } else if (!strcmp("-wme-max-count", argv[2])) {
01623                         print("%lu", current_agent(max_wm_size));
01624             /*setSoarResultResult(res, "%lu", current_agent(max_wm_size));*/
01625         }
01626 #ifndef NO_TIMING_STUFF
01627         else if (!strcmp("-total-time", argv[2])) {
01628                         print("%.3f", total_kernel_time);
01629             /*setSoarResultResult(res, "%.3f", total_kernel_time);*/
01630         } else if (!strcmp("-ms/dc", argv[2])) {
01631                         print("%.3f", (current_agent(d_cycle_count)
01632                                               ? total_kernel_msec / current_agent(d_cycle_count)
01633                                               : 0.0));
01634             /*setSoarResultResult(res, "%.3f", (current_agent(d_cycle_count)
01635                                               ? total_kernel_msec / current_agent(d_cycle_count)
01636                                               : 0.0));*/
01637         } else if (!strcmp("-ms/ec", argv[2])) {
01638                         print("%.3f", (current_agent(e_cycle_count)
01639                                               ? total_kernel_msec / current_agent(e_cycle_count)
01640                                               : 0.0));
01641             /*setSoarResultResult(res, "%.3f", (current_agent(e_cycle_count)
01642                                               ? total_kernel_msec / current_agent(e_cycle_count)
01643                                               : 0.0));*/
01644         } else if (!strcmp("-ms/firing", argv[2])) {
01645                         print("%.3f", (current_agent(production_firing_count)
01646                                               ? total_kernel_msec / current_agent(production_firing_count)
01647                                               : 0.0));
01648             /*setSoarResultResult(res, "%.3f", (current_agent(production_firing_count)
01649                                               ? total_kernel_msec / current_agent(production_firing_count)
01650                                               : 0.0));*/
01651         }
01652 #endif                          /* NO_TIMING_STUFF */
01653 #ifdef DETAILED_TIMING_STATS
01654         else if (!strcmp("-ms/wme-change", argv[2])) {
01655             long wme_changes;
01656             time = timer_value(&current_agent(match_cpu_time[INPUT_PHASE]))
01657                 + timer_value(&current_agent(match_cpu_time[DETERMINE_LEVEL_PHASE]))
01658                 + timer_value(&current_agent(match_cpu_time[PREFERENCE_PHASE]))
01659                 + timer_value(&current_agent(match_cpu_time[WM_PHASE]))
01660                 + timer_value(&current_agent(match_cpu_time[OUTPUT_PHASE]))
01661                 + timer_value(&current_agent(match_cpu_time[DECISION_PHASE]));
01662 
01663             time *= 1000;       /* convert to msec */
01664 
01665             wme_changes = current_agent(wme_addition_count)
01666                 + current_agent(wme_removal_count);
01667 
01668                         print("%.3f", (wme_changes ? time / wme_changes : 0.0));
01669             /*setSoarResultResult(res, "%.3f", (wme_changes ? time / wme_changes : 0.0));*/
01670         } else if (!strcmp("-match-time", argv[2])) {
01671 
01672             time = timer_value(&current_agent(match_cpu_time[INPUT_PHASE]))
01673                 + timer_value(&current_agent(match_cpu_time[DETERMINE_LEVEL_PHASE]))
01674                 + timer_value(&current_agent(match_cpu_time[PREFERENCE_PHASE]))
01675                 + timer_value(&current_agent(match_cpu_time[WM_PHASE]))
01676                 + timer_value(&current_agent(match_cpu_time[OUTPUT_PHASE]))
01677                 + timer_value(&current_agent(match_cpu_time[DECISION_PHASE]));
01678 
01679                         print("%.3f", time);
01680             /*setSoarResultResult(res, "%.3f", time);*/
01681 
01682         } else if (!strcmp("-ownership-time", argv[2])) {
01683             time = timer_value(&current_agent(ownership_cpu_time[INPUT_PHASE]))
01684                 + timer_value(&current_agent(ownership_cpu_time[DETERMINE_LEVEL_PHASE]))
01685                 + timer_value(&current_agent(ownership_cpu_time[PREFERENCE_PHASE]))
01686                 + timer_value(&current_agent(ownership_cpu_time[WM_PHASE]))
01687                 + timer_value(&current_agent(ownership_cpu_time[OUTPUT_PHASE]))
01688                 + timer_value(&current_agent(ownership_cpu_time[DECISION_PHASE]));
01689 
01690             print("%.3f", time);
01691                         /*setSoarResultResult(res, "%.3f", time);*/
01692 
01693         } else if (!strcmp("-chunking-time", argv[2])) {
01694             time = timer_value(&current_agent(chunking_cpu_time[INPUT_PHASE]))
01695                 + timer_value(&current_agent(chunking_cpu_time[DETERMINE_LEVEL_PHASE]))
01696                 + timer_value(&current_agent(chunking_cpu_time[PREFERENCE_PHASE]))
01697                 + timer_value(&current_agent(chunking_cpu_time[WM_PHASE]))
01698                 + timer_value(&current_agent(chunking_cpu_time[OUTPUT_PHASE]))
01699                 + timer_value(&current_agent(chunking_cpu_time[DECISION_PHASE]));
01700 
01701                         print("%.3f", time);
01702             /*setSoarResultResult(res, "%.3f", time);*/
01703 
01704         }
01705 #endif                          /* DETAILED_TIMING_STATS */
01706         else {
01707             setSoarResultResult(res, "Unrecognized argument to stats: -system %s", argv[2]);
01708         }
01709     }
01710 
01711     return SOAR_OK;
01712 }
01713 
01714 int printTimingInfo()
01715 {
01716 
01717 #ifdef PII_TIMERS
01718     unsigned long long int start, stop;
01719 #else
01720     struct timeval start, stop;
01721 #endif
01722 
01723     double min, max, min_nz;
01724 
01725     min_nz = soar_cDetermineTimerResolution(&min, &max);
01726 
01727 #ifdef PII_TIMERS
01728     print("Using Pentium II Time Stamp -- Assuming %d MHZ Processor...\n", MHZ);
01729 #else
01730     print("Using system timers...\n");
01731 #endif
01732 
01733     print("---------------------------------------------------------------\n");
01734     print("A timing loop is used to obtain the following values.\n");
01735     print("At least one additional instruction takes place between\n");
01736     print("starting and stopping the timers, thus a perfectly accurate\n");
01737     print("timer which costs nothing to invoke would still accumulate\n");
01738     print("non-zero value. The loop runs for a total of ~2 seconds as \n");
01739     print("a result, the Maximum timer value is likely to be relatively \n");
01740     print("large, but should be < 2 seconds\n");
01741     print("** NOTE: If the code was optimized, the timing loop may yield\n");
01742     print("         unanticipated results.  If both minimum values are\n");
01743     print("         zero, it is unclear what the timer resolution is...\n");
01744     print("---------------------------------------------------------------\n");
01745     print("Minimum (Non-Zero) Timer Value: %11.5e sec\n", min_nz);
01746     print("Minimum Timer Value           : %11.5e sec\n", min);
01747     print("Maximum Timer Value           : %11.5e sec\n\n", max);
01748 
01749     print("---------------------------------------------------------------\n");
01750     print("A short delay will be issued using the sleep() command, and \n");
01751     print("timed using Soar's timers....\n");
01752     reset_timer(&stop);
01753     start_timer(&start);
01754     sys_sleep(3);
01755     stop_timer(&start, &stop);
01756     print("Sleep interval  -->   3 seconds\n");
01757     print("Timers report   -->  %8.5f seconds\n", timer_value(&stop));
01758     print("---------------------------------------------------------------\n");
01759 
01760     return 1;
01761 
01762 }

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