Subversion Repositories tendra.SVN

Rev

Rev 2 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2 Rev 7
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
Line 82... Line 112...
82
#include "name.h"
112
#include "name.h"
83
#include "type.h"
113
#include "type.h"
84
 
114
 
85
/*--------------------------------------------------------------------------*/
115
/*--------------------------------------------------------------------------*/
86
 
116
 
87
#define EQUALITY_TABLE_SIZE (127)
117
#define EQUALITY_TABLE_SIZE	(127)
88
 
118
 
89
/*--------------------------------------------------------------------------*/
119
/*--------------------------------------------------------------------------*/
90
 
120
 
91
typedef struct RuleSortListT {
121
typedef struct RuleSortListT {
92
    AltP			head;
122
    AltP			head;
Line 98... Line 128...
98
    EntryP			to;
128
    EntryP			to;
99
} ReplaceClosureT, *ReplaceClosureP;
129
} ReplaceClosureT, *ReplaceClosureP;
100
 
130
 
101
/*--------------------------------------------------------------------------*/
131
/*--------------------------------------------------------------------------*/
102
 
132
 
103
static RuleP			equality_table [EQUALITY_TABLE_SIZE];
133
static RuleP		equality_table[EQUALITY_TABLE_SIZE];
104
 
134
 
105
/*--------------------------------------------------------------------------*/
135
/*--------------------------------------------------------------------------*/
106
 
136
 
107
static void
137
static void
108
rule_sort_alts PROTO_N ((sort_list))
-
 
109
	       PROTO_T (RuleSortListP sort_list)
138
rule_sort_alts(RuleSortListP sort_list)
110
{
139
{
111
    AltP alt      = sort_list->head;
140
    AltP alt      = sort_list->head;
112
    AltP scan_alt = alt_next (alt);
141
    AltP scan_alt = alt_next(alt);
113
 
142
 
114
    if (scan_alt) {
143
    if (scan_alt) {
115
	RuleSortListT lower;
144
	RuleSortListT lower;
116
	RuleSortListT higher;
145
	RuleSortListT higher;
117
 
146
 
118
	lower.tail  = &(lower.head);
147
	lower.tail  = &(lower.head);
119
	higher.tail = &(higher.head);
148
	higher.tail = &(higher.head);
120
	for (; scan_alt; scan_alt = alt_next (scan_alt)) {
149
	for (; scan_alt; scan_alt = alt_next(scan_alt)) {
121
	    if (alt_less_than (scan_alt, alt)) {
150
	    if (alt_less_than(scan_alt, alt)) {
122
		*(lower.tail)  = scan_alt;
151
		*(lower.tail) = scan_alt;
123
		lower.tail     = alt_next_ref (scan_alt);
152
		lower.tail     = alt_next_ref(scan_alt);
124
	    } else {
153
	    } else {
125
		*(higher.tail) = scan_alt;
154
		*(higher.tail) = scan_alt;
126
		higher.tail    = alt_next_ref (scan_alt);
155
		higher.tail    = alt_next_ref(scan_alt);
127
	    }
156
	    }
128
	}
157
	}
129
	*(lower.tail)  = NIL (AltP);
158
	*(lower.tail) = NIL(AltP);
130
	*(higher.tail) = NIL (AltP);
159
	*(higher.tail) = NIL(AltP);
131
	if (lower.head) {
160
	if (lower.head) {
132
	    rule_sort_alts (&lower);
161
	    rule_sort_alts(&lower);
133
	    sort_list->head = lower.head;
162
	    sort_list->head = lower.head;
134
	    sort_list->tail = lower.tail;
163
	    sort_list->tail = lower.tail;
135
	} else {
164
	} else {
136
	    sort_list->tail = &(sort_list->head);
165
	    sort_list->tail = &(sort_list->head);
137
	}
166
	}
138
	*(sort_list->tail) = alt;
167
	*(sort_list->tail) = alt;
139
	sort_list->tail    = alt_next_ref (alt);
168
	sort_list->tail    = alt_next_ref(alt);
140
	if (higher.head) {
169
	if (higher.head) {
141
	    rule_sort_alts (&higher);
170
	    rule_sort_alts(&higher);
142
	    *(sort_list->tail) = higher.head;
171
	    *(sort_list->tail) = higher.head;
143
	    sort_list->tail    = higher.tail;
172
	    sort_list->tail    = higher.tail;
144
	}
173
	}
145
	*(sort_list->tail) = NIL (AltP);
174
	*(sort_list->tail) = NIL(AltP);
146
    }
175
    }
147
}
176
}
148
 
