-
Notifications
You must be signed in to change notification settings - Fork 131
Expand file tree
/
Copy pathordered_attrs.cc
More file actions
97 lines (88 loc) · 3.2 KB
/
ordered_attrs.cc
File metadata and controls
97 lines (88 loc) · 3.2 KB
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
/// \file ordered_attrs.cc - create a list of attributes in the proper order for part 21, taking into account derivation, diamond inheritance, and (TODO) redefinition
#include <vector>
#include <cassert>
#include <cstring>
#include "ordered_attrs.h"
#ifdef _WIN32
# define strcasecmp _stricmp
#endif
Entity currentEntity = 0;
oaList attrs;
unsigned int attrIndex = 0;
/// uses depth-first recursion to add attrs in order; looks for derived attrs
void populateAttrList( oaList & list, Entity ent ) {
unsigned int attrCount = list.size(); //use to figure out how many attrs on end of list need to be checked for duplicates
//recurse through supertypes
LISTdo( ent->u.entity->supertypes, super, Entity ) {
populateAttrList( list, super );
} LISTod
//then look at ent's own attrs, checking against attrs with index >= attrCount
//derivation check only - leave deduplication for later
LISTdo( ent->u.entity->attributes, attr, Variable ) {
bool unique = true;
for( unsigned int i = attrCount; i < list.size(); i++ ) {
if( 0 == strcasecmp( attr->name->symbol.name, list[i]->attr->name->symbol.name ) ) {
// an attr by this name exists in a supertype
// originally printed a warning here, but that was misleading - they have more uses than I thought
unique = false;
list[i]->deriver = ent;
break;
}
}
if( unique ) {
orderedAttr * oa = new orderedAttr;
oa->attr=attr;
oa->creator=ent;
if( attr->initializer ) {
// attrs derived by their owner are omitted from part 21 - section 10.2.3
oa->deriver = ent;
} else {
oa->deriver = 0;
}
oa->redefiner = 0;
list.push_back( oa );
}
} LISTod
}
///compare attr name and creator, remove all but first occurrence
///this is necessary for diamond inheritance
void dedupList( oaList & list ) {
oaList::iterator it, jt;
for( it = list.begin(); it != list.end(); it++ ) {
for( jt = it + 1; jt != list.end(); jt++ ) {
if( ( 0 == strcasecmp( ( * it )->attr->name->symbol.name, ( * jt )->attr->name->symbol.name ) ) &&
( 0 == strcasecmp( ( * it )->creator->symbol.name, ( * jt )->creator->symbol.name ) ) ) {
//fprintf( stderr, "erasing %s created by %s\n", ( * jt )->attr->name->symbol.name, ( * jt )->creator->symbol.name );
jt--;
list.erase( jt + 1 );
}
}
}
}
/// set up ordered attrs for new entity
void orderedAttrsInit( Entity e ) {
orderedAttrsCleanup();
attrIndex = 0;
currentEntity = e;
if( currentEntity ) {
populateAttrList( attrs, currentEntity );
if( attrs.size() > 1 ) {
dedupList( attrs );
}
}
}
void orderedAttrsCleanup() {
for( unsigned int i = 0; i < attrs.size(); i++ ) {
delete attrs[i];
}
attrs.clear();
}
const orderedAttr * nextAttr() {
if( attrIndex < attrs.size() ) {
unsigned int i = attrIndex;
attrIndex++;
return attrs.at( i );
} else {
return 0;
}
}