1 %{ 2 3 /* 4 * Copyright (c) 1983 Regents of the University of California. 5 * All rights reserved. The Berkeley software License Agreement 6 * specifies the terms and conditions for redistribution. 7 * 8 * @(#)commands.y 5.4 (Berkeley) 01/12/88 9 */ 10 11 static char rcsid[] = "$Header: commands.y,v 1.2 87/08/19 15:18:53 mike Exp $"; 12 13 /* 14 * Yacc grammar for debugger commands. 15 */ 16 17 #include "defs.h" 18 #include "symbols.h" 19 #include "operators.h" 20 #include "tree.h" 21 #include "process.h" 22 #include "source.h" 23 #include "scanner.h" 24 #include "keywords.h" 25 #include "names.h" 26 #include "lists.h" 27 28 private String curformat = "X"; 29 30 %} 31 32 %term 33 ALIAS AND ASSIGN AT CALL CATCH CONT DEBUG DELETE DIV DOWN DUMP 34 EDIT FILE FUNC GRIPE HELP IF IGNORE IN LIST MOD NEXT NEXTI NIL NOT OR 35 PRINT PSYM QUIT RERUN RETURN RUN SET SH SKIP SOURCE STATUS STEP STEPI 36 STOP STOPI TRACE TRACEI UNALIAS UNSET UP USE 37 WHATIS WHEN WHERE WHEREIS WHICH 38 39 %term INT CHAR REAL NAME STRING 40 %term ARROW 41 42 %right INT 43 %binary REDIRECT 44 %binary '<' '=' '>' '!' IN 45 %left '+' '-' OR 46 %left UNARYSIGN 47 %left '*' '/' DIV MOD AND 48 %left '\\' 49 %left NOT '(' '[' '.' '^' ARROW 50 51 %union { 52 Name y_name; 53 Symbol y_sym; 54 Node y_node; 55 Integer y_int; 56 Operator y_op; 57 long y_long; 58 char y_char; 59 double y_real; 60 String y_string; 61 Boolean y_bool; 62 Cmdlist y_cmdlist; 63 List y_list; 64 }; 65 66 %type <y_op> trace stop 67 %type <y_long> INT count signal 68 %type <y_char> CHAR 69 %type <y_real> REAL 70 %type <y_string> STRING redirectout filename opt_filename mode 71 %type <y_name> ALIAS AND ASSIGN AT CALL CATCH CONT 72 %type <y_name> DEBUG DELETE DIV DOWN DUMP 73 %type <y_name> EDIT FILE FUNC GRIPE HELP IF IGNORE IN LIST MOD 74 %type <y_name> NEXT NEXTI NIL NOT OR 75 %type <y_name> PRINT PSYM QUIT RERUN RETURN RUN SET SH SKIP SOURCE STATUS 76 %type <y_name> STEP STEPI STOP STOPI TRACE TRACEI 77 %type <y_name> UNALIAS UNSET UP USE WHATIS WHEN WHERE WHEREIS WHICH 78 %type <y_name> name NAME keyword 79 %type <y_node> opt_qual_symbol symbol 80 %type <y_node> command rcommand cmd step what where examine 81 %type <y_node> event opt_exp_list opt_cond 82 %type <y_node> exp_list exp term boolean_exp constant address 83 %type <y_node> integer_list alias_command list_command line_number 84 %type <y_cmdlist> actions 85 %type <y_list> sourcepath name_list 86 87 %% 88 89 input: 90 input command_nl 91 | 92 /* empty */ 93 ; 94 command_nl: 95 command_line '\n' 96 | 97 command_line ';' 98 { 99 chkalias = true; 100 } 101 | 102 '\n' 103 ; 104 105 command_line: 106 command 107 { 108 if ($1 != nil) { 109 topeval($1); 110 } 111 } 112 | 113 rcommand redirectout 114 { 115 if ($1 != nil) { 116 if ($2 != nil) { 117 setout($2); 118 topeval($1); 119 unsetout(); 120 } else { 121 topeval($1); 122 } 123 } 124 } 125 ; 126 redirectout: 127 '>' shellmode NAME 128 { 129 $$ = ident($3); 130 } 131 | 132 /* empty */ 133 { 134 $$ = nil; 135 } 136 ; 137 138 /* 139 * Non-redirectable commands. 140 */ 141 command: 142 alias_command 143 { 144 $$ = $1; 145 } 146 | 147 ASSIGN exp '=' exp 148 { 149 $$ = build(O_ASSIGN, unrval($2), $4); 150 } 151 | 152 CATCH signal 153 { 154 $$ = build(O_CATCH, $2); 155 } 156 | 157 CATCH 158 { 159 $$ = build(O_CATCH, 0); 160 } 161 | 162 CONT 163 { 164 $$ = build(O_CONT, (long) DEFSIG); 165 } 166 | 167 CONT signal 168 { 169 $$ = build(O_CONT, $2); 170 } 171 | 172 DELETE integer_list 173 { 174 $$ = build(O_DELETE, $2); 175 } 176 | 177 DOWN 178 { 179 $$ = build(O_DOWN, build(O_LCON, (long) 1)); 180 } 181 | 182 DOWN INT 183 { 184 $$ = build(O_DOWN, build(O_LCON, (long) $2)); 185 } 186 | 187 EDIT shellmode opt_filename 188 { 189 $$ = build(O_EDIT, $3); 190 } 191 | 192 FILE shellmode opt_filename 193 { 194 $$ = build(O_CHFILE, $3); 195 } 196 | 197 FUNC 198 { 199 $$ = build(O_FUNC, nil); 200 } 201 | 202 FUNC opt_qual_symbol 203 { 204 $$ = build(O_FUNC, $2); 205 } 206 | 207 GRIPE 208 { 209 $$ = build(O_GRIPE); 210 } 211 | 212 HELP 213 { 214 $$ = build(O_HELP); 215 } 216 | 217 IGNORE signal 218 { 219 $$ = build(O_IGNORE, $2); 220 } 221 | 222 IGNORE 223 { 224 $$ = build(O_IGNORE, 0); 225 } 226 | 227 list_command 228 { 229 $$ = $1; 230 } 231 | 232 PSYM exp 233 { 234 $$ = build(O_PSYM, unrval($2)); 235 } 236 | 237 QUIT 238 { 239 if (not popinput()) { 240 quit(0); 241 } else { 242 $$ = nil; 243 } 244 } 245 | 246 RETURN 247 { 248 $$ = build(O_RETURN, nil); 249 } 250 | 251 RETURN opt_qual_symbol 252 { 253 $$ = build(O_RETURN, $2); 254 } 255 | 256 runcommand 257 { 258 run(); 259 /* NOTREACHED */ 260 } 261 | 262 SET name '=' exp 263 { 264 $$ = build(O_SET, build(O_NAME, $2), $4); 265 } 266 | 267 SET name 268 { 269 $$ = build(O_SET, build(O_NAME, $2), nil); 270 } 271 | 272 SET 273 { 274 $$ = build(O_SET, nil, nil); 275 } 276 | 277 SH 278 { 279 shellline(); 280 $$ = nil; 281 } 282 | 283 SOURCE shellmode filename 284 { 285 $$ = build(O_SOURCE, $3); 286 } 287 | 288 step 289 { 290 $$ = $1; 291 } 292 | 293 stop where opt_cond 294 { 295 $$ = build($1, nil, $2, $3); 296 } 297 | 298 stop what opt_cond 299 { 300 $$ = build($1, $2, nil, $3); 301 } 302 | 303 stop IF boolean_exp 304 { 305 $$ = build($1, nil, nil, $3); 306 } 307 | 308 trace what where opt_cond 309 { 310 $$ = build($1, $2, $3, $4); 311 } 312 | 313 trace where opt_cond 314 { 315 $$ = build($1, nil, $2, $3); 316 } 317 | 318 trace what opt_cond 319 { 320 $$ = build($1, $2, nil, $3); 321 } 322 | 323 trace opt_cond 324 { 325 $$ = build($1, nil, nil, $2); 326 } 327 | 328 UNALIAS name 329 { 330 $$ = build(O_UNALIAS, build(O_NAME, $2)); 331 } 332 | 333 UNSET name 334 { 335 $$ = build(O_UNSET, build(O_NAME, $2)); 336 } 337 | 338 UP 339 { 340 $$ = build(O_UP, build(O_LCON, (long) 1)); 341 } 342 | 343 UP INT 344 { 345 $$ = build(O_UP, build(O_LCON, (long) $2)); 346 } 347 | 348 USE shellmode sourcepath 349 { 350 String dir; 351 352 $$ = nil; 353 if (list_size($3) == 0) { 354 foreach (String, dir, sourcepath) 355 printf("%s ", dir); 356 endfor 357 printf("\n"); 358 } else { 359 foreach (String, dir, sourcepath) 360 list_delete(list_curitem(sourcepath), sourcepath); 361 endfor 362 sourcepath = $3; 363 } 364 } 365 | 366 WHATIS opt_qual_symbol 367 { 368 $$ = build(O_WHATIS, $2); 369 } 370 | 371 WHEN event '{' actions '}' 372 { 373 $$ = build(O_ADDEVENT, $2, $4); 374 } 375 | 376 WHEREIS name 377 { 378 $$ = build(O_WHEREIS, build(O_SYM, lookup($2))); 379 } 380 | 381 WHICH symbol 382 { 383 $$ = build(O_WHICH, $2); 384 } 385 | 386 '/' 387 { 388 $$ = build(O_SEARCH, 389 build(O_LCON, (long) '/'), 390 build(O_SCON, strdup(scanner_linebuf)) 391 ); 392 gobble(); 393 insertinput("\n"); 394 } 395 | 396 '?' 397 { 398 $$ = build(O_SEARCH, 399 build(O_LCON, (long) '?'), 400 build(O_SCON, strdup(scanner_linebuf)) 401 ); 402 gobble(); 403 insertinput("\n"); 404 } 405 ; 406 signal: 407 INT 408 { 409 $$ = $1; 410 } 411 | 412 name 413 { 414 $$ = siglookup(ident($1)); 415 } 416 ; 417 runcommand: 418 run arglist 419 | 420 run 421 ; 422 run: 423 RUN shellmode 424 { 425 arginit(); 426 fflush(stdout); 427 } 428 | 429 RERUN shellmode 430 { 431 fflush(stdout); 432 } 433 ; 434 arglist: 435 arglist arg 436 | 437 arg 438 ; 439 arg: 440 NAME 441 { 442 newarg(ident($1)); 443 } 444 | 445 STRING 446 { 447 newarg($1); 448 } 449 | 450 '<' NAME 451 { 452 inarg(ident($2)); 453 } 454 | 455 '>' NAME 456 { 457 outarg(ident($2)); 458 } 459 ; 460 step: 461 STEP 462 { 463 $$ = build(O_STEP, true, false); 464 } 465 | 466 STEPI 467 { 468 $$ = build(O_STEP, false, false); 469 } 470 | 471 NEXT 472 { 473 $$ = build(O_STEP, true, true); 474 } 475 | 476 NEXTI 477 { 478 $$ = build(O_STEP, false, true); 479 } 480 ; 481 shellmode: 482 /* empty */ 483 { 484 beginshellmode(); 485 } 486 ; 487 sourcepath: 488 sourcepath NAME 489 { 490 $$ = $1; 491 list_append(list_item(ident($2)), nil, $$); 492 } 493 | 494 /* empty */ 495 { 496 $$ = list_alloc(); 497 } 498 ; 499 event: 500 where 501 | 502 exp 503 ; 504 actions: 505 actions cmd ';' 506 { 507 $$ = $1; 508 cmdlist_append($2, $$); 509 } 510 | 511 cmd ';' 512 { 513 $$ = list_alloc(); 514 cmdlist_append($1, $$); 515 } 516 ; 517 cmd: 518 command 519 | 520 rcommand 521 ; 522 523 /* 524 * Redirectable commands. 525 */ 526 rcommand: 527 PRINT exp_list 528 { 529 $$ = build(O_PRINT, $2); 530 } 531 | 532 WHERE 533 { 534 $$ = build(O_WHERE); 535 } 536 | 537 examine 538 { 539 $$ = $1; 540 } 541 | 542 CALL term '(' opt_exp_list ')' 543 { 544 $$ = build(O_CALLPROC, $2, $4); 545 } 546 | 547 DEBUG INT 548 { 549 $$ = build(O_DEBUG, $2); 550 } 551 | 552 DEBUG '-' INT 553 { 554 $$ = build(O_DEBUG, -$3); 555 } 556 | 557 DUMP opt_qual_symbol 558 { 559 $$ = build(O_DUMP, $2); 560 } 561 | 562 DUMP '.' 563 { 564 $$ = build(O_DUMP, nil); 565 } 566 | 567 DUMP 568 { 569 $$ = build(O_DUMP, build(O_SYM, curfunc)); 570 } 571 | 572 STATUS 573 { 574 $$ = build(O_STATUS); 575 } 576 ; 577 alias_command: 578 ALIAS name name 579 { 580 $$ = build(O_ALIAS, build(O_NAME, $2), build(O_NAME, $3)); 581 } 582 | 583 ALIAS name STRING 584 { 585 $$ = build(O_ALIAS, build(O_NAME, $2), build(O_SCON, $3)); 586 } 587 | 588 ALIAS name '(' name_list ')' STRING 589 { 590 $$ = build(O_ALIAS, 591 build(O_COMMA, build(O_NAME, $2), (Node) $4), 592 build(O_SCON, $6) 593 ); 594 } 595 | 596 ALIAS name 597 { 598 $$ = build(O_ALIAS, build(O_NAME, $2), nil); 599 } 600 | 601 ALIAS 602 { 603 $$ = build(O_ALIAS, nil, nil); 604 } 605 ; 606 name_list: 607 name_list ',' name 608 { 609 $$ = $1; 610 list_append(list_item($3), nil, $$); 611 } 612 | 613 name 614 { 615 $$ = list_alloc(); 616 list_append(list_item($1), nil, $$); 617 } 618 ; 619 trace: 620 TRACE 621 { 622 $$ = O_TRACE; 623 } 624 | 625 TRACEI 626 { 627 $$ = O_TRACEI; 628 } 629 ; 630 stop: 631 STOP 632 { 633 $$ = O_STOP; 634 } 635 | 636 STOPI 637 { 638 $$ = O_STOPI; 639 } 640 ; 641 what: 642 exp 643 { 644 $$ = $1; 645 } 646 | 647 STRING ':' line_number 648 { 649 $$ = build(O_QLINE, build(O_SCON, $1), $3); 650 } 651 ; 652 where: 653 IN exp 654 { 655 $$ = unrval($2); 656 } 657 | 658 AT line_number 659 { 660 $$ = build(O_QLINE, build(O_SCON, strdup(cursource)), $2); 661 } 662 | 663 AT STRING ':' line_number 664 { 665 $$ = build(O_QLINE, build(O_SCON, $2), $4); 666 } 667 ; 668 filename: 669 NAME 670 { 671 $$ = ident($1); 672 } 673 ; 674 opt_filename: 675 /* empty */ 676 { 677 $$ = nil; 678 } 679 | 680 filename 681 { 682 $$ = $1; 683 } 684 ; 685 opt_exp_list: 686 exp_list 687 { 688 $$ = $1; 689 } 690 | 691 /* empty */ 692 { 693 $$ = nil; 694 } 695 ; 696 list_command: 697 LIST 698 { 699 $$ = build(O_LIST, 700 build(O_LCON, (long) cursrcline), 701 build(O_LCON, (long) cursrcline + srcwindowlen() - 1) 702 ); 703 } 704 | 705 LIST line_number 706 { 707 $$ = build(O_LIST, $2, $2); 708 } 709 | 710 LIST line_number ',' line_number 711 { 712 $$ = build(O_LIST, $2, $4); 713 } 714 | 715 LIST opt_qual_symbol 716 { 717 $$ = build(O_LIST, $2, $2); 718 } 719 ; 720 integer_list: 721 INT 722 { 723 $$ = build(O_LCON, $1); 724 } 725 | 726 INT integer_list 727 { 728 $$ = build(O_COMMA, build(O_LCON, $1), $2); 729 } 730 ; 731 line_number: 732 INT 733 { 734 $$ = build(O_LCON, $1); 735 } 736 | 737 '$' 738 { 739 $$ = build(O_LCON, (long) LASTLINE); 740 } 741 ; 742 examine: 743 address '/' count mode 744 { 745 $$ = build(O_EXAMINE, $4, $1, nil, $3); 746 } 747 | 748 address ',' address '/' mode 749 { 750 $$ = build(O_EXAMINE, $5, $1, $3, 0); 751 } 752 | 753 address '=' mode 754 { 755 $$ = build(O_EXAMINE, $3, $1, nil, 0); 756 } 757 ; 758 address: 759 INT 760 { 761 $$ = build(O_LCON, $1); 762 } 763 | 764 '.' 765 { 766 $$ = build(O_LCON, (long) prtaddr); 767 } 768 | 769 '&' term 770 { 771 $$ = amper($2); 772 } 773 | 774 address '+' address 775 { 776 $$ = build(O_ADD, $1, $3); 777 } 778 | 779 address '-' address 780 { 781 $$ = build(O_SUB, $1, $3); 782 } 783 | 784 address '*' address 785 { 786 $$ = build(O_MUL, $1, $3); 787 } 788 | 789 '*' address %prec UNARYSIGN 790 { 791 $$ = build(O_INDIR, $2); 792 } 793 | 794 '-' address %prec UNARYSIGN 795 { 796 $$ = build(O_NEG, $2); 797 } 798 | 799 '(' exp ')' 800 { 801 $$ = $2; 802 } 803 ; 804 term: 805 symbol 806 { 807 $$ = $1; 808 } 809 | 810 term '.' name 811 { 812 $$ = unrval(dot($1, $3)); 813 } 814 | 815 term ARROW name 816 { 817 $$ = unrval(dot($1, $3)); 818 } 819 | 820 term '[' exp_list ']' 821 { 822 $$ = unrval(subscript($1, $3)); 823 } 824 ; 825 count: 826 /* empty */ 827 { 828 $$ = 1; 829 } 830 | 831 INT 832 { 833 $$ = $1; 834 } 835 ; 836 mode: 837 name 838 { 839 $$ = ident($1); 840 curformat = $$; 841 } 842 | 843 /* empty */ 844 { 845 $$ = curformat; 846 } 847 ; 848 opt_cond: 849 /* empty */ 850 { 851 $$ = nil; 852 } 853 | 854 IF boolean_exp 855 { 856 $$ = $2; 857 } 858 ; 859 exp_list: 860 exp 861 { 862 $$ = build(O_COMMA, $1, nil); 863 } 864 | 865 exp ',' exp_list 866 { 867 $$ = build(O_COMMA, $1, $3); 868 } 869 ; 870 exp: 871 symbol 872 { 873 $$ = build(O_RVAL, $1); 874 } 875 | 876 exp '[' exp_list ']' 877 { 878 $$ = subscript(unrval($1), $3); 879 } 880 | 881 exp '.' name 882 { 883 $$ = dot($1, $3); 884 } 885 | 886 exp ARROW name 887 { 888 $$ = dot($1, $3); 889 } 890 | 891 '*' exp %prec UNARYSIGN 892 { 893 $$ = build(O_INDIR, $2); 894 } 895 | 896 exp '^' %prec UNARYSIGN 897 { 898 $$ = build(O_INDIR, $1); 899 } 900 | 901 exp '\\' opt_qual_symbol 902 { 903 $$ = build(O_TYPERENAME, $1, $3); 904 } 905 | 906 exp '\\' '&' opt_qual_symbol %prec '\\' 907 { 908 $$ = renameptr($1, $4); 909 } 910 | 911 exp '(' opt_exp_list ')' 912 { 913 $$ = build(O_CALL, unrval($1), $3); 914 } 915 | 916 constant 917 { 918 $$ = $1; 919 } 920 | 921 '+' exp %prec UNARYSIGN 922 { 923 $$ = $2; 924 } 925 | 926 '-' exp %prec UNARYSIGN 927 { 928 $$ = build(O_NEG, $2); 929 } 930 | 931 '&' exp %prec UNARYSIGN 932 { 933 $$ = amper($2); 934 } 935 | 936 exp '+' exp 937 { 938 $$ = build(O_ADD, $1, $3); 939 } 940 | 941 exp '-' exp 942 { 943 $$ = build(O_SUB, $1, $3); 944 } 945 | 946 exp '*' exp 947 { 948 $$ = build(O_MUL, $1, $3); 949 } 950 | 951 exp '/' exp 952 { 953 $$ = build(O_DIVF, $1, $3); 954 } 955 | 956 exp DIV exp 957 { 958 $$ = build(O_DIV, $1, $3); 959 } 960 | 961 exp MOD exp 962 { 963 $$ = build(O_MOD, $1, $3); 964 } 965 | 966 exp AND exp 967 { 968 $$ = build(O_AND, $1, $3); 969 } 970 | 971 exp OR exp 972 { 973 $$ = build(O_OR, $1, $3); 974 } 975 | 976 exp '<' exp 977 { 978 $$ = build(O_LT, $1, $3); 979 } 980 | 981 exp '<' '=' exp 982 { 983 $$ = build(O_LE, $1, $4); 984 } 985 | 986 exp '>' exp 987 { 988 $$ = build(O_GT, $1, $3); 989 } 990 | 991 exp '>' '=' exp 992 { 993 $$ = build(O_GE, $1, $4); 994 } 995 | 996 exp '=' exp 997 { 998 $$ = build(O_EQ, $1, $3); 999 } 1000 | 1001 exp '=' '=' exp 1002 { 1003 $$ = build(O_EQ, $1, $4); 1004 } 1005 | 1006 exp '<' '>' exp 1007 { 1008 $$ = build(O_NE, $1, $4); 1009 } 1010 | 1011 exp '!' '=' exp 1012 { 1013 $$ = build(O_NE, $1, $4); 1014 } 1015 | 1016 '(' exp ')' 1017 { 1018 $$ = $2; 1019 } 1020 ; 1021 boolean_exp: 1022 exp 1023 { 1024 chkboolean($1); 1025 $$ = $1; 1026 } 1027 ; 1028 constant: 1029 INT 1030 { 1031 $$ = build(O_LCON, $1); 1032 } 1033 | 1034 CHAR 1035 { 1036 $$ = build(O_CCON, $1); 1037 } 1038 | 1039 REAL 1040 { 1041 $$ = build(O_FCON, $1); 1042 } 1043 | 1044 STRING 1045 { 1046 $$ = build(O_SCON, $1); 1047 } 1048 ; 1049 opt_qual_symbol: 1050 symbol 1051 { 1052 $$ = $1; 1053 } 1054 | 1055 opt_qual_symbol '.' name 1056 { 1057 $$ = dot($1, $3); 1058 } 1059 ; 1060 symbol: 1061 name 1062 { 1063 $$ = findvar($1); 1064 if ($$ == nil) { 1065 $$ = build(O_SYM, which($1)); 1066 } 1067 } 1068 | 1069 '.' name 1070 { 1071 $$ = dot(build(O_SYM, program), $2); 1072 } 1073 ; 1074 name: 1075 NAME 1076 { 1077 $$ = $1; 1078 } 1079 | 1080 keyword 1081 { 1082 $$ = $1; 1083 } 1084 keyword: 1085 ALIAS | AND | ASSIGN | AT | CALL | CATCH | CONT | DEBUG | DELETE | DIV | 1086 DOWN | DUMP | EDIT | FILE | FUNC | GRIPE | HELP | IGNORE | IN | LIST | 1087 MOD | NEXT | NEXTI | NIL | NOT | OR | PRINT | PSYM | QUIT | 1088 RERUN | RETURN | RUN | SET | SH | SKIP | SOURCE | STATUS | STEP | STEPI | 1089 STOP | STOPI | TRACE | TRACEI | UNALIAS | UNSET | UP | USE | 1090 WHATIS | WHEN | WHERE | WHEREIS | WHICH 1091 ; 1092