177
 
149
static void
178
static void
150
rule_reorder PROTO_N ((rule))
179
rule_reorder(RuleP rule)
151
	     PROTO_T (RuleP rule)
-
 
152
{
180
{
153
    RuleSortListT sort_list;
181
    RuleSortListT sort_list;
154
 
182
 
155
    if ((sort_list.head = rule_alt_head (rule)) != NIL (AltP)) {
183
    if ((sort_list.head = rule_alt_head(rule)) != NIL(AltP)) {
156
	sort_list.tail = rule->alt_tail;
184
	sort_list.tail = rule->alt_tail;
157
	rule_sort_alts (&sort_list);
185
	rule_sort_alts(&sort_list);
158
	rule->alt_head = sort_list.head;
186
	rule->alt_head = sort_list.head;
159
	rule->alt_tail = sort_list.tail;
187
	rule->alt_tail = sort_list.tail;
160
    }
188
    }
161
}
189
}
162
 
190
 
163
static void
191
static void
164
rule_hash_1 PROTO_N ((rule, predicate_id))
192
rule_hash_1(RuleP rule, EntryP predicate_id)
165
	    PROTO_T (RuleP  rule X
-
 
166
		     EntryP predicate_id)
-
 
167
{
193
{
168
    unsigned hash_value = (unsigned) (rule_has_empty_alt (rule) ? 3 : 0);
194
    unsigned hash_value = (unsigned)(rule_has_empty_alt(rule)? 3 : 0);
169
    AltP     alt;
195
    AltP     alt;
170
 
196
 
171
    rule_renumber (rule, TRUE, predicate_id);
197
    rule_renumber(rule, TRUE, predicate_id);
172
    rule_reorder (rule);
198
    rule_reorder(rule);
173
    for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
199
    for (alt = rule_alt_head(rule); alt; alt = alt_next(alt)) {
174
	ItemP item;
200
	ItemP item;
175
	KeyP  key = NIL (KeyP);
201
	KeyP  key = NIL(KeyP);
176
 
202
 
177
	hash_value += 5;
203
	hash_value += 5;
178
	for (item = alt_item_head (alt); item; item = item_next (item)) {
204
	for (item = alt_item_head(alt); item; item = item_next(item)) {
179
	    hash_value ++;
205
	    hash_value++;
180
	    if (!item_is_rule (item)) {
206
	    if (!item_is_rule(item)) {
181
		key = entry_key (item_entry (item));
207
		key = entry_key(item_entry(item));
182
	    }
208
	    }
183
	}
209
	}
184
	if (key) {
210
	if (key) {
185
	    hash_value += key_hash_value (key);
211
	    hash_value += key_hash_value(key);
186
	}
212
	}
187
    }
213
    }
188
    hash_value %= EQUALITY_TABLE_SIZE;
214
    hash_value %= EQUALITY_TABLE_SIZE;
189
    rule_set_next_in_table (rule, equality_table [hash_value]);
215
    rule_set_next_in_table(rule, equality_table[hash_value]);
190
    equality_table [hash_value] = rule;
216
    equality_table[hash_value] = rule;
191
}
217
}
192
 
218
 
193
static void
219
static void
194
rule_hash_for_comparison PROTO_N ((entry, gclosure))
220
rule_hash_for_comparison(EntryP entry, GenericP gclosure)
195
			 PROTO_T (EntryP   entry X
-
 
196
				  GenericP gclosure)
