Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5/src/utilities/sid/rule-simp.c – Rev 2

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
/*** rule-simp.c --- Rule simplification routines.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the SID elimination of identical rules routines.
38
 *
39
 * In order to optimise the elimination of identical rules the following is
40
 * done:
41
 *
42
 * 	- name flow through each rule is numbered, so that differences in
43
 *	  names do not affect the comparisons;
44
 *
45
 *	- alternatives are reordered so that they will appear in the same
46
 *	  order in identical rules;
47
 *
48
 *	- rules are placed in a hash table, so that identical rules will be in
49
 *	  the same slot in the table.
50
 *
51
 * The first two of these make comparisons between two rules quicker.  The
52
 * third reduces the number of comparisons that are made.
53
 *
54
 * One important thing to remember is that the hash value of a rule should not
55
 * depend upon the names of any rules that it calls.  If this was the case,
56
 * and one of the rules was replaced then it would be possible to have two
57
 * identical rules in different slots in the hash table!
58
 *
59
 * If two identical rules are found, one is substituted for the other.  If
60
 * one of the rules is a required rule, then it becomes the used rule.
61
 *
62
 *** Change Log:
63
 * $Log: rule-simp.c,v $
64
 * Revision 1.1.1.1  1998/01/17  15:57:47  release
65
 * First version to be checked into rolling release.
66
 *
67
 * Revision 1.2  1994/12/15  09:58:52  smf
68
 * Brought into line with OSSG C Coding Standards Document, as per
69
 * "CR94_178.sid+tld-update".
70
 *
71
 * Revision 1.1.1.1  1994/07/25  16:04:41  smf
72
 * Initial import of SID 1.8 non shared files.
73
 *
74
**/
75
 
76
/****************************************************************************/
77
 
78
#include "rule.h"
79
#include "action.h"
80
#include "basic.h"
81
#include "entry-list.h"
82
#include "name.h"
83
#include "type.h"
84
 
85
/*--------------------------------------------------------------------------*/
86
 
87
#define EQUALITY_TABLE_SIZE (127)
88
 
89
/*--------------------------------------------------------------------------*/
90
 
91
typedef struct RuleSortListT {
92
    AltP			head;
93
    AltP		       *tail;
94
} RuleSortListT, *RuleSortListP;
95
 
96
typedef struct ReplaceClosureT {
97
    EntryP			from;
98
    EntryP			to;
99
} ReplaceClosureT, *ReplaceClosureP;
100
 
101
/*--------------------------------------------------------------------------*/
102
 
103
static RuleP			equality_table [EQUALITY_TABLE_SIZE];
104
 
105
/*--------------------------------------------------------------------------*/
106
 
107
static void
108
rule_sort_alts PROTO_N ((sort_list))
109
	       PROTO_T (RuleSortListP sort_list)
110
{
111
    AltP alt      = sort_list->head;
112
    AltP scan_alt = alt_next (alt);
113
 
114
    if (scan_alt) {
115
	RuleSortListT lower;
116
	RuleSortListT higher;
117
 
118
	lower.tail  = &(lower.head);
119
	higher.tail = &(higher.head);
120
	for (; scan_alt; scan_alt = alt_next (scan_alt)) {
121
	    if (alt_less_than (scan_alt, alt)) {
122
		*(lower.tail)  = scan_alt;
123
		lower.tail     = alt_next_ref (scan_alt);
124
	    } else {
125
		*(higher.tail) = scan_alt;
126
		higher.tail    = alt_next_ref (scan_alt);
127
	    }
128
	}
129
	*(lower.tail)  = NIL (AltP);
130
	*(higher.tail) = NIL (AltP);
131
	if (lower.head) {
132
	    rule_sort_alts (&lower);
133
	    sort_list->head = lower.head;
134
	    sort_list->tail = lower.tail;
135
	} else {
136
	    sort_list->tail = &(sort_list->head);
137
	}
138
	*(sort_list->tail) = alt;
139
	sort_list->tail    = alt_next_ref (alt);
140
	if (higher.head) {
141
	    rule_sort_alts (&higher);
142
	    *(sort_list->tail) = higher.head;
143
	    sort_list->tail    = higher.tail;
144
	}
145
	*(sort_list->tail) = NIL (AltP);
146
    }
147
}
148
 
