Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
#include "config.h"
32
#include "c_types.h"
33
#include "exp_ops.h"
34
#include "error.h"
35
#include "catalog.h"
36
#include "operator.h"
37
#include "quality.h"
38
#include "syntax.h"
39
 
40
 
41
/*
42
    CHECKING CONTROL FLAG
43
 
44
    This flag may be set to true to temporarily disable the checks in
45
    this module.
46
*/
47
 
48
int suppress_quality = 0 ;
49
 
50
 
51
/*
52
    TABLE OF OPERATIONS
53
 
54
    This table gives the list of operations checked by check_paren.  They
55
    are listed in order of decreasing precedence.  Calls to check_paren
56
    give an entry point into this table beyond which checks are applied.
57
    For example, left shift operations are checked from PAREN_PLUS which
58
    detects 'a << b + c', 'a << b - c', 'a + b << c' and 'a - b << c'.
59
*/
60
 
61
static struct {
62
    unsigned tag ;
63
    int op ;
64
} paren_ops [] = {
65
    { exp_or_tag, lex_or_H1 },		/* PAREN_OR */
66
    { exp_xor_tag, lex_xor_H1 },		/* PAREN_XOR */
67
    { exp_and_tag, lex_and_H1 },		/* PAREN_AND */
68
    { exp_compare_tag, lex_eq },	/* PAREN_EQUALITY */
69
    { exp_test_tag, lex_eq },		/* PAREN_RELATION */
70
    { exp_plus_tag, lex_plus },		/* PAREN_PLUS */
71
    { exp_minus_tag, lex_minus }	/* PAREN_MINUS */
72
} ;
73
 
74
 
75
/*
76
    FIND AN EXPRESSION TAG
77
 
78
    This routine finds the tag associated with the expression e for unusual
79
    parenthesis analysis etc.  Note that an integer constant expression may
80
    have been evaluated to give a simple integer constant, however the top
81
    level operation giving rise to this constant is held in the etag field.
82
*/
83
 
84
static unsigned exp_tag
85
    PROTO_N ( ( e ) )
86
    PROTO_T ( EXP e )
87
{
88
    unsigned tag = TAG_exp ( e ) ;
89
    if ( tag == exp_int_lit_tag ) {
90
	/* Allow for evaluated constants */
91
	tag = DEREF_unsigned ( exp_int_lit_etag ( e ) ) ;
92
    }
93
    return ( tag ) ;
94
}
95
 
96
 
97
/*
98
    CHECK FOR DUBIOUS SHIFTS AND BIT OPERATIONS
99
 
100
    For various pairs of operations, op1 and op2, the resolution of the
101
    expression 'a op1 b op2 c' to '( a op1 b ) op2 c' or 'a op1 ( b op2 c )'
102
    is not obvious.  This routine checks whether the expression 'a op b'
103
    is of this form, checking the operations starting from position n in
104
    the table paren_ops.
105
*/
106
 
107
void check_paren
108
    PROTO_N ( ( n, op, a, b ) )
109
    PROTO_T ( int n X int op X EXP a X EXP b )
110
{
111
    if ( !suppress_quality ) {
112
	int i ;
113
 
114
	/* Check first operand */
115
	unsigned tag = exp_tag ( a ) ;
116
	for ( i = n ; i < array_size ( paren_ops ) ; i++ ) {
117
	    if ( tag == paren_ops [i].tag ) {
118
		int op1 = paren_ops [i].op ;
119
		if ( op1 == lex_eq ) op1 = op_token ( a, op1 ) ;
120
		report ( crt_loc, ERR_expr_paren_left ( op1, op ) ) ;
121
		break ;
122
	    }
123
	}
124
 
125
	/* Check second operand */
126
	tag = exp_tag ( b ) ;
127
	for ( i = n ; i < array_size ( paren_ops ) ; i++ ) {
128
	    if ( tag == paren_ops [i].tag ) {
129
		int op2 = paren_ops [i].op ;
130
		if ( op2 == lex_eq ) op2 = op_token ( b, op2 ) ;
131
		report ( crt_loc, ERR_expr_paren_right ( op, op2 ) ) ;
132
		break ;
133
	    }
134
	}
135
    }
136
    return ;
137
}
138
 
139
 
140
/*
141
    CHECK FOR DUBIOUS RELATIONS
142
 
143
    This routine checks for dubious relations such as 'a < b < c' which
144
    do not have their mathematical meaning.
145
*/
146
 
147
void check_relation
148
    PROTO_N ( ( op, a, b ) )
149
    PROTO_T ( int op X EXP a X EXP b )
150
{
151
    if ( !suppress_quality ) {
152
	/* Check first operand */
153
	unsigned tag = exp_tag ( a ) ;
154
	if ( tag == exp_compare_tag ) {
155
	    int tst = op_token ( a, op ) ;
156
	    report ( crt_loc, ERR_expr_rel_paren ( tst, op ) ) ;
157
	} else if ( tag == exp_test_tag ) {
158
	    int tst = op_token ( a, op ) ;
159
	    report ( crt_loc, ERR_expr_rel_paren ( tst, op ) ) ;
160
	}
161
 
162
	/* Check second operand */
163
	tag = exp_tag ( b ) ;
164
	if ( tag == exp_compare_tag ) {
165
	    int tst = op_token ( b, op ) ;
166
	    report ( crt_loc, ERR_expr_rel_paren ( op, tst ) ) ;
167
	} else if ( tag == exp_test_tag ) {
168
	    int tst = op_token ( b, op ) ;
169
	    report ( crt_loc, ERR_expr_rel_paren ( op, tst ) ) ;
170
	}
171
    }
172
    return ;
173
}
174
 
175
 
176
/*
177
    CHECK FOR DUBIOUS LOGICAL EXPRESSIONS
178
 
179
    The resolution of 'a && b || c' to '( a && b ) || c' is odd.  This
180
    routine checks a logical or expression to see if it is of this form.
181
*/
182
 
183
void check_logic
184
    PROTO_N ( ( a, b ) )
185
    PROTO_T ( EXP a X EXP b )
186
{
187
    if ( !suppress_quality ) {
188
	if ( exp_tag ( a ) == exp_log_and_tag ) {
189
	    int op1 = lex_logical_Hand_H1 ;
190
	    int op2 = lex_logical_Hor_H1 ;
191
	    report ( crt_loc, ERR_expr_paren_left ( op1, op2 ) ) ;
192
	}
193
	if ( exp_tag ( b ) == exp_log_and_tag ) {
194
	    int op1 = lex_logical_Hor_H1 ;
195
	    int op2 = lex_logical_Hand_H1 ;
196
	    report ( crt_loc, ERR_expr_paren_right ( op1, op2 ) ) ;
197
	}
198
    }
199
    return ;
200
}