-
 
197
{
221
{
198
    if (entry_is_rule (entry)) {
222
    if (entry_is_rule(entry)) {
199
	RuleP  rule         = entry_get_rule (entry);
223
	RuleP  rule         = entry_get_rule(entry);
200
	EntryP predicate_id = (EntryP) gclosure;
224
	EntryP predicate_id = (EntryP)gclosure;
201
 
225
 
202
	rule_hash_1 (rule, predicate_id);
226
	rule_hash_1(rule, predicate_id);
203
    }
227
    }
204
}
228
}
205
 
229
 
206
static BoolT
230
static BoolT
207
rule_equal PROTO_N ((rule1, rule2))
231
rule_equal(RuleP rule1, RuleP rule2)
208
	   PROTO_T (RuleP rule1 X
-
 
209
		    RuleP rule2)
-
 
210
{
232
{
211
    AltP alt1;
233
    AltP alt1;
212
    AltP alt2;
234
    AltP alt2;
213
 
235
 
214
    if ((!types_equal_numbers (rule_param (rule1), rule_param (rule2))) ||
236
    if ((!types_equal_numbers(rule_param(rule1), rule_param(rule2))) ||
215
	(!types_equal_numbers (rule_result (rule1), rule_result (rule2))) ||
237
	(!types_equal_numbers(rule_result(rule1), rule_result(rule2))) ||
216
	(rule_has_empty_alt (rule1) != rule_has_empty_alt (rule2)) ||
238
	(rule_has_empty_alt(rule1) != rule_has_empty_alt(rule2)) ||
217
	(!alt_equal (rule_get_handler (rule1), rule_get_handler (rule2))) ||
239
	(!alt_equal(rule_get_handler(rule1), rule_get_handler(rule2))) ||
218
	(!non_local_list_is_empty (rule_non_locals (rule1))) ||
240
	(!non_local_list_is_empty(rule_non_locals(rule1))) ||
219
	(!non_local_list_is_empty (rule_non_locals (rule2)))) {
241
	(!non_local_list_is_empty(rule_non_locals(rule2)))) {
220
	return (FALSE);
242
	return(FALSE);
221
    }
243
    }
222
    for (alt1 = rule_alt_head (rule1), alt2 = rule_alt_head (rule2);
244
    for (alt1 = rule_alt_head(rule1), alt2 = rule_alt_head(rule2);
223
	 alt1 && alt2; alt1 = alt_next (alt1), alt2 = alt_next (alt2)) {
245
	 alt1 && alt2; alt1 = alt_next(alt1), alt2 = alt_next(alt2)) {
224
	ItemP item1;
246
	ItemP item1;
225
	ItemP item2;
247
	ItemP item2;
226
 
248
 
227
	for (item1 = alt_item_head (alt1), item2 = alt_item_head (alt2);
249
	for (item1 = alt_item_head(alt1), item2 = alt_item_head(alt2);
228
	     item1 && item2;
250
	     item1 && item2;
229
	     item1 = item_next (item1), item2 = item_next (item2)) {
251
	     item1 = item_next(item1), item2 = item_next(item2)) {
230
	    if ((item_entry (item1) != item_entry (item2)) ||
252
	    if ((item_entry(item1) != item_entry(item2)) ||
231
		(!types_equal_numbers (item_param (item1),
253
		(!types_equal_numbers(item_param(item1), item_param(item2))) ||
232
				       item_param (item2))) ||
-
 
233
		(!types_equal_numbers (item_result (item1),
254
		(!types_equal_numbers(item_result(item1),
234
				       item_result (item2)))) {
255
				      item_result(item2)))) {
235
		return (FALSE);
256
		return(FALSE);
236
	    }
257
	    }
237
	}
258
	}
238
	if (item1 || item2) {
259
	if (item1 || item2) {
239
	    return (FALSE);
260
	    return(FALSE);
240
	}
261
	}
241
    }
262
    }
242
    if (alt1 || alt2) {
263
    if (alt1 || alt2) {
243
	return (FALSE);
264
	return(FALSE);
244
    }
265
    }
245
    return (TRUE);
266
    return(TRUE);
246
}
267
}
247
 
