00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include "soarkernel.h"
00051 #include <ctype.h>
00052
00053
00054
00055 enum trace_format_type {
00056 STRING_TFT,
00057 PERCENT_TFT,
00058 L_BRACKET_TFT,
00059 R_BRACKET_TFT,
00060 VALUES_TFT,
00061 VALUES_RECURSIVELY_TFT,
00062 ATTS_AND_VALUES_TFT,
00063 ATTS_AND_VALUES_RECURSIVELY_TFT,
00064 CURRENT_STATE_TFT,
00065 CURRENT_OPERATOR_TFT,
00066 DECISION_CYCLE_COUNT_TFT,
00067 ELABORATION_CYCLE_COUNT_TFT,
00068 IDENTIFIER_TFT,
00069 IF_ALL_DEFINED_TFT,
00070 LEFT_JUSTIFY_TFT,
00071 RIGHT_JUSTIFY_TFT,
00072 SUBGOAL_DEPTH_TFT,
00073 REPEAT_SUBGOAL_DEPTH_TFT,
00074 NEWLINE_TFT
00075 };
00076
00077
00078
00079 typedef struct trace_format_struct {
00080 struct trace_format_struct *next;
00081 enum trace_format_type type;
00082 int num;
00083 union trace_format_data_union {
00084 char *string;
00085 struct trace_format_struct *subformat;
00086 list *attribute_path;
00087 } data;
00088 } trace_format;
00089
00090
00091
00092
00093
00094
00095
00096 void deallocate_trace_format_list(trace_format * tf)
00097 {
00098 trace_format *next;
00099
00100 while (tf) {
00101 switch (tf->type) {
00102 case STRING_TFT:
00103 free_memory_block_for_string(tf->data.string);
00104 break;
00105
00106 case VALUES_TFT:
00107 case VALUES_RECURSIVELY_TFT:
00108 case ATTS_AND_VALUES_TFT:
00109 case ATTS_AND_VALUES_RECURSIVELY_TFT:
00110 deallocate_symbol_list_removing_references(tf->data.attribute_path);
00111 break;
00112
00113 case IF_ALL_DEFINED_TFT:
00114 case LEFT_JUSTIFY_TFT:
00115 case RIGHT_JUSTIFY_TFT:
00116 case REPEAT_SUBGOAL_DEPTH_TFT:
00117 deallocate_trace_format_list(tf->data.subformat);
00118 break;
00119
00120 default:
00121 break;
00122 }
00123 next = tf->next;
00124 free_memory(tf, MISCELLANEOUS_MEM_USAGE);
00125 tf = next;
00126 }
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 const char *format;
00156 char *format_string_error_message;
00157
00158 trace_format *parse_item_from_format_string(void);
00159
00160 trace_format *parse_format_string(const char *string)
00161 {
00162 trace_format *first, *prev, *new;
00163
00164 format = string;
00165 format_string_error_message = NIL;
00166
00167 prev = NIL;
00168 first = NIL;
00169 while (*format != 0) {
00170 new = parse_item_from_format_string();
00171 if (!new) {
00172 if (prev)
00173 prev->next = NIL;
00174 else
00175 first = NIL;
00176 deallocate_trace_format_list(first);
00177 print("Error: bad trace format string: %s\n", string);
00178 if (format_string_error_message) {
00179 print(" %s\n", format_string_error_message);
00180 print(" Error found at: %s\n", format);
00181 }
00182 return NIL;
00183 }
00184 if (prev)
00185 prev->next = new;
00186 else
00187 first = new;
00188 prev = new;
00189 }
00190 if (prev)
00191 prev->next = NIL;
00192 else
00193 first = NIL;
00194
00195 return first;
00196 }
00197
00198 list *parse_attribute_path_in_brackets(void)
00199 {
00200 list *path;
00201 char name[MAX_LEXEME_LENGTH + 20], *ch;
00202 Symbol *sym;
00203
00204
00205 if (*format != '[') {
00206 format_string_error_message = "Expected '[' followed by attribute (path)";
00207 return NIL;
00208 }
00209 format++;
00210
00211
00212 if (*format == '*') {
00213 path = NIL;
00214 format++;
00215 } else {
00216
00217 path = NIL;
00218 for (;;) {
00219 ch = name;
00220 while ((*format != 0) && (*format != ']') && (*format != '.'))
00221 *ch++ = *format++;
00222 if (*format == 0) {
00223 format_string_error_message = "'[' without closing ']'";
00224 deallocate_symbol_list_removing_references(path);
00225 return NIL;
00226 }
00227 if (ch == name) {
00228 format_string_error_message = "null attribute found in attribute path";
00229 deallocate_symbol_list_removing_references(path);
00230 return NIL;
00231 }
00232 *ch = 0;
00233 sym = make_sym_constant(name);
00234 push(sym, path);
00235 if (*format == ']')
00236 break;
00237 format++;
00238 }
00239 path = destructively_reverse_list(path);
00240 }
00241
00242
00243 if (*format != ']') {
00244 format_string_error_message = "'[' without closing ']'";
00245 deallocate_symbol_list_removing_references(path);
00246 return NIL;
00247 }
00248 format++;
00249
00250 return path;
00251 }
00252
00253 trace_format *parse_pattern_in_brackets(bool read_opening_bracket)
00254 {
00255 trace_format *first, *prev, *new;
00256
00257
00258 if (read_opening_bracket) {
00259 if (*format != '[') {
00260 format_string_error_message = "Expected '[' followed by attribute path";
00261 return NIL;
00262 }
00263 format++;
00264 }
00265
00266
00267 prev = NIL;
00268 first = NIL;
00269 while ((*format != 0) && (*format != ']')) {
00270 new = parse_item_from_format_string();
00271 if (!new) {
00272 if (prev)
00273 prev->next = NIL;
00274 else
00275 first = NIL;
00276 deallocate_trace_format_list(first);
00277 return NIL;
00278 }
00279 if (prev)
00280 prev->next = new;
00281 else
00282 first = new;
00283 prev = new;
00284 }
00285 if (prev)
00286 prev->next = NIL;
00287 else
00288 first = NIL;
00289
00290
00291 if (*format != ']') {
00292 format_string_error_message = "'[' without closing ']'";
00293 deallocate_trace_format_list(first);
00294 return NIL;
00295 }
00296 format++;
00297
00298 return first;
00299 }
00300
00301 trace_format *parse_item_from_format_string(void)
00302 {
00303 trace_format *tf, *pattern;
00304 char *ch;
00305 list *attribute_path;
00306 int n;
00307
00308 if (*format == 0)
00309 return NIL;
00310 if (*format == ']')
00311 return NIL;
00312 if (*format == '[') {
00313 format_string_error_message = "unexpected '[' character";
00314 return NIL;
00315 }
00316
00317 if (*format != '%') {
00318 char buf[MAX_LEXEME_LENGTH + 20];
00319
00320 ch = buf;
00321 while ((*format != 0) && (*format != '%') && (*format != '[') && (*format != ']'))
00322 *ch++ = *format++;
00323 *ch = 0;
00324 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00325 tf->type = STRING_TFT;
00326 tf->data.string = make_memory_block_for_string(buf);
00327 return tf;
00328 }
00329
00330
00331
00332 if (!strncmp(format, "%v", 2)) {
00333 format += 2;
00334 attribute_path = parse_attribute_path_in_brackets();
00335 if (format_string_error_message)
00336 return NIL;
00337 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00338 tf->type = VALUES_TFT;
00339 tf->data.attribute_path = attribute_path;
00340 return tf;
00341 }
00342
00343 if (!strncmp(format, "%o", 2)) {
00344 format += 2;
00345 attribute_path = parse_attribute_path_in_brackets();
00346 if (format_string_error_message)
00347 return NIL;
00348 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00349 tf->type = VALUES_RECURSIVELY_TFT;
00350 tf->data.attribute_path = attribute_path;
00351 return tf;
00352 }
00353
00354 if (!strncmp(format, "%av", 3)) {
00355 format += 3;
00356 attribute_path = parse_attribute_path_in_brackets();
00357 if (format_string_error_message)
00358 return NIL;
00359 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00360 tf->type = ATTS_AND_VALUES_TFT;
00361 tf->data.attribute_path = attribute_path;
00362 return tf;
00363 }
00364
00365 if (!strncmp(format, "%ao", 3)) {
00366 format += 3;
00367 attribute_path = parse_attribute_path_in_brackets();
00368 if (format_string_error_message)
00369 return NIL;
00370 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00371 tf->type = ATTS_AND_VALUES_RECURSIVELY_TFT;
00372 tf->data.attribute_path = attribute_path;
00373 return tf;
00374 }
00375
00376 if (!strncmp(format, "%cs", 3)) {
00377 format += 3;
00378 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00379 tf->type = CURRENT_STATE_TFT;
00380 return tf;
00381 }
00382
00383 if (!strncmp(format, "%co", 3)) {
00384 format += 3;
00385 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00386 tf->type = CURRENT_OPERATOR_TFT;
00387 return tf;
00388 }
00389
00390 if (!strncmp(format, "%dc", 3)) {
00391 format += 3;
00392 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00393 tf->type = DECISION_CYCLE_COUNT_TFT;
00394 return tf;
00395 }
00396
00397 if (!strncmp(format, "%ec", 3)) {
00398 format += 3;
00399 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00400 tf->type = ELABORATION_CYCLE_COUNT_TFT;
00401 return tf;
00402 }
00403
00404 if (!strncmp(format, "%%", 2)) {
00405 format += 2;
00406 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00407 tf->type = PERCENT_TFT;
00408 return tf;
00409 }
00410
00411 if (!strncmp(format, "%[", 2)) {
00412 format += 2;
00413 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00414 tf->type = L_BRACKET_TFT;
00415 return tf;
00416 }
00417
00418 if (!strncmp(format, "%]", 2)) {
00419 format += 2;
00420 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00421 tf->type = R_BRACKET_TFT;
00422 return tf;
00423 }
00424
00425 if (!strncmp(format, "%sd", 3)) {
00426 format += 3;
00427 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00428 tf->type = SUBGOAL_DEPTH_TFT;
00429 return tf;
00430 }
00431
00432 if (!strncmp(format, "%id", 3)) {
00433 format += 3;
00434 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00435 tf->type = IDENTIFIER_TFT;
00436 return tf;
00437 }
00438
00439 if (!strncmp(format, "%ifdef", 6)) {
00440 format += 6;
00441 pattern = parse_pattern_in_brackets(TRUE);
00442 if (format_string_error_message)
00443 return NIL;
00444 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00445 tf->type = IF_ALL_DEFINED_TFT;
00446 tf->data.subformat = pattern;
00447 return tf;
00448 }
00449
00450 if (!strncmp(format, "%left", 5)) {
00451 format += 5;
00452 if (*format != '[') {
00453 format_string_error_message = "Expected '[' after %left";
00454 return NIL;
00455 }
00456 format++;
00457 if (!isdigit(*format)) {
00458 format_string_error_message = "Expected number with %left";
00459 return NIL;
00460 }
00461 n = 0;
00462 while (isdigit(*format))
00463 n = 10 * n + (*format++ - '0');
00464 if (*format != ',') {
00465 format_string_error_message = "Expected ',' after number in %left";
00466 return NIL;
00467 }
00468 format++;
00469 pattern = parse_pattern_in_brackets(FALSE);
00470 if (format_string_error_message)
00471 return NIL;
00472 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00473 tf->type = LEFT_JUSTIFY_TFT;
00474 tf->num = n;
00475 tf->data.subformat = pattern;
00476 return tf;
00477 }
00478
00479 if (!strncmp(format, "%right", 6)) {
00480 format += 6;
00481 if (*format != '[') {
00482 format_string_error_message = "Expected '[' after %right";
00483 return NIL;
00484 }
00485 format++;
00486 if (!isdigit(*format)) {
00487 format_string_error_message = "Expected number with %right";
00488 return NIL;
00489 }
00490 n = 0;
00491 while (isdigit(*format))
00492 n = 10 * n + (*format++ - '0');
00493 if (*format != ',') {
00494 format_string_error_message = "Expected ',' after number in %right";
00495 return NIL;
00496 }
00497 format++;
00498 pattern = parse_pattern_in_brackets(FALSE);
00499 if (format_string_error_message)
00500 return NIL;
00501 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00502 tf->type = RIGHT_JUSTIFY_TFT;
00503 tf->num = n;
00504 tf->data.subformat = pattern;
00505 return tf;
00506 }
00507
00508 if (!strncmp(format, "%rsd", 4)) {
00509 format += 4;
00510 pattern = parse_pattern_in_brackets(TRUE);
00511 if (format_string_error_message)
00512 return NIL;
00513 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00514 tf->type = REPEAT_SUBGOAL_DEPTH_TFT;
00515 tf->data.subformat = pattern;
00516 return tf;
00517 }
00518
00519 if (!strncmp(format, "%nl", 3)) {
00520 format += 3;
00521 tf = allocate_memory(sizeof(trace_format), MISCELLANEOUS_MEM_USAGE);
00522 tf->type = NEWLINE_TFT;
00523 return tf;
00524 }
00525
00526
00527 format_string_error_message = "Unrecognized escape sequence";
00528 return NIL;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538 void print_trace_format_list(trace_format * tf)
00539 {
00540 cons *c;
00541
00542 for (; tf != NIL; tf = tf->next) {
00543 switch (tf->type) {
00544 case STRING_TFT:
00545 {
00546 char *s;
00547 int i, len;
00548
00549 s = string_to_escaped_string(tf->data.string, '"', NULL);
00550 len = strlen(s);
00551 for (i = 1; i < len - 1; i++)
00552 print("%c", *(s + i));
00553 }
00554 break;
00555 case PERCENT_TFT:
00556 print_string("%%");
00557 break;
00558 case L_BRACKET_TFT:
00559 print_string("%[");
00560 break;
00561 case R_BRACKET_TFT:
00562 print_string("%]");
00563 break;
00564
00565 case VALUES_TFT:
00566 case VALUES_RECURSIVELY_TFT:
00567 case ATTS_AND_VALUES_TFT:
00568 case ATTS_AND_VALUES_RECURSIVELY_TFT:
00569 if (tf->type == VALUES_TFT)
00570 print_string("%v[");
00571 else if (tf->type == VALUES_RECURSIVELY_TFT)
00572 print_string("%o[");
00573 else if (tf->type == ATTS_AND_VALUES_TFT)
00574 print_string("%av[");
00575 else
00576 print_string("%ao[");
00577 if (tf->data.attribute_path) {
00578 for (c = tf->data.attribute_path; c != NIL; c = c->rest) {
00579 print_string(((Symbol *) (c->first))->sc.name);
00580 if (c->rest)
00581 print_string(".");
00582 }
00583 } else {
00584 print_string("*");
00585 }
00586 print_string("]");
00587 break;
00588
00589 case CURRENT_STATE_TFT:
00590 print_string("%cs");
00591 break;
00592 case CURRENT_OPERATOR_TFT:
00593 print_string("%co");
00594 break;
00595 case DECISION_CYCLE_COUNT_TFT:
00596 print_string("%dc");
00597 break;
00598 case ELABORATION_CYCLE_COUNT_TFT:
00599 print_string("%ec");
00600 break;
00601 case IDENTIFIER_TFT:
00602 print_string("%id");
00603 break;
00604
00605 case IF_ALL_DEFINED_TFT:
00606 print_string("%ifdef[");
00607 print_trace_format_list(tf->data.subformat);
00608 print_string("]");
00609 break;
00610
00611 case LEFT_JUSTIFY_TFT:
00612 case RIGHT_JUSTIFY_TFT:
00613 if (tf->type == LEFT_JUSTIFY_TFT)
00614 print_string("%left[");
00615 else
00616 print_string("%right[");
00617 print("%d,", tf->num);
00618 print_trace_format_list(tf->data.subformat);
00619 print_string("]");
00620 break;
00621
00622 case SUBGOAL_DEPTH_TFT:
00623 print_string("%sd");
00624 break;
00625
00626 case REPEAT_SUBGOAL_DEPTH_TFT:
00627 print_string("%rsd[");
00628 print_trace_format_list(tf->data.subformat);
00629 print_string("]");
00630 break;
00631
00632 case NEWLINE_TFT:
00633 print_string("%nl");
00634 break;
00635
00636 default:
00637 {
00638 char msg[MESSAGE_SIZE];
00639 strncpy(msg, "Internal error: bad trace format type\n", MESSAGE_SIZE);
00640 msg[MESSAGE_SIZE - 1] = 0;
00641 abort_with_fatal_error(msg);
00642 }
00643 }
00644 }
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 typedef struct tracing_rule_struct {
00684
00685 struct tracing_rule_struct *next_in_hash_bucket;
00686 int type_restriction;
00687 Symbol *name_restriction;
00688 trace_format *format;
00689 } tracing_rule;
00690
00691 #define hash_name_restriction(name,num_bits) \
00692 ((name)->common.hash_id & masks_for_n_low_order_bits[(num_bits)])
00693
00694
00695 unsigned long tracing_rule_hash_function(void *item, short num_bits)
00696 {
00697 tracing_rule *tr;
00698
00699 tr = item;
00700 return hash_name_restriction(tr->name_restriction, num_bits);
00701 }
00702
00703
00704
00705 void init_tracing(void)
00706 {
00707 int i;
00708
00709 for (i = 0; i < 3; i++) {
00710 current_agent(object_tr_ht)[i] = make_hash_table(0, tracing_rule_hash_function);
00711 current_agent(stack_tr_ht)[i] = make_hash_table(0, tracing_rule_hash_function);
00712 current_agent(object_tf_for_anything)[i] = NIL;
00713 current_agent(stack_tf_for_anything)[i] = NIL;
00714 }
00715 }
00716
00717 trace_format *lookup_trace_format(bool stack_trace, int type_restriction, Symbol * name_restriction)
00718 {
00719 unsigned long hash_value;
00720 hash_table *ht;
00721 tracing_rule *tr;
00722
00723 if (name_restriction) {
00724 if (stack_trace)
00725 ht = current_agent(stack_tr_ht)[type_restriction];
00726 else
00727 ht = current_agent(object_tr_ht)[type_restriction];
00728 hash_value = hash_name_restriction(name_restriction, ht->log2size);
00729 tr = (tracing_rule *) (*(ht->buckets + hash_value));
00730 for (; tr != NIL; tr = tr->next_in_hash_bucket)
00731 if (tr->name_restriction == name_restriction)
00732 return tr->format;
00733 return NIL;
00734 }
00735
00736 if (stack_trace)
00737 return current_agent(stack_tf_for_anything)[type_restriction];
00738 else
00739 return current_agent(object_tf_for_anything)[type_restriction];
00740 }
00741
00742 bool remove_trace_format(bool stack_trace, int type_restriction, Symbol * name_restriction)
00743 {
00744 unsigned long hash_value;
00745 hash_table *ht;
00746 tracing_rule *tr;
00747 trace_format **format;
00748
00749 if (name_restriction) {
00750 if (stack_trace)
00751 ht = current_agent(stack_tr_ht)[type_restriction];
00752 else
00753 ht = current_agent(object_tr_ht)[type_restriction];
00754 hash_value = hash_name_restriction(name_restriction, ht->log2size);
00755 tr = (tracing_rule *) (*(ht->buckets + hash_value));
00756 for (; tr != NIL; tr = tr->next_in_hash_bucket)
00757 if (tr->name_restriction == name_restriction)
00758 break;
00759 if (!tr)
00760 return FALSE;
00761 deallocate_trace_format_list(tr->format);
00762 remove_from_hash_table(ht, tr);
00763 free_memory(tr, MISCELLANEOUS_MEM_USAGE);
00764 symbol_remove_ref(name_restriction);
00765 return TRUE;
00766 }
00767
00768 if (stack_trace)
00769 format = &(current_agent(stack_tf_for_anything)[type_restriction]);
00770 else
00771 format = &(current_agent(object_tf_for_anything)[type_restriction]);
00772 if (!*format)
00773 return FALSE;
00774 deallocate_trace_format_list(*format);
00775 *format = NIL;
00776 return TRUE;
00777 }
00778
00779 bool add_trace_format(bool stack_trace, int type_restriction, Symbol * name_restriction, const char *format_string)
00780 {
00781 tracing_rule *tr;
00782 trace_format *new_tf;
00783 hash_table *ht;
00784
00785
00786 new_tf = parse_format_string(format_string);
00787 if (!new_tf)
00788 return FALSE;
00789
00790
00791 remove_trace_format(stack_trace, type_restriction, name_restriction);
00792
00793
00794 if (name_restriction) {
00795 symbol_add_ref(name_restriction);
00796 if (stack_trace)
00797 ht = current_agent(stack_tr_ht)[type_restriction];
00798 else
00799 ht = current_agent(object_tr_ht)[type_restriction];
00800 tr = allocate_memory(sizeof(tracing_rule), MISCELLANEOUS_MEM_USAGE);
00801 tr->type_restriction = type_restriction;
00802 tr->name_restriction = name_restriction;
00803 tr->format = new_tf;
00804 add_to_hash_table(ht, tr);
00805 return TRUE;
00806 }
00807
00808 if (stack_trace)
00809 current_agent(stack_tf_for_anything)[type_restriction] = new_tf;
00810 else
00811 current_agent(object_tf_for_anything)[type_restriction] = new_tf;
00812
00813 return TRUE;
00814 }
00815
00816 char tracing_object_letters[3] = { '*', 's', 'o' };
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 void print_tracing_rule(int type_restriction, Symbol * name_restriction, trace_format * format)
00829 {
00830 print("%c ", tracing_object_letters[type_restriction]);
00831 if (name_restriction)
00832 print_with_symbols("%y ", name_restriction);
00833 print_string("{");
00834 print_trace_format_list(format);
00835 print("}\n");
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 bool print_trace_callback_fn(void *item)
00849 {
00850 tracing_rule *tr;
00851
00852 tr = item;
00853 print_tracing_rule(tr->type_restriction, tr->name_restriction, tr->format);
00854 return FALSE;
00855 }
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868 void print_all_trace_formats(bool stack_trace)
00869 {
00870 int i;
00871
00872 current_agent(printing_stack_traces) = stack_trace;
00873 if (stack_trace) {
00874 for (i = 0; i < 3; i++) {
00875 if (current_agent(stack_tf_for_anything)[i])
00876 print_tracing_rule(i, NIL, current_agent(stack_tf_for_anything)[i]);
00877 do_for_all_items_in_hash_table(current_agent(stack_tr_ht)[i], print_trace_callback_fn);
00878 }
00879 } else {
00880 for (i = 0; i < 3; i++) {
00881 if (current_agent(object_tf_for_anything)[i])
00882 print_tracing_rule(i, NIL, current_agent(object_tf_for_anything)[i]);
00883 do_for_all_items_in_hash_table(current_agent(object_tr_ht)[i], print_trace_callback_fn);
00884 }
00885 }
00886 }
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897 growable_string object_to_trace_string(Symbol * object);
00898
00899 bool found_undefined;
00900
00901
00902 struct tracing_parameters {
00903 Symbol *current_s;
00904 Symbol *current_o;
00905 bool allow_cycle_counts;
00906 } tparams;
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917 void add_values_of_attribute_path(Symbol * object, list * path, growable_string * result, bool recursive, int *count)
00918 {
00919 slot *s;
00920 wme *w;
00921 char *ch;
00922 growable_string gs;
00923
00924 if (!path) {
00925 add_to_growable_string(result, " ");
00926 if (recursive) {
00927 gs = object_to_trace_string(object);
00928 add_to_growable_string(result, text_of_growable_string(gs));
00929 free_growable_string(gs);
00930 } else {
00931 ch = symbol_to_string(object, TRUE, NULL, 0);
00932 add_to_growable_string(result, ch);
00933 }
00934 (*count)++;
00935 return;
00936 }
00937
00938
00939
00940 if (object->common.symbol_type != IDENTIFIER_SYMBOL_TYPE)
00941 return;
00942
00943
00944
00945 for (w = object->id.impasse_wmes; w != NIL; w = w->next)
00946 if (w->attr == path->first)
00947 add_values_of_attribute_path(w->value, path->rest, result, recursive, count);
00948 for (w = object->id.input_wmes; w != NIL; w = w->next)
00949 if (w->attr == path->first)
00950 add_values_of_attribute_path(w->value, path->rest, result, recursive, count);
00951 s = find_slot(object, path->first);
00952 if (s) {
00953 for (w = s->wmes; w != NIL; w = w->next)
00954 add_values_of_attribute_path(w->value, path->rest, result, recursive, count);
00955 }
00956 }
00957
00958
00959
00960
00961
00962
00963
00964
00965 void add_trace_for_wme(growable_string * result, wme * w, bool print_attribute, bool recursive)
00966 {
00967 char *ch;
00968 growable_string gs;
00969
00970 add_to_growable_string(result, " ");
00971 if (print_attribute) {
00972 add_to_growable_string(result, "^");
00973 ch = symbol_to_string(w->attr, TRUE, NULL, 0);
00974 add_to_growable_string(result, ch);
00975 add_to_growable_string(result, " ");
00976 }
00977 if (recursive) {
00978 gs = object_to_trace_string(w->value);
00979 add_to_growable_string(result, text_of_growable_string(gs));
00980 free_growable_string(gs);
00981 } else {
00982 ch = symbol_to_string(w->value, TRUE, NULL, 0);
00983 add_to_growable_string(result, ch);
00984 }
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 void add_trace_for_attribute_path(Symbol * object,
00998 list * path, growable_string * result, bool print_attributes, bool recursive)
00999 {
01000 growable_string values;
01001 cons *c;
01002 char *ch;
01003 int count;
01004 slot *s;
01005 wme *w;
01006
01007 values = make_blank_growable_string();
01008
01009 if (!path) {
01010 if (object->common.symbol_type != IDENTIFIER_SYMBOL_TYPE)
01011 return;
01012 for (s = object->id.slots; s != NIL; s = s->next)
01013 for (w = s->wmes; w != NIL; w = w->next)
01014 add_trace_for_wme(&values, w, print_attributes, recursive);
01015 for (w = object->id.impasse_wmes; w != NIL; w = w->next)
01016 add_trace_for_wme(&values, w, print_attributes, recursive);
01017 for (w = object->id.input_wmes; w != NIL; w = w->next)
01018 add_trace_for_wme(&values, w, print_attributes, recursive);
01019 if (length_of_growable_string(values) > 0)
01020 add_to_growable_string(result, text_of_growable_string(values) + 1);
01021 free_growable_string(values);
01022 return;
01023 }
01024
01025 count = 0;
01026 add_values_of_attribute_path(object, path, &values, recursive, &count);
01027 if (!count) {
01028 found_undefined = TRUE;
01029 free_growable_string(values);
01030 return;
01031 }
01032
01033 if (print_attributes) {
01034 add_to_growable_string(result, "^");
01035 for (c = path; c != NIL; c = c->rest) {
01036 ch = symbol_to_string(c->first, TRUE, NULL, 0);
01037 add_to_growable_string(result, ch);
01038 if (c->rest)
01039 add_to_growable_string(result, ".");
01040 }
01041 add_to_growable_string(result, " ");
01042 }
01043 if (length_of_growable_string(values) > 0)
01044 add_to_growable_string(result, text_of_growable_string(values) + 1);
01045 free_growable_string(values);
01046 }
01047
01048
01049
01050
01051
01052
01053
01054 #define TRACE_FORMAT_LIST_TO_STRING_BUF_SIZE 50
01055 growable_string trace_format_list_to_string(trace_format * tf, Symbol * object)
01056 {
01057 char buf[TRACE_FORMAT_LIST_TO_STRING_BUF_SIZE], *ch;
01058 growable_string result, temp_gs;
01059 int i;
01060
01061 result = make_blank_growable_string();
01062
01063 for (; tf != NIL; tf = tf->next) {
01064 switch (tf->type) {
01065 case STRING_TFT:
01066 add_to_growable_string(&result, tf->data.string);
01067 break;
01068 case PERCENT_TFT:
01069 add_to_growable_string(&result, "%");
01070 break;
01071 case L_BRACKET_TFT:
01072 add_to_growable_string(&result, "[");
01073 break;
01074 case R_BRACKET_TFT:
01075 add_to_growable_string(&result, "]");
01076 break;
01077
01078 case VALUES_TFT:
01079 add_trace_for_attribute_path(object, tf->data.attribute_path, &result, FALSE, FALSE);
01080 break;
01081 case VALUES_RECURSIVELY_TFT:
01082 add_trace_for_attribute_path(object, tf->data.attribute_path, &result, FALSE, TRUE);
01083 break;
01084 case ATTS_AND_VALUES_TFT:
01085 add_trace_for_attribute_path(object, tf->data.attribute_path, &result, TRUE, FALSE);
01086 break;
01087 case ATTS_AND_VALUES_RECURSIVELY_TFT:
01088 add_trace_for_attribute_path(object, tf->data.attribute_path, &result, TRUE, TRUE);
01089 break;
01090
01091 case CURRENT_STATE_TFT:
01092 if (!tparams.current_s) {
01093 found_undefined = TRUE;
01094 } else {
01095 temp_gs = object_to_trace_string(tparams.current_s);
01096 add_to_growable_string(&result, text_of_growable_string(temp_gs));
01097 free_growable_string(temp_gs);
01098 }
01099 break;
01100 case CURRENT_OPERATOR_TFT:
01101 if (!tparams.current_o) {
01102 found_undefined = TRUE;
01103 } else {
01104 temp_gs = object_to_trace_string(tparams.current_o);
01105 add_to_growable_string(&result, text_of_growable_string(temp_gs));
01106 free_growable_string(temp_gs);
01107 }
01108 break;
01109
01110 case DECISION_CYCLE_COUNT_TFT:
01111 if (tparams.allow_cycle_counts) {
01112 snprintf(buf, TRACE_FORMAT_LIST_TO_STRING_BUF_SIZE, "%lu", current_agent(d_cycle_count));
01113 buf[TRACE_FORMAT_LIST_TO_STRING_BUF_SIZE - 1] = 0;
01114 add_to_growable_string(&result, buf);
01115 } else {
01116 found_undefined = TRUE;
01117 }
01118 break;
01119 case ELABORATION_CYCLE_COUNT_TFT:
01120 if (tparams.allow_cycle_counts) {
01121 snprintf(buf, TRACE_FORMAT_LIST_TO_STRING_BUF_SIZE, "%lu", current_agent(e_cycle_count));
01122 buf[TRACE_FORMAT_LIST_TO_STRING_BUF_SIZE - 1] = 0;
01123 add_to_growable_string(&result, buf);
01124 } else {
01125 found_undefined = TRUE;
01126 }
01127 break;
01128
01129 case IDENTIFIER_TFT:
01130 ch = symbol_to_string(object, TRUE, NULL, 0);
01131 add_to_growable_string(&result, ch);
01132 break;
01133
01134 case IF_ALL_DEFINED_TFT:
01135 {
01136 bool saved_found_undefined;
01137 saved_found_undefined = found_undefined;
01138 found_undefined = FALSE;
01139 temp_gs = trace_format_list_to_string(tf->data.subformat, object);
01140 if (!found_undefined)
01141 add_to_growable_string(&result, text_of_growable_string(temp_gs));
01142 free_growable_string(temp_gs);
01143 found_undefined = saved_found_undefined;
01144 }
01145 break;
01146
01147 case LEFT_JUSTIFY_TFT:
01148 temp_gs = trace_format_list_to_string(tf->data.subformat, object);
01149 add_to_growable_string(&result, text_of_growable_string(temp_gs));
01150 for (i = tf->num - length_of_growable_string(temp_gs); i > 0; i--)
01151 add_to_growable_string(&result, " ");
01152 free_growable_string(temp_gs);
01153 break;
01154
01155 case RIGHT_JUSTIFY_TFT:
01156 temp_gs = trace_format_list_to_string(tf->data.subformat, object);
01157 for (i = tf->num - length_of_growable_string(temp_gs); i > 0; i--)
01158 add_to_growable_string(&result, " ");
01159 add_to_growable_string(&result, text_of_growable_string(temp_gs));
01160 free_growable_string(temp_gs);
01161 break;
01162
01163 case SUBGOAL_DEPTH_TFT:
01164 if (tparams.current_s) {
01165 snprintf(buf, TRACE_FORMAT_LIST_TO_STRING_BUF_SIZE, "%u", tparams.current_s->id.level - 1);
01166 buf[TRACE_FORMAT_LIST_TO_STRING_BUF_SIZE - 1] = 0;
01167 add_to_growable_string(&result, buf);
01168 } else {
01169 found_undefined = TRUE;
01170 }
01171 break;
01172
01173 case REPEAT_SUBGOAL_DEPTH_TFT:
01174 if (tparams.current_s) {
01175 temp_gs = trace_format_list_to_string(tf->data.subformat, object);
01176 for (i = tparams.current_s->id.level - 1; i > 0; i--)
01177 add_to_growable_string(&result, text_of_growable_string(temp_gs));
01178 free_growable_string(temp_gs);
01179 } else {
01180 found_undefined = TRUE;
01181 }
01182 break;
01183
01184 case NEWLINE_TFT:
01185 add_to_growable_string(&result, "\n");
01186 break;
01187
01188 default:
01189 {
01190 char msg[MESSAGE_SIZE];
01191 strncpy(msg, "Internal error: bad trace format type\n", MESSAGE_SIZE);
01192 msg[MESSAGE_SIZE - 1] = 0;
01193 abort_with_fatal_error(msg);
01194 }
01195 }
01196 }
01197 return result;
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 trace_format *find_appropriate_trace_format(bool stack_trace, int type, Symbol * name)
01219 {
01220 trace_format *tf;
01221
01222
01223 tf = lookup_trace_format(stack_trace, type, name);
01224 if (tf)
01225 return tf;
01226
01227
01228 if (type != FOR_ANYTHING_TF) {
01229 tf = lookup_trace_format(stack_trace, FOR_ANYTHING_TF, name);
01230 if (tf)
01231 return tf;
01232 }
01233
01234
01235 if (name) {
01236 tf = lookup_trace_format(stack_trace, type, NIL);
01237 if (tf)
01238 return tf;
01239 }
01240
01241
01242 return lookup_trace_format(stack_trace, FOR_ANYTHING_TF, NIL);
01243 }
01244
01245 growable_string object_to_trace_string(Symbol * object)
01246 {
01247 growable_string gs;
01248 int type_of_object;
01249 trace_format *tf;
01250 Symbol *name;
01251 struct tracing_parameters saved_tparams;
01252
01253
01254
01255
01256 if ((object->common.symbol_type != IDENTIFIER_SYMBOL_TYPE) || (object->id.tc_num == current_agent(tf_printing_tc))) {
01257 gs = make_blank_growable_string();
01258 add_to_growable_string(&gs, symbol_to_string(object, TRUE, NIL, 0));
01259 return gs;
01260 }
01261
01262
01263 object->id.tc_num = current_agent(tf_printing_tc);
01264
01265
01266 if (object->id.isa_goal)
01267 type_of_object = FOR_STATES_TF;
01268 else if (object->id.isa_operator)
01269 type_of_object = FOR_OPERATORS_TF;
01270 else
01271 type_of_object = FOR_ANYTHING_TF;
01272
01273 name = find_name_of_object(object);
01274
01275
01276 tf = find_appropriate_trace_format(FALSE, type_of_object, name);
01277
01278
01279 if (tf) {
01280 saved_tparams = tparams;
01281 tparams.current_s = tparams.current_o = NIL;
01282 tparams.allow_cycle_counts = FALSE;
01283 gs = trace_format_list_to_string(tf, object);
01284 tparams = saved_tparams;
01285 } else {
01286
01287 gs = make_blank_growable_string();
01288 add_to_growable_string(&gs, symbol_to_string(object, TRUE, NIL, 0));
01289 }
01290
01291 object->id.tc_num = 0;
01292 return gs;
01293 }
01294
01295 growable_string selection_to_trace_string(Symbol * object,
01296 Symbol * current_state, int selection_type, bool allow_cycle_counts)
01297 {
01298 trace_format *tf;
01299 Symbol *name;
01300 growable_string gs;
01301 struct tracing_parameters saved_tparams;
01302
01303
01304 name = NIL;
01305
01306
01307 tf = find_appropriate_trace_format(TRUE, selection_type, name);
01308
01309
01310 if (!tf)
01311 return make_blank_growable_string();
01312
01313
01314 saved_tparams = tparams;
01315 tparams.current_s = tparams.current_o = NIL;
01316 if (current_state) {
01317 tparams.current_s = current_state;
01318 if (current_state->id.operator_slot->wmes) {
01319 tparams.current_o = current_state->id.operator_slot->wmes->value;
01320 }
01321 }
01322 tparams.allow_cycle_counts = allow_cycle_counts;
01323 gs = trace_format_list_to_string(tf, object);
01324 tparams = saved_tparams;
01325
01326 return gs;
01327 }
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341 void print_object_trace(Symbol * object)
01342 {
01343 growable_string gs;
01344
01345 current_agent(tf_printing_tc) = get_new_tc_number();
01346 gs = object_to_trace_string(object);
01347 print_string(text_of_growable_string(gs));
01348 free_growable_string(gs);
01349 }
01350
01351 void print_stack_trace(Symbol * object, Symbol * state, int slot_type, bool allow_cycle_counts)
01352 {
01353 growable_string gs;
01354
01355 current_agent(tf_printing_tc) = get_new_tc_number();
01356 gs = selection_to_trace_string(object, state, slot_type, allow_cycle_counts);
01357 print_string(text_of_growable_string(gs));
01358 free_growable_string(gs);
01359 }
01360
01361
01362 void print_object_trace_using_provided_format_string(Symbol * object, Symbol * current_goal, char *format_string)
01363 {
01364 growable_string gs;
01365 struct tracing_parameters saved_tparams;
01366 trace_format *fs;
01367
01368 fs = parse_format_string(format_string);
01369
01370 current_agent(tf_printing_tc) = get_new_tc_number();
01371
01372 saved_tparams = tparams;
01373
01374 if (current_goal)
01375 tparams.current_s = current_goal;
01376 tparams.allow_cycle_counts = TRUE;
01377
01378 gs = trace_format_list_to_string(fs, object);
01379
01380 tparams = saved_tparams;
01381
01382 if (current_agent(printer_output_column) != 1)
01383 print_string("\n");
01384
01385 print_string(text_of_growable_string(gs));
01386 free_growable_string(gs);
01387 }
01388
01389