149
static void
150
rule_reorder PROTO_N ((rule))
151
	     PROTO_T (RuleP rule)
152
{
153
    RuleSortListT sort_list;
154
 
155
    if ((sort_list.head = rule_alt_head (rule)) != NIL (AltP)) {
156
	sort_list.tail = rule->alt_tail;
157
	rule_sort_alts (&sort_list);
158
	rule->alt_head = sort_list.head;
159
	rule->alt_tail = sort_list.tail;
160
    }
161
}
162
 
163
static void
164
rule_hash_1 PROTO_N ((rule, predicate_id))
165
	    PROTO_T (RuleP  rule X
166
		     EntryP predicate_id)
167
{
168
    unsigned hash_value = (unsigned) (rule_has_empty_alt (rule) ? 3 : 0);
169
    AltP     alt;
170
 
171
    rule_renumber (rule, TRUE, predicate_id);
172
    rule_reorder (rule);
173
    for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
174
	ItemP item;
175
	KeyP  key = NIL (KeyP);
176
 
177
	hash_value += 5;
178
	for (item = alt_item_head (alt); item; item = item_next (item)) {
179
	    hash_value ++;
180
	    if (!item_is_rule (item)) {
181
		key = entry_key (item_entry (item));
182
	    }
183
	}
184
	if (key) {
185
	    hash_value += key_hash_value (key);
186
	}
187
    }
188
    hash_value %= EQUALITY_TABLE_SIZE;
189
    rule_set_next_in_table (rule, equality_table [hash_value]);
190
    equality_table [hash_value] = rule;
191
}
192
 
193
static void
194
rule_hash_for_comparison PROTO_N ((entry, gclosure))
195
			 PROTO_T (EntryP   entry X
196
				  GenericP gclosure)
197
{
198
    if (entry_is_rule (entry)) {
199
	RuleP  rule         = entry_get_rule (entry);
200
	EntryP predicate_id = (EntryP) gclosure;
201
 
202
	rule_hash_1 (rule, predicate_id);
203
    }
204
}
205
 
206
static BoolT
207
rule_equal PROTO_N ((rule1, rule2))
208
	   PROTO_T (RuleP rule1 X
209
		    RuleP rule2)
210
{
211
    AltP alt1;
212
    AltP alt2;
213
 
214
    if ((!types_equal_numbers (rule_param (rule1), rule_param (rule2))) ||
215
	(!types_equal_numbers (rule_result (rule1), rule_result (rule2))) ||
216
	(rule_has_empty_alt (rule1) != rule_has_empty_alt (rule2)) ||
217
	(!alt_equal (rule_get_handler (rule1), rule_get_handler (rule2))) ||
218
	(!non_local_list_is_empty (rule_non_locals (rule1))) ||
219
	(!non_local_list_is_empty (rule_non_locals (rule2)))) {
220
	return (FALSE);
221
    }
222
    for (alt1 = rule_alt_head (rule1), alt2 = rule_alt_head (rule2);
223
	 alt1 && alt2; alt1 = alt_next (alt1), alt2 = alt_next (alt2)) {
224
	ItemP item1;
225
	ItemP item2;
226
 
227
	for (item1 = alt_item_head (alt1), item2 = alt_item_head (alt2);
228
	     item1 && item2;
229
	     item1 = item_next (item1), item2 = item_next (item2)) {
230
	    if ((item_entry (item1) != item_entry (item2)) ||
231
		(!types_equal_numbers (item_param (item1),
232
				       item_param (item2))) ||
233
		(!types_equal_numbers (item_result (item1),
234
				       item_result (item2)))) {
235
		return (FALSE);
236
	    }
237
	}
238
	if (item1 || item2) {
239
	    return (FALSE);
240
	}
241
    }
242
    if (alt1 || alt2) {
243
	return (FALSE);
244
    }
245
    return (TRUE);
246
}
247
 