268
 
248
static BoolT
269
static BoolT
249
rule_do_replacements_1 PROTO_N ((alt, closure))
270
rule_do_replacements_1(AltP alt, ReplaceClosureP closure)
250
		       PROTO_T (AltP            alt X
-
 
251
				ReplaceClosureP closure)
-
 
252
{
271
{
253
    BoolT changed = FALSE;
272
    BoolT changed = FALSE;
254
    ItemP item;
273
    ItemP item;
255
 
274
 
256
    for (item = alt_item_head (alt); item; item = item_next (item)) {
275
    for (item = alt_item_head(alt); item; item = item_next(item)) {
257
	if (item_entry (item) == closure->from) {
276
	if (item_entry(item) == closure->from) {
258
	    item_set_entry (item, closure->to);
277
	    item_set_entry(item, closure->to);
259
	    changed = TRUE;
278
	    changed = TRUE;
260
	}
279
	}
261
    }
280
    }
262
    return (changed);
281
    return(changed);
263
}
282
}
264
 
283
 
265
static void
284
static void
266
rule_do_replacements PROTO_N ((entry, gclosure))
285
rule_do_replacements(EntryP entry, GenericP gclosure)
267
		     PROTO_T (EntryP   entry X
-
 
268
			      GenericP gclosure)
-
 
269
{
286
{
270
    ReplaceClosureP closure = (ReplaceClosureP) gclosure;
287
    ReplaceClosureP closure = (ReplaceClosureP)gclosure;
271
 
288
 
272
    if (entry_is_rule (entry)) {
289
    if (entry_is_rule(entry)) {
273
	RuleP rule    = entry_get_rule (entry);
290
	RuleP rule    = entry_get_rule(entry);
274
	BoolT changed = FALSE;
291
	BoolT changed = FALSE;
275
	AltP  alt;
292
	AltP  alt;
276
 
293
 
277
	if ((alt = rule_get_handler (rule)) != NIL (AltP)) {
294
	if ((alt = rule_get_handler(rule)) != NIL(AltP)) {
278
	    if (rule_do_replacements_1 (alt, closure)) {
295
	    if (rule_do_replacements_1(alt, closure)) {
279
		changed = TRUE;
296
		changed = TRUE;
280
	    }
297
	    }
281
	}
298
	}
282
	for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
299
	for (alt = rule_alt_head(rule); alt; alt = alt_next(alt)) {
283
	    if (rule_do_replacements_1 (alt, closure)) {
300
	    if (rule_do_replacements_1(alt, closure)) {
284
		changed = TRUE;
301
		changed = TRUE;
285
	    }
302
	    }
286
	}
303
	}
287
	if (changed) {
304
	if (changed) {
288
	    rule_reorder (rule);
305
	    rule_reorder(rule);
289
	}
306
	}
290
    }
307
    }
291
}
308
}
292
 
309
 
293
static BoolT
310
static BoolT
294
rule_remove_duplicates_1 PROTO_N ((rule_ref, table))
311
rule_remove_duplicates_1(RuleP *rule_ref, TableP table)
295
			 PROTO_T (RuleP *rule_ref X
-
 
296
				  TableP table)
-
 
