|
|
1.1 ! root 1: /* Parse C expressions for GDB. ! 2: Copyright (C) 1986 Free Software Foundation, Inc. ! 3: ! 4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY ! 5: WARRANTY. No author or distributor accepts responsibility to anyone ! 6: for the consequences of using it or for whether it serves any ! 7: particular purpose or works at all, unless he says so in writing. ! 8: Refer to the GDB General Public License for full details. ! 9: ! 10: Everyone is granted permission to copy, modify and redistribute GDB, ! 11: but only under the conditions described in the GDB General Public ! 12: License. A copy of this license is supposed to have been given to you ! 13: along with GDB so you can know your rights and responsibilities. It ! 14: should be in a file named COPYING. Among other things, the copyright ! 15: notice and this notice must be preserved on all copies. ! 16: ! 17: In other words, go ahead and share GDB, but don't try to stop ! 18: anyone else from sharing it farther. Help stamp out software hoarding! ! 19: */ ! 20: ! 21: /* Parse a C expression from text in a string, ! 22: and return the result as a struct expression pointer. ! 23: That structure contains arithmetic operations in reverse polish, ! 24: with constants represented by operations that are followed by special data. ! 25: See expression.h for the details of the format. ! 26: What is important here is that it can be built up sequentially ! 27: during the process of parsing; the lower levels of the tree always ! 28: come first in the result. */ ! 29: ! 30: %{ ! 31: #include "defs.h" ! 32: #include "param.h" ! 33: #include "symtab.h" ! 34: #include "frame.h" ! 35: #include "expression.h" ! 36: ! 37: #include <stdio.h> ! 38: ! 39: static struct expression *expout; ! 40: static int expout_size; ! 41: static int expout_ptr; ! 42: ! 43: static int yylex (); ! 44: static yyerror (); ! 45: static void write_exp_elt (); ! 46: static void write_exp_string (); ! 47: static void start_arglist (); ! 48: static int end_arglist (); ! 49: static void free_funcalls (); ! 50: static char *copy_name (); ! 51: ! 52: /* If this is nonzero, this block is used as the lexical context ! 53: for symbol names. */ ! 54: ! 55: static struct block *expression_context_block; ! 56: ! 57: /* Number of arguments seen so far in innermost function call. */ ! 58: static int arglist_len; ! 59: ! 60: /* Data structure for saving values of arglist_len ! 61: for function calls whose arguments contain other function calls. */ ! 62: ! 63: struct funcall ! 64: { ! 65: struct funcall *next; ! 66: int arglist_len; ! 67: }; ! 68: ! 69: struct funcall *funcall_chain; ! 70: ! 71: /* This kind of datum is used to represent the name ! 72: of a symbol token. */ ! 73: ! 74: struct stoken ! 75: { ! 76: char *ptr; ! 77: int length; ! 78: }; ! 79: %} ! 80: ! 81: /* Although the yacc "value" of an expression is not used, ! 82: since the result is stored in the structure being created, ! 83: other node types do have values. */ ! 84: ! 85: %union ! 86: { ! 87: long lval; ! 88: double dval; ! 89: struct symbol *sym; ! 90: struct type *tval; ! 91: struct stoken sval; ! 92: int voidval; ! 93: struct block *bval; ! 94: enum exp_opcode opcode; ! 95: struct internalvar *ivar; ! 96: } ! 97: ! 98: %type <voidval> exp exp1 start variable ! 99: %type <tval> type typebase ! 100: %type <bval> block ! 101: ! 102: %token <lval> INT CHAR ! 103: %token <dval> FLOAT ! 104: ! 105: /* Both NAME and TYPENAME tokens represent symbols in the input, ! 106: and both convey their data as strings. ! 107: But a TYPENAME is a string that happens to be defined as a typedef ! 108: or builtin type name (such as int or char) ! 109: and a NAME is any other symbol. ! 110: ! 111: Contexts where this distinction is not important can use the ! 112: nonterminal "name", which matches either NAME or TYPENAME. */ ! 113: ! 114: %token <sval> NAME TYPENAME STRING ! 115: %type <sval> name ! 116: ! 117: %token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON ! 118: ! 119: %token <lval> LAST REGNAME ! 120: ! 121: %token <ivar> VARIABLE ! 122: ! 123: %token <opcode> ASSIGN_MODIFY ! 124: ! 125: %left ',' ! 126: %left ABOVE_COMMA ! 127: %right '=' ASSIGN_MODIFY ! 128: %left OR ! 129: %left AND ! 130: %left '|' ! 131: %left '^' ! 132: %left '&' ! 133: %left EQUAL NOTEQUAL ! 134: %left '<' '>' LEQ GEQ ! 135: %left LSH RSH ! 136: %left '+' '-' ! 137: %left '*' '/' '%' ! 138: %left '@' ! 139: %right UNARY INCREMENT DECREMENT ! 140: %right ARROW '.' '[' ! 141: %left COLONCOLON ! 142: ! 143: %% ! 144: ! 145: start : exp1 ! 146: ; ! 147: ! 148: /* Expressions, including the comma operator. */ ! 149: exp1 : exp ! 150: | exp1 ',' exp ! 151: { write_exp_elt (BINOP_COMMA); } ! 152: ; ! 153: ! 154: /* Expressions, not including the comma operator. */ ! 155: exp : '*' exp %prec UNARY ! 156: { write_exp_elt (UNOP_IND); } ! 157: ! 158: exp : '&' exp %prec UNARY ! 159: { write_exp_elt (UNOP_ADDR); } ! 160: ! 161: exp : '-' exp %prec UNARY ! 162: { write_exp_elt (UNOP_NEG); } ! 163: ; ! 164: ! 165: exp : '!' exp %prec UNARY ! 166: { write_exp_elt (UNOP_ZEROP); } ! 167: ; ! 168: ! 169: exp : '~' exp %prec UNARY ! 170: { write_exp_elt (UNOP_LOGNOT); } ! 171: ; ! 172: ! 173: exp : INCREMENT exp %prec UNARY ! 174: { write_exp_elt (UNOP_PREINCREMENT); } ! 175: ; ! 176: ! 177: exp : DECREMENT exp %prec UNARY ! 178: { write_exp_elt (UNOP_PREDECREMENT); } ! 179: ; ! 180: ! 181: exp : exp INCREMENT %prec UNARY ! 182: { write_exp_elt (UNOP_POSTINCREMENT); } ! 183: ; ! 184: ! 185: exp : exp DECREMENT %prec UNARY ! 186: { write_exp_elt (UNOP_POSTDECREMENT); } ! 187: ; ! 188: ! 189: exp : SIZEOF exp %prec UNARY ! 190: { write_exp_elt (UNOP_SIZEOF); } ! 191: ; ! 192: ! 193: exp : exp ARROW name ! 194: { write_exp_elt (STRUCTOP_PTR); ! 195: write_exp_string ($3); ! 196: write_exp_elt (STRUCTOP_PTR); } ! 197: ; ! 198: ! 199: exp : exp '.' name ! 200: { write_exp_elt (STRUCTOP_STRUCT); ! 201: write_exp_string ($3); ! 202: write_exp_elt (STRUCTOP_STRUCT); } ! 203: ; ! 204: ! 205: exp : exp '[' exp1 ']' ! 206: { write_exp_elt (BINOP_SUBSCRIPT); } ! 207: ; ! 208: ! 209: exp : exp '(' ! 210: /* This is to save the value of arglist_len ! 211: being accumulated by an outer function call. */ ! 212: { start_arglist (); } ! 213: arglist ')' ! 214: { write_exp_elt (OP_FUNCALL); ! 215: write_exp_elt (end_arglist ()); ! 216: write_exp_elt (OP_FUNCALL); } ! 217: ; ! 218: ! 219: arglist : ! 220: ; ! 221: ! 222: arglist : exp ! 223: { arglist_len = 1; } ! 224: ; ! 225: ! 226: arglist : arglist ',' exp %prec ABOVE_COMMA ! 227: { arglist_len++; } ! 228: ; ! 229: ! 230: exp : '{' type '}' exp %prec UNARY ! 231: { write_exp_elt (UNOP_MEMVAL); ! 232: write_exp_elt ($2); ! 233: write_exp_elt (UNOP_MEMVAL); } ! 234: ; ! 235: ! 236: exp : '(' type ')' exp %prec UNARY ! 237: { write_exp_elt (UNOP_CAST); ! 238: write_exp_elt ($2); ! 239: write_exp_elt (UNOP_CAST); } ! 240: ; ! 241: ! 242: exp : '(' exp1 ')' ! 243: { } ! 244: ; ! 245: ! 246: /* Binary operators in order of decreasing precedence. */ ! 247: ! 248: exp : exp '@' exp ! 249: { write_exp_elt (BINOP_REPEAT); } ! 250: ; ! 251: ! 252: exp : exp '*' exp ! 253: { write_exp_elt (BINOP_MUL); } ! 254: ; ! 255: ! 256: exp : exp '/' exp ! 257: { write_exp_elt (BINOP_DIV); } ! 258: ; ! 259: ! 260: exp : exp '%' exp ! 261: { write_exp_elt (BINOP_REM); } ! 262: ; ! 263: ! 264: exp : exp '+' exp ! 265: { write_exp_elt (BINOP_ADD); } ! 266: ; ! 267: ! 268: exp : exp '-' exp ! 269: { write_exp_elt (BINOP_SUB); } ! 270: ; ! 271: ! 272: exp : exp LSH exp ! 273: { write_exp_elt (BINOP_LSH); } ! 274: ; ! 275: ! 276: exp : exp RSH exp ! 277: { write_exp_elt (BINOP_RSH); } ! 278: ; ! 279: ! 280: exp : exp EQUAL exp ! 281: { write_exp_elt (BINOP_EQUAL); } ! 282: ; ! 283: ! 284: exp : exp NOTEQUAL exp ! 285: { write_exp_elt (BINOP_NOTEQUAL); } ! 286: ; ! 287: ! 288: exp : exp LEQ exp ! 289: { write_exp_elt (BINOP_LEQ); } ! 290: ; ! 291: ! 292: exp : exp GEQ exp ! 293: { write_exp_elt (BINOP_GEQ); } ! 294: ; ! 295: ! 296: exp : exp '<' exp ! 297: { write_exp_elt (BINOP_LESS); } ! 298: ; ! 299: ! 300: exp : exp '>' exp ! 301: { write_exp_elt (BINOP_GTR); } ! 302: ; ! 303: ! 304: exp : exp '&' exp ! 305: { write_exp_elt (BINOP_LOGAND); } ! 306: ; ! 307: ! 308: exp : exp '^' exp ! 309: { write_exp_elt (BINOP_LOGXOR); } ! 310: ; ! 311: ! 312: exp : exp '|' exp ! 313: { write_exp_elt (BINOP_LOGIOR); } ! 314: ; ! 315: ! 316: exp : exp AND exp ! 317: { write_exp_elt (BINOP_AND); } ! 318: ; ! 319: ! 320: exp : exp OR exp ! 321: { write_exp_elt (BINOP_OR); } ! 322: ; ! 323: ! 324: exp : exp '?' exp ':' exp ! 325: { write_exp_elt (TERNOP_COND); } ! 326: ; ! 327: ! 328: exp : exp '=' exp ! 329: { write_exp_elt (BINOP_ASSIGN); } ! 330: ; ! 331: ! 332: exp : exp ASSIGN_MODIFY exp ! 333: { write_exp_elt (BINOP_ASSIGN_MODIFY); ! 334: write_exp_elt ($2); ! 335: write_exp_elt (BINOP_ASSIGN_MODIFY); } ! 336: ; ! 337: ! 338: exp : INT ! 339: { write_exp_elt (OP_LONG); ! 340: write_exp_elt (builtin_type_long); ! 341: write_exp_elt ($1); ! 342: write_exp_elt (OP_LONG); } ! 343: ; ! 344: ! 345: exp : CHAR ! 346: { write_exp_elt (OP_LONG); ! 347: write_exp_elt (builtin_type_char); ! 348: write_exp_elt ($1); ! 349: write_exp_elt (OP_LONG); } ! 350: ; ! 351: ! 352: exp : FLOAT ! 353: { write_exp_elt (OP_DOUBLE); ! 354: write_exp_elt (builtin_type_double); ! 355: write_exp_elt ($1); ! 356: write_exp_elt (OP_DOUBLE); } ! 357: ; ! 358: ! 359: exp : variable ! 360: ; ! 361: ! 362: exp : LAST ! 363: { write_exp_elt (OP_LAST); ! 364: write_exp_elt ($1); ! 365: write_exp_elt (OP_LAST); } ! 366: ; ! 367: ! 368: exp : REGNAME ! 369: { write_exp_elt (OP_REGISTER); ! 370: write_exp_elt ($1); ! 371: write_exp_elt (OP_REGISTER); } ! 372: ; ! 373: ! 374: exp : VARIABLE ! 375: { write_exp_elt (OP_INTERNALVAR); ! 376: write_exp_elt ($1); ! 377: write_exp_elt (OP_INTERNALVAR); } ! 378: ; ! 379: ! 380: exp : SIZEOF '(' type ')' ! 381: { write_exp_elt (OP_LONG); ! 382: write_exp_elt (builtin_type_int); ! 383: write_exp_elt ((long) TYPE_LENGTH ($3)); ! 384: write_exp_elt (OP_LONG); } ! 385: ; ! 386: ! 387: exp : STRING ! 388: { write_exp_elt (OP_STRING); ! 389: write_exp_string ($1); ! 390: write_exp_elt (OP_STRING); } ! 391: ; ! 392: ! 393: block : name ! 394: { struct symtab *tem = lookup_symtab (copy_name ($1)); ! 395: struct symbol *sym; ! 396: ! 397: if (tem) ! 398: $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1); ! 399: else ! 400: { ! 401: sym = lookup_symbol (copy_name ($1), ! 402: expression_context_block, ! 403: VAR_NAMESPACE); ! 404: if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ! 405: $$ = SYMBOL_BLOCK_VALUE (sym); ! 406: else ! 407: error ("No file or function \"%s\".", ! 408: copy_name ($1)); ! 409: }} ! 410: ; ! 411: ! 412: block : block COLONCOLON name ! 413: { struct symbol *tem ! 414: = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE); ! 415: if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) ! 416: error ("No function \"%s\" in specified context.", ! 417: copy_name ($3)); ! 418: $$ = SYMBOL_BLOCK_VALUE (tem); } ! 419: ; ! 420: ! 421: variable: block COLONCOLON name ! 422: { struct symbol *sym; ! 423: sym = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE); ! 424: if (sym == 0) ! 425: error ("No symbol \"%s\" in specified context.", ! 426: copy_name ($3)); ! 427: write_exp_elt (OP_VAR_VALUE); ! 428: write_exp_elt (sym); ! 429: write_exp_elt (OP_VAR_VALUE); } ! 430: ; ! 431: ! 432: variable: NAME ! 433: { struct symbol *sym; ! 434: sym = lookup_symbol (copy_name ($1), ! 435: expression_context_block, ! 436: VAR_NAMESPACE); ! 437: if (sym) ! 438: { ! 439: write_exp_elt (OP_VAR_VALUE); ! 440: write_exp_elt (sym); ! 441: write_exp_elt (OP_VAR_VALUE); ! 442: } ! 443: else ! 444: { ! 445: register char *arg = copy_name ($1); ! 446: register int i; ! 447: for (i = 0; i < misc_function_count; i++) ! 448: if (!strcmp (misc_function_vector[i].name, arg)) ! 449: break; ! 450: ! 451: if (i < misc_function_count) ! 452: { ! 453: write_exp_elt (OP_LONG); ! 454: write_exp_elt (builtin_type_int); ! 455: write_exp_elt (misc_function_vector[i].address); ! 456: write_exp_elt (OP_LONG); ! 457: write_exp_elt (UNOP_MEMVAL); ! 458: write_exp_elt (builtin_type_char); ! 459: write_exp_elt (UNOP_MEMVAL); ! 460: } ! 461: else ! 462: if (symtab_list == 0) ! 463: error ("No symbol table is loaded. Use the \"symbol-file\" command."); ! 464: else ! 465: error ("No symbol \"%s\" in current context.", ! 466: copy_name ($1)); ! 467: } ! 468: } ! 469: ; ! 470: ! 471: type : typebase ! 472: | type '*' ! 473: { $$ = lookup_pointer_type ($1); } ! 474: ; ! 475: ! 476: typebase ! 477: : TYPENAME ! 478: { $$ = lookup_typename (copy_name ($1), ! 479: expression_context_block, 0); } ! 480: | STRUCT name ! 481: { $$ = lookup_struct (copy_name ($2), ! 482: expression_context_block); } ! 483: | UNION name ! 484: { $$ = lookup_union (copy_name ($2), ! 485: expression_context_block); } ! 486: | ENUM name ! 487: { $$ = lookup_enum (copy_name ($2), ! 488: expression_context_block); } ! 489: | UNSIGNED name ! 490: { $$ = lookup_unsigned_typename (copy_name ($2)); } ! 491: ; ! 492: ! 493: name : NAME ! 494: | TYPENAME ! 495: ; ! 496: %% ! 497: ! 498: /* Begin counting arguments for a function call, ! 499: saving the data about any containing call. */ ! 500: ! 501: static void ! 502: start_arglist () ! 503: { ! 504: register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall)); ! 505: ! 506: new->next = funcall_chain; ! 507: new->arglist_len = arglist_len; ! 508: arglist_len = 0; ! 509: funcall_chain = new; ! 510: } ! 511: ! 512: /* Return the number of arguments in a function call just terminated, ! 513: and restore the data for the containing function call. */ ! 514: ! 515: static int ! 516: end_arglist () ! 517: { ! 518: register int val = arglist_len; ! 519: register struct funcall *call = funcall_chain; ! 520: funcall_chain = call->next; ! 521: arglist_len = call->arglist_len; ! 522: free (call); ! 523: return val; ! 524: } ! 525: ! 526: /* Free everything in the funcall chain. ! 527: Used when there is an error inside parsing. */ ! 528: ! 529: static void ! 530: free_funcalls () ! 531: { ! 532: register struct funcall *call, *next; ! 533: ! 534: for (call = funcall_chain; call; call = next) ! 535: { ! 536: next = call->next; ! 537: free (call); ! 538: } ! 539: } ! 540: ! 541: /* This page contains the functions for adding data to the struct expression ! 542: being constructed. */ ! 543: ! 544: /* Add one element to the end of the expression. */ ! 545: ! 546: static void ! 547: write_exp_elt (expelt) ! 548: union exp_element expelt; ! 549: { ! 550: if (expout_ptr >= expout_size) ! 551: { ! 552: expout_size *= 2; ! 553: expout = (struct expression *) xrealloc (expout, ! 554: sizeof (struct expression) ! 555: + expout_size * sizeof (union exp_element)); ! 556: } ! 557: expout->elts[expout_ptr++] = expelt; ! 558: } ! 559: ! 560: /* Add a string constant to the end of the expression. ! 561: Follow it by its length in bytes, as a separate exp_element. */ ! 562: ! 563: static void ! 564: write_exp_string (str) ! 565: struct stoken str; ! 566: { ! 567: register int len = str.length; ! 568: register int lenelt ! 569: = (len + sizeof (union exp_element)) / sizeof (union exp_element); ! 570: ! 571: expout_ptr += lenelt; ! 572: ! 573: if (expout_ptr >= expout_size) ! 574: { ! 575: expout_size = max (expout_size * 2, expout_ptr + 10); ! 576: expout = (struct expression *) xrealloc (expout, ! 577: sizeof (struct expression) ! 578: + expout_size * sizeof (union exp_element)); ! 579: } ! 580: bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len); ! 581: ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0; ! 582: write_exp_elt (len); ! 583: } ! 584: ! 585: /* During parsing of a C expression, the pointer to the next character ! 586: is in this variable. */ ! 587: ! 588: static char *lexptr; ! 589: ! 590: /* Tokens that refer to names do so with explicit pointer and length, ! 591: so they can share the storage that lexptr is parsing. ! 592: ! 593: When it is necessary to pass a name to a function that expects ! 594: a null-terminated string, the substring is copied out ! 595: into a block of storage that namecopy points to. ! 596: ! 597: namecopy is allocated once, guaranteed big enough, for each parsing. */ ! 598: ! 599: static char *namecopy; ! 600: ! 601: /* Current depth in parentheses within the expression. */ ! 602: ! 603: static int paren_depth; ! 604: ! 605: /* Nonzero means stop parsing on first comma (if not within parentheses). */ ! 606: ! 607: static int comma_terminates; ! 608: ! 609: /* Take care of parsing a number (anything that starts with a digit). ! 610: Set yylval and return the token type; update lexptr. ! 611: LEN is the number of characters in it. */ ! 612: ! 613: /*** Needs some error checking for the float case ***/ ! 614: ! 615: static int ! 616: parse_number (olen) ! 617: int olen; ! 618: { ! 619: register char *p = lexptr; ! 620: register long n = 0; ! 621: register int c; ! 622: register int base = 10; ! 623: register int len = olen; ! 624: char *err_copy; ! 625: ! 626: extern double atof (); ! 627: ! 628: for (c = 0; c < len; c++) ! 629: if (p[c] == '.') ! 630: { ! 631: /* It's a float since it contains a point. */ ! 632: yylval.dval = atof (p); ! 633: lexptr += len; ! 634: return FLOAT; ! 635: } ! 636: ! 637: if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2))) ! 638: { ! 639: p += 2; ! 640: base = 16; ! 641: len -= 2; ! 642: } ! 643: else if (*p == '0') ! 644: base = 8; ! 645: ! 646: while (len-- > 0) ! 647: { ! 648: c = *p++; ! 649: n *= base; ! 650: if (c >= '0' && c <= '9') ! 651: n += c - '0'; ! 652: else ! 653: { ! 654: if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; ! 655: if (base == 16 && c >= 'a' && c <= 'f') ! 656: n += c - 'a' + 10; ! 657: else if (len == 0 && c == 'l') ! 658: ; ! 659: else ! 660: { ! 661: err_copy = (char *) alloca (olen + 1); ! 662: bcopy (lexptr, err_copy, olen); ! 663: err_copy[olen] = 0; ! 664: error ("Invalid number \"%s\".", err_copy); ! 665: } ! 666: } ! 667: } ! 668: ! 669: lexptr = p; ! 670: yylval.lval = n; ! 671: return INT; ! 672: } ! 673: ! 674: struct token ! 675: { ! 676: char *operator; ! 677: int token; ! 678: enum exp_opcode opcode; ! 679: }; ! 680: ! 681: static struct token tokentab3[] = ! 682: { ! 683: {">>=", ASSIGN_MODIFY, BINOP_RSH}, ! 684: {"<<=", ASSIGN_MODIFY, BINOP_LSH} ! 685: }; ! 686: ! 687: static struct token tokentab2[] = ! 688: { ! 689: {"+=", ASSIGN_MODIFY, BINOP_ADD}, ! 690: {"-=", ASSIGN_MODIFY, BINOP_SUB}, ! 691: {"*=", ASSIGN_MODIFY, BINOP_MUL}, ! 692: {"/=", ASSIGN_MODIFY, BINOP_DIV}, ! 693: {"%=", ASSIGN_MODIFY, BINOP_REM}, ! 694: {"|=", ASSIGN_MODIFY, BINOP_LOGIOR}, ! 695: {"&=", ASSIGN_MODIFY, BINOP_LOGAND}, ! 696: {"^=", ASSIGN_MODIFY, BINOP_LOGXOR}, ! 697: {"++", INCREMENT, BINOP_END}, ! 698: {"--", DECREMENT, BINOP_END}, ! 699: {"->", ARROW, BINOP_END}, ! 700: {"&&", AND, BINOP_END}, ! 701: {"||", OR, BINOP_END}, ! 702: {"::", COLONCOLON, BINOP_END}, ! 703: {"<<", LSH, BINOP_END}, ! 704: {">>", RSH, BINOP_END}, ! 705: {"==", EQUAL, BINOP_END}, ! 706: {"!=", NOTEQUAL, BINOP_END}, ! 707: {"<=", LEQ, BINOP_END}, ! 708: {">=", GEQ, BINOP_END} ! 709: }; ! 710: ! 711: /* Read one token, getting characters through lexptr. */ ! 712: ! 713: static int ! 714: yylex () ! 715: { ! 716: register int c; ! 717: register int namelen; ! 718: register int i; ! 719: register char *tokstart; ! 720: ! 721: retry: ! 722: ! 723: tokstart = lexptr; ! 724: /* See if it is a special token of length 3. */ ! 725: for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++) ! 726: if (!strncmp (tokstart, tokentab3[i].operator, 3)) ! 727: { ! 728: lexptr += 3; ! 729: yylval.opcode = tokentab3[i].opcode; ! 730: return tokentab3[i].token; ! 731: } ! 732: ! 733: /* See if it is a special token of length 2. */ ! 734: for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++) ! 735: if (!strncmp (tokstart, tokentab2[i].operator, 2)) ! 736: { ! 737: lexptr += 2; ! 738: yylval.opcode = tokentab2[i].opcode; ! 739: return tokentab2[i].token; ! 740: } ! 741: ! 742: switch (c = *tokstart) ! 743: { ! 744: case 0: ! 745: return 0; ! 746: ! 747: case ' ': ! 748: case '\t': ! 749: case '\n': ! 750: lexptr++; ! 751: goto retry; ! 752: ! 753: case '\'': ! 754: lexptr++; ! 755: c = *lexptr++; ! 756: if (c == '\\') ! 757: c = parse_escape (&lexptr); ! 758: yylval.lval = c; ! 759: c = *lexptr++; ! 760: if (c != '\'') ! 761: error ("Invalid character constant."); ! 762: return CHAR; ! 763: ! 764: case '(': ! 765: paren_depth++; ! 766: lexptr++; ! 767: return c; ! 768: ! 769: case ')': ! 770: if (paren_depth == 0) ! 771: return 0; ! 772: paren_depth--; ! 773: lexptr++; ! 774: return c; ! 775: ! 776: case ',': ! 777: if (comma_terminates && paren_depth == 0) ! 778: return 0; ! 779: lexptr++; ! 780: return c; ! 781: ! 782: case '+': ! 783: case '-': ! 784: case '*': ! 785: case '/': ! 786: case '%': ! 787: case '|': ! 788: case '&': ! 789: case '^': ! 790: case '~': ! 791: case '!': ! 792: case '@': ! 793: case '<': ! 794: case '>': ! 795: case '[': ! 796: case ']': ! 797: case '.': ! 798: case '?': ! 799: case ':': ! 800: case '=': ! 801: case '{': ! 802: case '}': ! 803: lexptr++; ! 804: return c; ! 805: ! 806: case '"': ! 807: for (namelen = 1; (c = tokstart[namelen]) != '"'; namelen++) ! 808: if (c == '\\') ! 809: { ! 810: c = tokstart[++namelen]; ! 811: if (c >= '0' && c <= '9') ! 812: { ! 813: c = tokstart[++namelen]; ! 814: if (c >= '0' && c <= '9') ! 815: c = tokstart[++namelen]; ! 816: } ! 817: } ! 818: yylval.sval.ptr = tokstart + 1; ! 819: yylval.sval.length = namelen - 1; ! 820: lexptr += namelen + 1; ! 821: return STRING; ! 822: } ! 823: if (c >= '0' && c <= '9') ! 824: { ! 825: /* It's a number */ ! 826: for (namelen = 0; ! 827: c = tokstart[namelen], ! 828: (c == '_' || c == '$' || c == '.' || (c >= '0' && c <= '9') ! 829: || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); ! 830: namelen++) ! 831: ; ! 832: return parse_number (namelen); ! 833: } ! 834: ! 835: if (!(c == '_' || c == '$' ! 836: || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) ! 837: error ("Invalid token in expression."); ! 838: ! 839: /* It is a name. See how long it is. */ ! 840: ! 841: for (namelen = 0; ! 842: c = tokstart[namelen], ! 843: (c == '_' || c == '$' || (c >= '0' && c <= '9') ! 844: || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); ! 845: namelen++) ! 846: ; ! 847: ! 848: /* The token "if" terminates the expression and is NOT ! 849: removed from the input stream. */ ! 850: if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f') ! 851: { ! 852: return 0; ! 853: } ! 854: ! 855: lexptr += namelen; ! 856: ! 857: /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1) ! 858: and $$digits (equivalent to $<-digits> if you could type that). ! 859: Make token type LAST, and put the number (the digits) in yylval. */ ! 860: ! 861: if (*tokstart == '$') ! 862: { ! 863: register int negate = 0; ! 864: c = 1; ! 865: /* Double dollar means negate the number and add -1 as well. ! 866: Thus $$ alone means -1. */ ! 867: if (namelen >= 2 && tokstart[1] == '$') ! 868: { ! 869: negate = 1; ! 870: c = 2; ! 871: } ! 872: if (c == namelen) ! 873: { ! 874: /* Just dollars (one or two) */ ! 875: yylval.lval = - negate; ! 876: return LAST; ! 877: } ! 878: /* Is the rest of the token digits? */ ! 879: for (; c < namelen; c++) ! 880: if (!(tokstart[c] >= '0' && tokstart[c] <= '9')) ! 881: break; ! 882: if (c == namelen) ! 883: { ! 884: yylval.lval = atoi (tokstart + 1 + negate); ! 885: if (negate) ! 886: yylval.lval = - yylval.lval; ! 887: return LAST; ! 888: } ! 889: } ! 890: ! 891: /* Handle tokens that refer to machine registers: ! 892: $ followed by a register name. */ ! 893: ! 894: if (*tokstart == '$') ! 895: for (c = 0; c < NUM_REGS; c++) ! 896: if (namelen - 1 == strlen (reg_names[c]) ! 897: && !strncmp (tokstart + 1, reg_names[c], namelen - 1)) ! 898: { ! 899: yylval.lval = c; ! 900: return REGNAME; ! 901: } ! 902: ! 903: if (namelen == 6 && !strncmp (tokstart, "struct", 6)) ! 904: { ! 905: return STRUCT; ! 906: } ! 907: if (namelen == 5 && !strncmp (tokstart, "union", 5)) ! 908: { ! 909: return UNION; ! 910: } ! 911: if (namelen == 4 && !strncmp (tokstart, "enum", 4)) ! 912: { ! 913: return ENUM; ! 914: } ! 915: if (namelen == 6 && !strncmp (tokstart, "sizeof", 6)) ! 916: { ! 917: return SIZEOF; ! 918: } ! 919: if (namelen == 8 && !strncmp (tokstart, "unsigned", 6)) ! 920: { ! 921: return UNSIGNED; ! 922: } ! 923: yylval.sval.ptr = tokstart; ! 924: yylval.sval.length = namelen; ! 925: ! 926: /* Any other names starting in $ are debugger internal variables. */ ! 927: ! 928: if (*tokstart == '$') ! 929: { ! 930: yylval.ivar = (struct internalvar *) lookup_internalvar (copy_name (yylval.sval) + 1); ! 931: return VARIABLE; ! 932: } ! 933: ! 934: /* Use token-type TYPENAME for symbols that happen to be defined ! 935: currently as names of types; NAME for other symbols. ! 936: The caller is not constrained to care about the distinction. */ ! 937: if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1)) ! 938: return TYPENAME; ! 939: return NAME; ! 940: } ! 941: ! 942: static ! 943: yyerror () ! 944: { ! 945: error ("Invalid syntax in expression."); ! 946: } ! 947: ! 948: /* Return a null-terminated temporary copy of the name ! 949: of a string token. */ ! 950: ! 951: static char * ! 952: copy_name (token) ! 953: struct stoken token; ! 954: { ! 955: bcopy (token.ptr, namecopy, token.length); ! 956: namecopy[token.length] = 0; ! 957: return namecopy; ! 958: } ! 959: ! 960: /* Reverse an expression from suffix form (in which it is constructed) ! 961: to prefix form (in which we can conveniently print or execute it). */ ! 962: ! 963: static void prefixify_subexp (); ! 964: ! 965: static void ! 966: prefixify_expression (expr) ! 967: register struct expression *expr; ! 968: { ! 969: register int len = sizeof (struct expression) + ! 970: expr->nelts * sizeof (union exp_element); ! 971: register struct expression *temp; ! 972: register int inpos = expr->nelts, outpos = 0; ! 973: ! 974: temp = (struct expression *) alloca (len); ! 975: ! 976: /* Copy the original expression into temp. */ ! 977: bcopy (expr, temp, len); ! 978: ! 979: prefixify_subexp (temp, expr, inpos, outpos); ! 980: } ! 981: ! 982: /* Return the number of exp_elements in the subexpression of EXPR ! 983: whose last exp_element is at index ENDPOS - 1 in EXPR. */ ! 984: ! 985: static int ! 986: length_of_subexp (expr, endpos) ! 987: register struct expression *expr; ! 988: register int endpos; ! 989: { ! 990: register int oplen = 1; ! 991: register int args = 0; ! 992: register int i; ! 993: ! 994: i = (int) expr->elts[endpos - 1].opcode; ! 995: ! 996: switch (i) ! 997: { ! 998: case OP_LONG: ! 999: case OP_DOUBLE: ! 1000: oplen = 4; ! 1001: break; ! 1002: ! 1003: case OP_VAR_VALUE: ! 1004: case OP_LAST: ! 1005: case OP_REGISTER: ! 1006: case OP_INTERNALVAR: ! 1007: oplen = 3; ! 1008: break; ! 1009: ! 1010: case OP_FUNCALL: ! 1011: oplen = 3; ! 1012: args = 1 + expr->elts[endpos - 2].longconst; ! 1013: break; ! 1014: ! 1015: case UNOP_CAST: ! 1016: case UNOP_MEMVAL: ! 1017: oplen = 3; ! 1018: args = 1; ! 1019: break; ! 1020: ! 1021: case STRUCTOP_STRUCT: ! 1022: case STRUCTOP_PTR: ! 1023: args = 1; ! 1024: case OP_STRING: ! 1025: oplen = 3 + ((expr->elts[endpos - 2].longconst ! 1026: + sizeof (union exp_element)) ! 1027: / sizeof (union exp_element)); ! 1028: ! 1029: break; ! 1030: ! 1031: case TERNOP_COND: ! 1032: args = 3; ! 1033: break; ! 1034: ! 1035: case BINOP_ASSIGN_MODIFY: ! 1036: oplen = 3; ! 1037: args = 2; ! 1038: break; ! 1039: ! 1040: default: ! 1041: args = 1 + (i < (int) BINOP_END); ! 1042: } ! 1043: ! 1044: while (args > 0) ! 1045: { ! 1046: oplen += length_of_subexp (expr, endpos - oplen); ! 1047: args--; ! 1048: } ! 1049: ! 1050: return oplen; ! 1051: } ! 1052: ! 1053: /* Copy the subexpression ending just before index INEND in INEXPR ! 1054: into OUTEXPR, starting at index OUTBEG. ! 1055: In the process, convert it from suffix to prefix form. */ ! 1056: ! 1057: static void ! 1058: prefixify_subexp (inexpr, outexpr, inend, outbeg) ! 1059: register struct expression *inexpr; ! 1060: struct expression *outexpr; ! 1061: register int inend; ! 1062: int outbeg; ! 1063: { ! 1064: register int oplen = 1; ! 1065: register int args = 0; ! 1066: register int i; ! 1067: int *arglens; ! 1068: enum exp_opcode opcode; ! 1069: ! 1070: /* Compute how long the last operation is (in OPLEN), ! 1071: and also how many preceding subexpressions serve as ! 1072: arguments for it (in ARGS). */ ! 1073: ! 1074: opcode = inexpr->elts[inend - 1].opcode; ! 1075: switch (opcode) ! 1076: { ! 1077: case OP_LONG: ! 1078: case OP_DOUBLE: ! 1079: oplen = 4; ! 1080: break; ! 1081: ! 1082: case OP_VAR_VALUE: ! 1083: case OP_LAST: ! 1084: case OP_REGISTER: ! 1085: case OP_INTERNALVAR: ! 1086: oplen = 3; ! 1087: break; ! 1088: ! 1089: case OP_FUNCALL: ! 1090: oplen = 3; ! 1091: args = 1 + inexpr->elts[inend - 2].longconst; ! 1092: break; ! 1093: ! 1094: case UNOP_CAST: ! 1095: case UNOP_MEMVAL: ! 1096: oplen = 3; ! 1097: args = 1; ! 1098: break; ! 1099: ! 1100: case STRUCTOP_STRUCT: ! 1101: case STRUCTOP_PTR: ! 1102: args = 1; ! 1103: case OP_STRING: ! 1104: oplen = 3 + ((inexpr->elts[inend - 2].longconst ! 1105: + sizeof (union exp_element)) ! 1106: / sizeof (union exp_element)); ! 1107: ! 1108: break; ! 1109: ! 1110: case TERNOP_COND: ! 1111: args = 3; ! 1112: break; ! 1113: ! 1114: case BINOP_ASSIGN_MODIFY: ! 1115: oplen = 3; ! 1116: args = 2; ! 1117: break; ! 1118: ! 1119: default: ! 1120: args = 1 + ((int) opcode < (int) BINOP_END); ! 1121: } ! 1122: ! 1123: /* Copy the final operator itself, from the end of the input ! 1124: to the beginning of the output. */ ! 1125: inend -= oplen; ! 1126: bcopy (&inexpr->elts[inend], &outexpr->elts[outbeg], ! 1127: oplen * sizeof (union exp_element)); ! 1128: outbeg += oplen; ! 1129: ! 1130: /* Find the lengths of the arg subexpressions. */ ! 1131: arglens = (int *) alloca (args * sizeof (int)); ! 1132: for (i = args - 1; i >= 0; i--) ! 1133: { ! 1134: oplen = length_of_subexp (inexpr, inend); ! 1135: arglens[i] = oplen; ! 1136: inend -= oplen; ! 1137: } ! 1138: ! 1139: /* Now copy each subexpression, preserving the order of ! 1140: the subexpressions, but prefixifying each one. ! 1141: In this loop, inend starts at the beginning of ! 1142: the expression this level is working on ! 1143: and marches forward over the arguments. ! 1144: outbeg does similarly in the output. */ ! 1145: for (i = 0; i < args; i++) ! 1146: { ! 1147: oplen = arglens[i]; ! 1148: inend += oplen; ! 1149: prefixify_subexp (inexpr, outexpr, inend, outbeg); ! 1150: outbeg += oplen; ! 1151: } ! 1152: } ! 1153: ! 1154: /* This page contains the two entry points to this file. */ ! 1155: ! 1156: /* Read a C expression from the string *STRINGPTR points to, ! 1157: parse it, and return a pointer to a struct expression that we malloc. ! 1158: Use block BLOCK as the lexical context for variable names; ! 1159: if BLOCK is zero, use the block of the selected stack frame. ! 1160: Meanwhile, advance *STRINGPTR to point after the expression, ! 1161: at the first nonwhite character that is not part of the expression ! 1162: (possibly a null character). ! 1163: ! 1164: If COMMA is nonzero, stop if a comma is reached. */ ! 1165: ! 1166: struct expression * ! 1167: parse_c_1 (stringptr, block, comma) ! 1168: char **stringptr; ! 1169: struct block *block; ! 1170: { ! 1171: struct cleanup *old_chain; ! 1172: ! 1173: lexptr = *stringptr; ! 1174: ! 1175: comma_terminates = comma; ! 1176: ! 1177: if (lexptr == 0 || *lexptr == 0) ! 1178: error_no_arg ("expression to compute"); ! 1179: ! 1180: old_chain = make_cleanup (free_funcalls, 0); ! 1181: funcall_chain = 0; ! 1182: ! 1183: expression_context_block = block ? block : get_selected_block (); ! 1184: ! 1185: namecopy = (char *) alloca (strlen (lexptr) + 1); ! 1186: expout_size = 10; ! 1187: expout_ptr = 0; ! 1188: expout = (struct expression *) xmalloc (sizeof (struct expression) ! 1189: + expout_size * sizeof (union exp_element)); ! 1190: make_cleanup (free_current_contents, &expout); ! 1191: if (yyparse ()) ! 1192: yyerror (); ! 1193: discard_cleanups (old_chain); ! 1194: expout->nelts = expout_ptr; ! 1195: expout = (struct expression *) ! 1196: xrealloc (expout, ! 1197: sizeof (struct expression) ! 1198: + expout_ptr * sizeof (union exp_element)); ! 1199: prefixify_expression (expout); ! 1200: *stringptr = lexptr; ! 1201: return expout; ! 1202: } ! 1203: ! 1204: /* Parse STRING as an expression, and complain if this fails ! 1205: to use up all of the contents of STRING. */ ! 1206: ! 1207: struct expression * ! 1208: parse_c_expression (string) ! 1209: char *string; ! 1210: { ! 1211: register struct expression *exp; ! 1212: exp = parse_c_1 (&string, 0, 0); ! 1213: if (*string) ! 1214: error ("Junk after end of expression."); ! 1215: return exp; ! 1216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.