248
static BoolT
249
rule_do_replacements_1 PROTO_N ((alt, closure))
250
		       PROTO_T (AltP            alt X
251
				ReplaceClosureP closure)
252
{
253
    BoolT changed = FALSE;
254
    ItemP item;
255
 
256
    for (item = alt_item_head (alt); item; item = item_next (item)) {
257
	if (item_entry (item) == closure->from) {
258
	    item_set_entry (item, closure->to);
259
	    changed = TRUE;
260
	}
261
    }
262
    return (changed);
263
}
264
 
265
static void
266
rule_do_replacements PROTO_N ((entry, gclosure))
267
		     PROTO_T (EntryP   entry X
268
			      GenericP gclosure)
269
{
270
    ReplaceClosureP closure = (ReplaceClosureP) gclosure;
271
 
272
    if (entry_is_rule (entry)) {
273
	RuleP rule    = entry_get_rule (entry);
274
	BoolT changed = FALSE;
275
	AltP  alt;
276
 
277
	if ((alt = rule_get_handler (rule)) != NIL (AltP)) {
278
	    if (rule_do_replacements_1 (alt, closure)) {
279
		changed = TRUE;
280
	    }
281
	}
282
	for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
283
	    if (rule_do_replacements_1 (alt, closure)) {
284
		changed = TRUE;
285
	    }
286
	}
287
	if (changed) {
288
	    rule_reorder (rule);
289
	}
290
    }
291
}
292
 
293
static BoolT
294
rule_remove_duplicates_1 PROTO_N ((rule_ref, table))
295
			 PROTO_T (RuleP *rule_ref X
296
				  TableP table)
297
{
298
    BoolT did_remove = FALSE;
299
    RuleP rule;
300
 
301
    while ((rule = *rule_ref) != NIL (RuleP)) {
302
	RuleP *inner_rule_ref = rule_get_next_in_table_ref (rule);
303
	RuleP  inner_rule;
304
 
305
	while ((inner_rule = *inner_rule_ref) != NIL (RuleP)) {
306
	    if (rule_equal (rule, inner_rule)) {
307
		ReplaceClosureT closure;
308
 
309
		if (rule_is_required (inner_rule)) {
310
		    closure.from = rule_entry (rule);
311
		    closure.to   = rule_entry (inner_rule);
312
		    *rule_ref    = rule_get_next_in_table (rule);
313
		} else {
314
		    closure.from    = rule_entry (inner_rule);
315
		    closure.to      = rule_entry (rule);
316
		    *inner_rule_ref = rule_get_next_in_table (inner_rule);
317
		}
318
		table_iter (table, rule_do_replacements, (GenericP) &closure);
319
		did_remove = TRUE;
320
		if (rule != *rule_ref) {
321
		    goto removed_rule;
322
		}
323
	    } else {
324
		inner_rule_ref = rule_get_next_in_table_ref (inner_rule);
325
	    }
326
	}
327
	rule_ref = rule_get_next_in_table_ref (rule);
328
      removed_rule:;
329
    }
330
    return (did_remove);
331
}
332
 
333
/*--------------------------------------------------------------------------*/
334
 
335
void
336
rule_remove_duplicates PROTO_N ((table, predicate_id))
337
		       PROTO_T (TableP table X
338
				EntryP predicate_id)
339
{
340
    BoolT    did_remove;
341
    unsigned i;
342
 
343
    for (i = 0; i < EQUALITY_TABLE_SIZE; i ++) {
344
	equality_table [i] = NIL (RuleP);
345
    }
346
    table_iter (table, rule_hash_for_comparison, (GenericP) predicate_id);
347
    do {
348
	did_remove = FALSE;
349
	for (i = 0; i < EQUALITY_TABLE_SIZE; i ++) {
350
	    if (rule_remove_duplicates_1 (&(equality_table [i]), table)) {
351
		did_remove = TRUE;
352
	    }
353
	}
354
    } while (did_remove);
355
}
356
 
357
/*
358
 * Local variables(smf):
359
 * eval: (include::add-path-entry "../os-interface" "../library")
360
 * eval: (include::add-path-entry "../generated")
361
 * end:
362
**/