297
{
312
{
298
    BoolT did_remove = FALSE;
313
    BoolT did_remove = FALSE;
299
    RuleP rule;
314
    RuleP rule;
300
 
315
 
301
    while ((rule = *rule_ref) != NIL (RuleP)) {
316
    while ((rule = *rule_ref) != NIL(RuleP)) {
302
	RuleP *inner_rule_ref = rule_get_next_in_table_ref (rule);
317
	RuleP *inner_rule_ref = rule_get_next_in_table_ref(rule);
303
	RuleP  inner_rule;
318
	RuleP  inner_rule;
304
 
319
 
305
	while ((inner_rule = *inner_rule_ref) != NIL (RuleP)) {
320
	while ((inner_rule = *inner_rule_ref) != NIL(RuleP)) {
306
	    if (rule_equal (rule, inner_rule)) {
321
	    if (rule_equal(rule, inner_rule)) {
307
		ReplaceClosureT closure;
322
		ReplaceClosureT closure;
308
 
323
 
309
		if (rule_is_required (inner_rule)) {
324
		if (rule_is_required(inner_rule)) {
310
		    closure.from = rule_entry (rule);
325
		    closure.from = rule_entry(rule);
311
		    closure.to   = rule_entry (inner_rule);
326
		    closure.to   = rule_entry(inner_rule);
312
		    *rule_ref    = rule_get_next_in_table (rule);
327
		    *rule_ref    = rule_get_next_in_table(rule);
313
		} else {
328
		} else {
314
		    closure.from    = rule_entry (inner_rule);
329
		    closure.from    = rule_entry(inner_rule);
315
		    closure.to      = rule_entry (rule);
330
		    closure.to      = rule_entry(rule);
316
		    *inner_rule_ref = rule_get_next_in_table (inner_rule);
331
		    *inner_rule_ref = rule_get_next_in_table(inner_rule);
317
		}
332
		}
318
		table_iter (table, rule_do_replacements, (GenericP) &closure);
333
		table_iter(table, rule_do_replacements, (GenericP)&closure);
319
		did_remove = TRUE;
334
		did_remove = TRUE;
320
		if (rule != *rule_ref) {
335
		if (rule != *rule_ref) {
321
		    goto removed_rule;
336
		    goto removed_rule;
322
		}
337
		}
323
	    } else {
338
	    } else {
324
		inner_rule_ref = rule_get_next_in_table_ref (inner_rule);
339
		inner_rule_ref = rule_get_next_in_table_ref(inner_rule);
325
	    }
340
	    }
326
	}
341
	}
327
	rule_ref = rule_get_next_in_table_ref (rule);
342
	rule_ref = rule_get_next_in_table_ref(rule);
328
      removed_rule:;
343
      removed_rule:;
329
    }
344
    }
330
    return (did_remove);
345
    return(did_remove);
331
}
346
}
332
 
347
 
333
/*--------------------------------------------------------------------------*/
348
/*--------------------------------------------------------------------------*/
334
 
349
 
335
void
350
void
336
rule_remove_duplicates PROTO_N ((table, predicate_id))
351
rule_remove_duplicates(TableP table, EntryP predicate_id)
337
		       PROTO_T (TableP table X
-
 
338
				EntryP predicate_id)
-
 
339
{
352
{
340
    BoolT    did_remove;
353
    BoolT    did_remove;
341
    unsigned i;
354
    unsigned i;
342
 
355
 
343
    for (i = 0; i < EQUALITY_TABLE_SIZE; i ++) {
356
    for (i = 0; i < EQUALITY_TABLE_SIZE; i++) {
344
	equality_table [i] = NIL (RuleP);
357
	equality_table[i] = NIL(RuleP);
345
    }
358
    }
346
    table_iter (table, rule_hash_for_comparison, (GenericP) predicate_id);
359
    table_iter(table, rule_hash_for_comparison, (GenericP)predicate_id);
347
    do {
360
    do {
348
	did_remove = FALSE;
361
	did_remove = FALSE;
349
	for (i = 0; i < EQUALITY_TABLE_SIZE; i ++) {
362
	for (i = 0; i < EQUALITY_TABLE_SIZE; i++) {
350
	    if (rule_remove_duplicates_1 (&(equality_table [i]), table)) {
363
	    if (rule_remove_duplicates_1(&(equality_table[i]), table)) {
351
		did_remove = TRUE;
364
		did_remove = TRUE;
352
	    }
365
	    }
353
	}
366
	}
354
    } while (did_remove);
367
    } while (did_remove);
355
}
368
}