|
|
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.