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