-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtab.c
581 lines (456 loc) · 19.5 KB
/
tab.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
/*
FILE NAME: tab.c
Copyright (C) 1997-2016 Vladimir Makarov.
Written by Vladimir Makarov <[email protected]>
This file is part of the tool SPRUT.
This is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
TITLE: All tables of SPRUT (internal representation description
translator)
DESCRIPTION: This file contains abstract data which implement
the following tables
table of identifiers
table of double declaration identifiers
table of predefined types and node types
table of fields (key is the field identifier)
table of node type fields (key is the field identifier
and the field node type)
SPECIAL CONSIDERATION:
Defining macro `NDEBUG' (e.g. by option `-D' in C compiler
command line) during the file compilation disables to fix
some internal errors and errors of usage of the tables.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* #ifdef HAVE_CONFIG_H */
#include <string.h>
#include "hashtab.h"
#include "ird.h"
#include "common.h"
#include "tab.h"
#include <assert.h>
#include <limits.h>
/* This page contains common functions of some abstract data. */
/* The following function evaluates hash value of string. The
function returns hash value (0..UINT_MAX) of given string. */
static unsigned
string_hash_value (const char *string)
{
unsigned result, i;
for (result = i = 0;*string++ != '\0'; i++)
result += ((unsigned char) *string << (i % CHAR_BIT));
return result;
}
/* The following function tests strings on equality. The function
retruns 1 if the strings are equal, 0 otherwise. */
static int
string_equality (const char *string_1, const char *string_2)
{
return strcmp (string_1, string_2) == 0;
}
/* This page contains abstract data `tables of identifiers'. Elements
of the table is strings representing identifiers. */
/* The following function evaluates hash value of identifier string.
The function is used by abstract data `hash table'. The function
returns hash value (0..UINT_MAX) of given identifier string. */
static unsigned
identifier_hash_function (hash_table_entry_t identifier)
{
return string_hash_value (identifier);
}
/* The following function tests identifier strings on equality. The
function is used by abstract data `hash table'. The function
returns 1 if the identifier strings are equal, 0 otherwise. */
static int
identifier_eq_function (hash_table_entry_t identifier_1,
hash_table_entry_t identifier_2)
{
return string_equality (identifier_1, identifier_2);
}
/* The identifier table itself is represented by the following variable. */
static hash_table_t identifier_table;
/* The following function inserts identifier string into the table.
The function does nothing if an identifier string with the same key
exists already in the table. The function returns identifier
string in the table with the same key as given identifier. */
char *
insert_identifier (const char *identifier)
{
hash_table_entry_t *entry_ptr;
entry_ptr = find_hash_table_entry (identifier_table, identifier, TRUE);
if (*entry_ptr == NULL)
*entry_ptr = (hash_table_entry_t) identifier;
else
assert (strcmp (identifier, *entry_ptr) == 0);
return (char *) *entry_ptr;
}
/* The following function creates empty identifier table. The
function must be called only once before any work with the
identifier table. */
void
initiate_identifier_table (void)
{
identifier_table = create_hash_table (1000, identifier_hash_function,
identifier_eq_function);
}
/* The following function deletes given identifier table. Only call
of function `initiate_identifier_table' is possible immediately
after this function call. */
void
finish_identifier_table (void)
{
delete_hash_table (identifier_table);
}
/* This page contains abstract data `table of double declaration
identifiers'. Elements of the table is nodes representing
identifiers in double node type declarations. Key of the table elements
is identifier strings of given nodes. */
/* The following function evaluates hash value of double node type
declaration identifier. The function is used by abstract data
`hash table'. The function returns hash value (0..UINT_MAX) of
given double node type declaration identifier. */
static unsigned
double_declaration_identifier_hash_function (hash_table_entry_t identifier)
{
char *str;
unsigned result, i;
assert (identifier != NULL
&& IR_identifier_itself ((IR_node_t) identifier) != NULL);
for (str = IR_identifier_itself ((IR_node_t) identifier), result = i = 0;
*str++ != '\0'; i++)
result += ((unsigned char) *str << (i % CHAR_BIT));
return result;
}
/* The following function tests double node type declaration
identifiers on equality of their keys. The function is used by
abstract data `hash table'. The function returns 1 if the double
node type declaration identifiers have the same key, 0
otherwise. */
static int
double_declaration_identifier_eq_function (hash_table_entry_t identifier_1,
hash_table_entry_t identifier_2)
{
assert (identifier_1 != NULL
&& IR_identifier_itself ((IR_node_t) identifier_1) != NULL
&& identifier_2 != NULL
&& IR_identifier_itself ((IR_node_t) identifier_2) != NULL);
return strcmp (IR_identifier_itself ((IR_node_t) identifier_1),
IR_identifier_itself ((IR_node_t) identifier_2)) == 0;
}
/* The double declaration identifier table itself is represented by
the following variable. */
static hash_table_t double_declaration_identifier_table;
/* The following function inserts double node type declaration
identifier into the table. The function does nothing if an
identifier with the same key exists already in the table. The
function returns identifier node in the table with the same key as
given identifier node. */
IR_node_t
insert_double_declaration_identifier (IR_node_t identifier)
{
hash_table_entry_t *entry_ptr;
entry_ptr = find_hash_table_entry (double_declaration_identifier_table,
identifier, TRUE);
if (*entry_ptr == NULL)
*entry_ptr = (hash_table_entry_t) identifier;
return (IR_node_t) *entry_ptr;
}
/* The following function searches for double node type declaration
identifier in the table with the same key as given identifier node.
The function retruns identifier node in the table with the same key
as given identifier node, NULL if such identifier node does not
exist in the table. */
IR_node_t
find_double_declaration_identifier (IR_node_t identifier)
{
hash_table_entry_t *entry_ptr;
entry_ptr = find_hash_table_entry (double_declaration_identifier_table,
identifier, FALSE);
assert (*entry_ptr == NULL
|| strcmp (IR_identifier_itself (identifier),
IR_identifier_itself ((IR_node_t) *entry_ptr)) == 0);
return (IR_node_t) *entry_ptr;
}
/* The following function creates empty double node type declaration
identifier table. The function must be called only once before any
work with the double node type declaration identifier table. */
void
initiate_double_declaration_identifier_table (void)
{
double_declaration_identifier_table
= create_hash_table (10, double_declaration_identifier_hash_function,
double_declaration_identifier_eq_function);
}
/* The following function deletes given double node type declaration
identifier table. Only call of function
`initiate_double_declaration_identifier_table' is possible
immediately after this function call. */
void
finish_double_declaration_identifier_table (void)
{
delete_hash_table (double_declaration_identifier_table);
}
/* This page contains abstract data `table of types'. Elements of the
table is nodes representing node types and predefined types. Key of
the table elements is identifier strings of nodes representing identifiers
of the types. */
/* The following function evaluates hash value of node type or
predefined type. The function is used by abstract data
`hash table'. The function returns hash value (0..UINT_MAX) of
given node type or predefined type. */
static unsigned
type_hash_function (hash_table_entry_t type)
{
IR_node_t node = (IR_node_t) type;
assert (node != NULL
&& (IR_NODE_MODE (node) == IR_NM_node_type
|| IR_NODE_MODE (node) == IR_NM_predefined_type));
return (string_hash_value (IR_identifier_itself (IR_type_identifier
(node))));
}
/* The following function tests node types or/and predefined types on
equality of their keys. The function is used by abstract data
`hash table'. The function returns 1 if the types have the same
key, 0 otherwise. */
static int
type_eq_function (hash_table_entry_t type_1, hash_table_entry_t type_2)
{
IR_node_t node_1 = (IR_node_t) type_1;
IR_node_t node_2 = (IR_node_t) type_2;
assert
(node_1 != NULL && (IR_NODE_MODE (node_1) == IR_NM_node_type
|| IR_NODE_MODE (node_1) == IR_NM_predefined_type)
&& node_2 != NULL && (IR_NODE_MODE (node_2) == IR_NM_node_type
|| IR_NODE_MODE (node_2) == IR_NM_predefined_type));
return (string_equality (IR_identifier_itself (IR_type_identifier (node_1)),
IR_identifier_itself (IR_type_identifier
(node_2))));
}
/* The type table itself is represented by the following variable. */
static hash_table_t type_table;
/* The following function inserts node type or predefined type into
the table. The function does nothing if an type with the same key
exists already in the table. The function returns node in the
table with the same key as node representing given node type or
predefined type. */
IR_node_t
insert_type (IR_node_t type)
{
hash_table_entry_t *entry_ptr;
entry_ptr = find_hash_table_entry (type_table, type, TRUE);
if (*entry_ptr == NULL)
*entry_ptr = (hash_table_entry_t) type;
return (IR_node_t) *entry_ptr;
}
/* The following variable value is node representing node type. The node
used for searching type with given identifier. */
static IR_node_t work_node_type;
/* The following function searches for node type or/and predefined
type in the table with the same key as node representing identifier
of the type. The function returns node found in the table, NULL if
such node does not exist in the table. */
IR_node_t
find_type (IR_node_t identifier)
{
hash_table_entry_t *entry_ptr;
IR_set_type_identifier (work_node_type, identifier);
entry_ptr = find_hash_table_entry (type_table, work_node_type, FALSE);
return (IR_node_t) *entry_ptr;
}
/* The following function creates empty node type or/and predefined
type table and node representing node type and used for searching
type with given identifier. The function must be called only once
before any work with the type table. */
void
initiate_type_table (void)
{
work_node_type = IR_create_node (IR_NM_node_type);
type_table = create_hash_table (200, type_hash_function, type_eq_function);
}
/* The following function deletes given type table. Only call of
function `initiate_type_table' is possible immediately after this
function call. */
void
finish_type_table (void)
{
delete_hash_table (type_table);
}
/* This page contains abstract data `table of fields'. Elements of the
table is nodes representing fields. Key of the table elements is
identifier strings of nodes representing identifiers
of the fields. */
/* The follwoing function evaluates hash value of field. The function
is used by abstract data `hash table'. The function returns hash
value (0..UINT_MAX) of given field. */
static unsigned
field_hash_function (hash_table_entry_t node_field)
{
IR_node_t node = (IR_node_t) node_field;
assert (node != NULL && IR_NODE_MODE (node) == IR_NM_field);
return (string_hash_value (IR_identifier_itself (IR_field_identifier
(node))));
}
/* The following function tests fields on equality of their keys. The
function is used by abstract data `hash table'. The function
returns 1 if the fields have the same key, 0 otherwise. */
static int
field_eq_function (hash_table_entry_t node_field_1,
hash_table_entry_t node_field_2)
{
IR_node_t node_1 = (IR_node_t) node_field_1;
IR_node_t node_2 = (IR_node_t) node_field_2;
assert (node_1 != NULL && IR_NODE_MODE (node_1) == IR_NM_field
&& node_2 != NULL && IR_NODE_MODE (node_2) == IR_NM_field);
return (string_equality (IR_identifier_itself (IR_field_identifier (node_1)),
IR_identifier_itself (IR_field_identifier
(node_2))));
}
/* The field table itself is represented by the following variable. */
static hash_table_t field_table;
/* The following function inserts field into the table. The function
does nothing if an field with the same key exists already in the
table. The function returns node in the table with the same key as
node representing given field. */
IR_node_t
insert_field (IR_node_t node_field)
{
hash_table_entry_t *entry_ptr;
entry_ptr = find_hash_table_entry (field_table, node_field, TRUE);
if (*entry_ptr == NULL)
*entry_ptr = (hash_table_entry_t) node_field;
return (IR_node_t) *entry_ptr;
}
/* The following variable value is node representing field. The node
used for searching field with given identifier. */
static IR_node_t work_field;
/* The following function searches for field in the table with the
same key as node representing identifier of the field. The
function returns node found in the table, NULL if such node does
not exist in the table. */
IR_node_t
find_field (IR_node_t field_identifier)
{
hash_table_entry_t *entry_ptr;
IR_set_field_identifier (work_field, field_identifier);
entry_ptr = find_hash_table_entry (field_table, work_field, FALSE);
return (IR_node_t) *entry_ptr;
}
/* The following function creates empty field table and node
representing field and used for searching field with given
identifier. The function must be called only once before any work
with the field table. */
void
initiate_field_table (void)
{
work_field = IR_create_node (IR_NM_field);
field_table = create_hash_table (500, field_hash_function,
field_eq_function);
}
/* The following function deletes given field table. Only call of
function `initiate_field_table' is possible immediately after this
function call. */
void
finish_field_table (void)
{
delete_hash_table (field_table);
}
/* This page contains abstract data `table of node fields'. Elements of the
table is nodes representing fields. Key of the table elements is
identifier strings of nodes representing identifier of the field and
identifier of corresponding node type of the field. */
/* The following function evaluates hash value of a node field. The
function is used by abstract data `hash table'. The function
returns hash value (0..UINT_MAX) of given field of some node
type. */
static unsigned
node_field_hash_function (hash_table_entry_t node_field)
{
IR_node_t node = (IR_node_t) node_field;
assert (node != NULL && IR_NODE_MODE (node) == IR_NM_field);
return (string_hash_value (IR_identifier_itself (IR_field_identifier (node)))
^
string_hash_value (IR_identifier_itself (IR_type_identifier
(IR_node_type (node)))));
}
/* The following function tests fields of some node type on equality
of their keys. The function is used by abstract data `hash table'.
The function returns 1 if the fields of some node type have the
same key, 0 otherwise. */
static int
node_field_eq_function (hash_table_entry_t node_field_1,
hash_table_entry_t node_field_2)
{
IR_node_t node_1 = (IR_node_t) node_field_1;
IR_node_t node_2 = (IR_node_t) node_field_2;
assert (node_1 != NULL && IR_NODE_MODE (node_1) == IR_NM_field
&& node_2 != NULL && IR_NODE_MODE (node_2) == IR_NM_field);
return (string_equality (IR_identifier_itself (IR_field_identifier (node_1)),
IR_identifier_itself (IR_field_identifier (node_2)))
&&
string_equality (IR_identifier_itself (IR_type_identifier
(IR_node_type (node_1))),
IR_identifier_itself (IR_type_identifier
(IR_node_type (node_2)))));
}
/* The node field table itself is represented by the following variable. */
static hash_table_t node_field_table;
/* The following function inserts field of some node type into the
table. The function does nothing if an node field with the same
key exists already in the table. The function returns node in the
table with the same key as node representing given field of some
node type. */
IR_node_t
insert_node_field (IR_node_t node_field)
{
hash_table_entry_t *entry_ptr;
entry_ptr = find_hash_table_entry (node_field_table, node_field, TRUE);
if (*entry_ptr == NULL)
*entry_ptr = (hash_table_entry_t) node_field;
return (IR_node_t) *entry_ptr;
}
/* The following variable value is node representing field of some node type.
The node used for searching field with given identifier in given node
type. */
static IR_node_t work_node_field;
/* The following function searches for field of some node type in the
table with the same key as nodes representing identifier of the
field and corresponding node type. The function returns node found
in the table, NULL if such node does not exist in the table. */
IR_node_t
find_node_field (IR_node_t field_identifier, IR_node_t node_type)
{
hash_table_entry_t *entry_ptr;
IR_set_field_identifier (work_node_field, field_identifier);
IR_set_node_type (work_node_field, node_type);
entry_ptr = find_hash_table_entry (node_field_table, work_node_field, FALSE);
return (IR_node_t) *entry_ptr;
}
/* The following function creates empty node field table and node
representing field of some node type and used for searching field
with given identifier in given node type. The function must be
called only once before any work with the node field table. */
void
initiate_node_field_table (void)
{
work_node_field = IR_create_node (IR_NM_field);
node_field_table = create_hash_table (500, node_field_hash_function,
node_field_eq_function);
}
/* The following function deletes given node field table. Only call
of function `initiate_node_field_table' is possible immediately
after this function call. */
void
finish_node_field_table (void)
{
delete_hash_table (node_field_table);
}