during the process of parsing; the lower levels of the tree always
come first in the result.
- Note that malloc's and realloc's in this file are transformed to
- xmalloc and xrealloc respectively by the same sed command in the
- makefile that remaps any other malloc/realloc inserted by the parser
- generator. Doing this with #defines and trying to control the interaction
- with include files (<malloc.h> and <stdlib.h> for example) just became
- too messy, particularly when such includes can be inserted at random
- times by the parser generator.
-
- Also note that the language accepted by this parser is more liberal
+ Note that the language accepted by this parser is more liberal
than the one accepted by an actual Chill compiler. For example, the
language rule that a simple name string can not be one of the reserved
simple name strings is not enforced (e.g "case" is not treated as a
*/
#include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
#include <ctype.h>
#include "expression.h"
#include "language.h"
enum ch_terminal {
END_TOKEN = 0,
/* '\001' ... '\xff' come first. */
+ OPEN_PAREN = '(',
TOKEN_NOT_READ = 999,
INTEGER_LITERAL,
BOOLEAN_LITERAL,
static void parse_if_expression_body PARAMS((void));
static void write_lower_upper_value PARAMS ((enum exp_opcode, struct type *));
static enum ch_terminal ch_lex ();
+static void calculate_array_length PARAMS ((struct type *));
#define MAX_LOOK_AHEAD 2
static enum ch_terminal terminal_buffer[MAX_LOOK_AHEAD+1] = {
return terminal_buffer[i];
}
+#if 0
+
static void
pushback_token (code, node)
enum ch_terminal code;
val_buffer[0] = node;
}
+#endif
+
static void
forward_token_()
{
write_exp_elt_opcode (OP_ARRAY);
if (mode)
{
+ struct type *type = check_typedef (mode);
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_SET)
+ error ("invalid tuple mode");
write_exp_elt_opcode (UNOP_CAST);
write_exp_elt_type (mode);
write_exp_elt_opcode (UNOP_CAST);
if (PEEK_TOKEN () != TYPENAME)
error ("missing MODENAME after ARRAY()");
type = PEEK_LVAL().tsym.type;
+ FORWARD_TOKEN ();
expect ('(', NULL);
parse_expr ();
expect (')', "missing right parenthesis");
break;
case GENERAL_PROCEDURE_NAME:
case LOCATION_NAME:
- write_exp_elt_opcode (OP_VAR_VALUE);
- write_exp_elt_block (NULL);
- write_exp_elt_sym (PEEK_LVAL ().ssym.sym);
- write_exp_elt_opcode (OP_VAR_VALUE);
- FORWARD_TOKEN ();
+ {
+ struct type *type;
+
+ /* FIXME: look at calculate_array_length */
+ type = PEEK_LVAL().ssym.sym->type;
+ if (type && TYPE_CODE (type) == TYPE_CODE_ARRAY &&
+ TYPE_LENGTH (type) == 0)
+ calculate_array_length (type);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (PEEK_LVAL ().ssym.sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ FORWARD_TOKEN ();
+ }
break;
case GDB_VARIABLE: /* gdb specific */
FORWARD_TOKEN ();
write_exp_elt_type (builtin_type_int);
write_exp_elt_opcode (UNOP_CAST);
break;
+ case CARD:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CARD);
+ break;
+ case MAX_TOKEN:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CHMAX);
+ break;
+ case MIN_TOKEN:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CHMIN);
+ break;
case PRED: op_name = "PRED"; goto unimplemented_unary_builtin;
case SUCC: op_name = "SUCC"; goto unimplemented_unary_builtin;
case ABS: op_name = "ABS"; goto unimplemented_unary_builtin;
- case CARD: op_name = "CARD"; goto unimplemented_unary_builtin;
- case MAX_TOKEN: op_name = "MAX"; goto unimplemented_unary_builtin;
- case MIN_TOKEN: op_name = "MIN"; goto unimplemented_unary_builtin;
unimplemented_unary_builtin:
parse_unary_call ();
error ("not implemented: %s builtin function", op_name);
}
write_exp_elt_opcode (UNOP_IND);
continue;
- case '(':
+ case OPEN_PAREN:
parse_call ();
continue;
case CHARACTER_STRING_LITERAL:
write_exp_elt_longcst (1);
write_exp_elt_opcode (MULTI_SUBSCRIPT);
continue;
+ case END_TOKEN:
+ case TOKEN_NOT_READ:
+ case INTEGER_LITERAL:
+ case BOOLEAN_LITERAL:
+ case FLOAT_LITERAL:
+ case GENERAL_PROCEDURE_NAME:
+ case LOCATION_NAME:
+ case EMPTINESS_LITERAL:
+ case TYPENAME:
+ case CASE:
+ case OF:
+ case ESAC:
+ case LOGIOR:
+ case ORIF:
+ case LOGXOR:
+ case LOGAND:
+ case ANDIF:
+ case NOTEQUAL:
+ case GEQ:
+ case LEQ:
+ case IN:
+ case SLASH_SLASH:
+ case MOD:
+ case REM:
+ case NOT:
+ case RECEIVE:
+ case UP:
+ case IF:
+ case THEN:
+ case ELSE:
+ case FI:
+ case ELSIF:
+ case ILLEGAL_TOKEN:
+ case NUM:
+ case PRED:
+ case SUCC:
+ case ABS:
+ case CARD:
+ case MAX_TOKEN:
+ case MIN_TOKEN:
+ case ADDR_TOKEN:
+ case SIZE:
+ case UPPER:
+ case LOWER:
+ case LENGTH:
+ case ARRAY:
+ case GDB_VARIABLE:
+ case GDB_ASSIGNMENT:
+ break;
}
break;
}
tempbufsize += growby;
if (tempbuf == NULL)
{
- tempbuf = (char *) malloc (tempbufsize);
+ tempbuf = (char *) xmalloc (tempbufsize);
}
else
{
- tempbuf = (char *) realloc (tempbuf, tempbufsize);
+ tempbuf = (char *) xrealloc (tempbuf, tempbufsize);
}
}
match_string_literal ()
{
char *tokptr = lexptr;
+ int in_ctrlseq = 0;
+ LONGEST ival;
for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
{
CHECKBUF (1);
- if (*tokptr == *lexptr)
+ tryagain: ;
+ if (in_ctrlseq)
{
- if (*(tokptr + 1) == *lexptr)
+ /* skip possible whitespaces */
+ while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+ tokptr++;
+ if (*tokptr == ')')
{
+ in_ctrlseq = 0;
tokptr++;
+ goto tryagain;
+ }
+ else if (*tokptr != ',')
+ error ("Invalid control sequence");
+ tokptr++;
+ /* skip possible whitespaces */
+ while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+ tokptr++;
+ if (!decode_integer_literal (&ival, &tokptr))
+ error ("Invalid control sequence");
+ tokptr--;
+ }
+ else if (*tokptr == *lexptr)
+ {
+ if (*(tokptr + 1) == *lexptr)
+ {
+ ival = *tokptr++;
}
else
{
break;
}
}
- tempbuf[tempbufindex++] = *tokptr;
+ else if (*tokptr == '^')
+ {
+ if (*(tokptr + 1) == '(')
+ {
+ in_ctrlseq = 1;
+ tokptr += 2;
+ if (!decode_integer_literal (&ival, &tokptr))
+ error ("Invalid control sequence");
+ tokptr--;
+ }
+ else if (*(tokptr + 1) == '^')
+ ival = *tokptr++;
+ else
+ error ("Invalid control sequence");
+ }
+ else
+ ival = *tokptr;
+ tempbuf[tempbufindex++] = ival;
}
+ if (in_ctrlseq)
+ error ("Invalid control sequence");
+
if (*tokptr == '\0' /* no terminator */
|| (tempbufindex == 1 && *tokptr == '\'')) /* char literal */
{
Note that more than a single character, enclosed in single quotes, is
a string literal.
- Also note that the control sequence form is not in GNU Chill since it
- is ambiguous with the string literal form using single quotes. I.E.
- is '^(7)' a character literal or a string literal. In theory it it
- possible to tell by context, but GNU Chill doesn't accept the control
- sequence form, so neither do we (for now the code is disabled).
-
Returns CHARACTER_LITERAL if a match is found.
*/
/* Determine which form we have, either a control sequence or the
single character form. */
- if ((*tokptr == '^') && (*(tokptr + 1) == '('))
+ if (*tokptr == '^')
{
-#if 0 /* Disable, see note above. -fnf */
- /* Match and decode a control sequence. Return zero if we don't
- find a valid integer literal, or if the next unconsumed character
- after the integer literal is not the trailing ')'.
- FIXME: We currently don't handle the multiple integer literal
- form. */
- tokptr += 2;
- if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+ if (*(tokptr + 1) == '(')
+ {
+ /* Match and decode a control sequence. Return zero if we don't
+ find a valid integer literal, or if the next unconsumed character
+ after the integer literal is not the trailing ')'. */
+ tokptr += 2;
+ if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+ {
+ return (0);
+ }
+ }
+ else if (*(tokptr + 1) == '^')
{
- return (0);
+ ival = *tokptr;
+ tokptr += 2;
}
-#else
- return (0);
-#endif
+ else
+ /* fail */
+ error ("Invalid control sequence");
+ }
+ else if (*tokptr == '\'')
+ {
+ /* this must be duplicated */
+ ival = *tokptr;
+ tokptr += 2;
}
else
{
ival = *tokptr++;
}
-
+
/* The trailing quote has not yet been consumed. If we don't find
it, then we have no match. */
digit += 10;
break;
default:
- error ("Invalid character in bitstring or integer.");
+ /* this is not a bitstring literal, probably an integer */
+ return 0;
}
if (digit >= 1 << bits_per_char)
{
break;
case LOC_TYPEDEF:
yylval.tsym.type = SYMBOL_TYPE (sym);
+ calculate_array_length (yylval.tsym.type);
return TYPENAME;
case LOC_UNDEF:
case LOC_CONST_BYTES:
case LOC_OPTIMIZED_OUT:
error ("Symbol \"%s\" names no location.", inputname);
break;
+ case LOC_UNRESOLVED:
+ error ("unhandled SYMBOL_CLASS in ch_lex()");
+ break;
}
}
else if (!have_full_symbols () && !have_partial_symbols ())
}
}
+/* In certain cases it could happen, that an array type doesn't
+ have a length (this have to do with seizing). The reason is
+ shown in the following stabs:
+
+ .stabs "m_x:Tt81=s36i:1,0,32;ar:82=ar80;0;1;83=xsm_struct:,32,256;;",128,0,25,0
+
+ .stabs "m_struct:Tt83=s16f1:9,0,16;f2:85=*84,32,32;f3:84,64,64;;",128,0,10,0
+
+ When processing t81, the array ar80 doesn't have a length, cause
+ struct m_struct is specified extern at thse moment. Afterwards m_struct
+ gets specified and updated, but not the surrounding type.
+
+ So we walk through array's till we find a type with a length and
+ calculate the array length.
+
+ FIXME: Where may this happen too ?
+ */
+
+static void
+calculate_array_length (type)
+ struct type *type;
+{
+ struct type *target_type;
+ struct type *range_type;
+ LONGEST lower_bound, upper_bound;
+
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
+ /* not an array, stop processing */
+ return;
+
+ target_type = TYPE_TARGET_TYPE (type);
+ range_type = TYPE_FIELD_TYPE (type, 0);
+ lower_bound = TYPE_FIELD_BITPOS (range_type, 0);
+ upper_bound = TYPE_FIELD_BITPOS (range_type, 1);
+
+ if (TYPE_LENGTH (target_type) == 0 &&
+ TYPE_CODE (target_type) == TYPE_CODE_ARRAY)
+ /* we've got another array */
+ calculate_array_length (target_type);
+
+ TYPE_LENGTH (type) = (upper_bound - lower_bound + 1) * TYPE_LENGTH (target_type);
+}
+
void
chill_error (msg)
char *msg;