-
Notifications
You must be signed in to change notification settings - Fork 131
Expand file tree
/
Copy pathscl2html.cc
More file actions
330 lines (284 loc) · 12.8 KB
/
scl2html.cc
File metadata and controls
330 lines (284 loc) · 12.8 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
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
/*
* scl2html.cc
*
* Ian Soboroff, NIST
* June, 1994
*
* scl2html is a program to lay out a given schema in HTML, suitable for
* hypertext browsing using Mosaic or any other HTML viewer/WWW surfboard.
* While this particular code as designed is linked to the Example schema
* (via tests.h), it can be "fed" any exp2cxx-compiled schema and give
* appropriate output.
*
* The Makefile defaults to building the app to use the example schema. To
* link to another schema, build the appropriate libraries for it and
* 'make SCHEMA_NAME=my-schema'. See the Makefile for more details.
*
* The executable is named after the schema you use, e.g., scl2html.example.
* This can be renamed to whatever you want.
*
* This program works by using the registry to walk through each entity type.
* At each entity, the supertypes, subtypes, and attributes are probed out
* and mapped into a relatively nifty-looking HTML format.
*
* This code was heavily inspired by the original scltest program,
* distributed with the DataProbe, v2.0.x.
*/
/* Since scl2html doesn't use any schema-specific things except the init
function, we don't need to include the schema's header file inside
tests.h */
#define DONT_NEED_HEADER
#include "../tests.h"
/* STEPentity* Iterator class definition */
#include "../SEarritr.h"
// PrintAttrTypeWithAnchor()
// Given an attribute, print out its immediate type (not fundamental).
// Ah, but if life were so simple. If this attribute is _not_ of a
// fundamental type, put in an anchor to somewhere with info on the type.
// This could be either the index page Type list, or an entity's page if
// the attribute is an entity.
// BUGS: (sort of) IMHO, the handling of aggregates here is a kludge, but
// it's a kludge without a solution I can see. While the dictionary has
// ways to show you what kinds of things an aggregate holds, it won't tell
// you what kind of _aggragation_ (no pun intended) you have, as in giving
// you a code or "Bag" or something by itself. It probably doesn't work
// aesthetically for compound aggregates (i.e., a list of lists).
void PrintAttrTypeWithAnchor( const TypeDescriptor * typeDesc, ofstream & outhtml ) {
std::string buf;
// The type. See clstepcore/baseType.h for info
PrimitiveType base = typeDesc->Type();
// the type descriptor for the "referent type," if any.
// This is NULL if the attribute is a fundamental type.
// All we use it for now is checking for NULL.
const TypeDescriptor * reference = typeDesc->ReferentType();
// Do we need an anchor?
int anchor = 0;
// First, figure out if we need an anchor...
if( reference ) { // if this has a referent type (i.e., is a non-base type)
if( base != sdaiAGGR ) { // anchor all non-bases except for aggregates
anchor = 1; // which we'll take care of recursively
}
} else {
// entities and enumerations show up as base, but we want to
// anchor them anyway
if( base == sdaiENUMERATION || base == sdaiINSTANCE ) {
anchor = 1;
}
}
// Now, print type, with anchor if necessary
if( anchor && base != sdaiINSTANCE ) {
// for regular TYPEs, anchor to the index at that definition
outhtml << "<A HREF=\"" << "index.html#";
outhtml << typeDesc->Name() << "\">";
} else if( anchor && base == sdaiINSTANCE ) {
// for entities, anchor to that entity's page
outhtml << "<A HREF=\"" << typeDesc->Name();
outhtml << ".html\">";
}
typeDesc->AttrTypeName( buf );
outhtml << buf;
if( base == sdaiAGGR ) {
outhtml << " (contains elements of type ";
PrintAttrTypeWithAnchor( typeDesc->AggrElemTypeDescriptor(), outhtml );
outhtml << ")" << endl;
}
if( anchor ) {
outhtml << "</A>";
}
}
// PrintAttrsHTML()
// Given an entity, print out to the HTML file an unordered list of
// the entity's attributes and their types. It returns the number of
// explicit attributes that the entity has.
int PrintAttrsHTML( const EntityDescriptor * ent, ofstream & outhtml ) {
int attrCount = 0;
// To traverse the attributes of the entity, we're going to use
// an iterator native to the class library. This could also have
// been done using GetHead() and NextNode() of the entity's attribute
// list (nearly identical to how the entity lists are traversed), see
// PrintParentAttrsHTML() and also main() below.
AttrDescItr aditr( ent->ExplicitAttr() );
const AttrDescriptor * attrDesc = aditr.NextAttrDesc();
if( attrDesc != 0 ) {
outhtml << "\n<! -- These are the attributes for entity ";
outhtml << ent->Name() << " >\n\n";
outhtml << "<UL>" << endl;
while( attrDesc != 0 ) {
attrCount++;
outhtml << "<LI>" << attrDesc->Name() << " : ";
if( ( attrDesc->Optional() ) == SDAI_LOGICAL( LTrue ) ) {
outhtml << "optional ";
}
PrintAttrTypeWithAnchor( attrDesc->ReferentType(), outhtml );
outhtml << endl;
attrDesc = aditr.NextAttrDesc();
}
outhtml << "</UL>" << endl;
}
return attrCount;
}
// PrintParentAttrsHTML()
// This function, given an entity and its parent, recursively travels up
// the inheritance tree of the entity, printing to the HTML file a
// description-list structure showing all ancestors. For each ancestor,
// the attributes are printed using the PrintAttrsHTML() function above.
void PrintParentAttrsHTML( const EntityDescriptor * ent,
const EntityDescriptor * parent, ofstream & outhtml ) {
// Passing this function the pointer to ent is really cosmetic, so
// we can easily print out this 'header' information.
outhtml << "\n<! -- This is a parent of " << ent->Name() << ">\n\n";
outhtml << "<DL>" << endl;
outhtml << "<DT>" << ent->Name() << " inherits from ";
outhtml << "<A HREF=\"" << parent->Name() << ".html\">";
outhtml << parent->Name() << "</A>" << endl;
// Here we're going to traverse the list of supertypes of the parent
// using the EntityDescriptorList
const EntityDescriptorList * grandpaList = &( parent->Supertypes() );
EntityDescLinkNode * grandpaNode =
( EntityDescLinkNode * )grandpaList->GetHead();
while( grandpaNode ) {
// for each "grandparent" of ent, inside a descriptor body (<DD>)
// recursively call this function... the 'while' takes care of
// multiple inheritance: for each grandparent, trace back.
outhtml << "<DD>" << endl;
const EntityDescriptor * grandpa = grandpaNode->EntityDesc();
PrintParentAttrsHTML( parent, grandpa, outhtml );
grandpaNode = ( EntityDescLinkNode * )grandpaNode->NextNode();
}
// Now print the parent's attributes. This calls PrintAttrsHTML() to
// actually print any existing attributes, but to see if there are
// any, we'll check to see if the head of the attribute descriptor list
// exists. Conversely, once grabbing the head we could print out
// the attributes by following the list (attrNode->NextNode()).
const AttrDescriptorList * attrList = &( parent->ExplicitAttr() );
AttrDescLinkNode * attrNode = ( AttrDescLinkNode * )attrList->GetHead();
if( attrNode ) {
outhtml << "<DT>" << parent->Name();
outhtml << " has the following attributes" << endl;
outhtml << "<DD>" << endl;
if( PrintAttrsHTML( parent, outhtml ) == 0 ) {
outhtml << "<EM>none</EM>" << endl;
}
}
outhtml << "</DL>" << endl;
}
/******************** main() ****************************/
main() {
// This has to be done before anything else. This initializes
// all of the registry information for the schema you are using.
// The SchemaInit() function is generated by exp2cxx... see
// extern statement above.
Registry * registry = new Registry( SchemaInit );
// Rather than using the standard Registry class here, as in the treg
// example, we are using MyRegistry, which is derived from the original.
// Registry doesn`t contain a facility for browsing the types, as it
// does schemas and entities... so I added it. See the file
// MyRegistry.h for details on how this was done.
// "Reset" has tables for browsing
registry->ResetEntities();
registry->ResetSchemas();
registry->ResetTypes();
const SchemaDescriptor * schema = registry->NextSchema();
int num_ents = registry->GetEntityCnt();
cout << "Processing schema " << schema->Name();
cout << " with " << num_ents << " entities." << endl;
// Set up root-level index of the schema, in a file called
// "index.html". In this document are links to all objects in
// the schema.
cout << "Creating 'index.html'" << endl;
ofstream root( "index.html" );
root << "<TITLE>" << schema->Name() << "</TITLE>" << endl;
root << "<H1>Schema: " << schema->Name() << "</H1>" << endl;
// Do Type-list
cout << "Processing types ";
root << "<HR>" << endl;
root << "<H2>Types</H2>" << endl;
root << "<UL>" << endl;
const TypeDescriptor * type;
type = registry->NextType();
root << "<! -- The following is a list of types, which are>\n";
root << "<! -- cross-referenced from the entities.>\n";
while( type != 0 ) {
cout << ".";
root << "<LI><A NAME=\"" << type->Name() << "\">";
root << type->Name() << "</A>: ";
root << type->Description() << endl;
type = registry->NextType();
}
root << "</UL>" << endl;
cout << endl;
// Do entity root-section and pages
root << "<HR>" << endl;
root << "<H2>Entities</H2>" << endl;
root << "<UL>" << endl;
root << "<! -- These all lead to a page for each entity>\n";
// These are all pointers we need to wander around the registry
// information. We'll want to not only look at the current entity
// and its attributes, but also which entities are super- and subclasses
// of the current entity. Here, supers isn't really used beyond checking
// for ancestors, but we'll use subs to list subclasses and make links
// to them.
const EntityDescriptor * ent;
const EntityDescriptorList * supers;
const EntityDescriptorList * subs;
EntityDescLinkNode * entNode;
for( int i = 0; i < num_ents; i++ ) {
ent = registry->NextEntity();
cout << "Processing " << ent->Name() << endl;
// add anchor to root page
root << "<LI><A HREF=\"" << ent->Name() << ".html\">";
root << ent->Name() << "</A>" << endl;
// construct page for entity
char * tmpstr = new char[strlen( ent->Name() ) + 6];
ofstream entout( strcat( strcpy( tmpstr, ent->Name() ), ".html" ) );
delete [] tmpstr;
entout << "<TITLE>Entity " << ent->Name() << "</TITLE>" << endl;
entout << "<H1>" << ent->Name() << "</H1>" << endl;
// supertypes
entout << "<HR>\n<H2>Inherited Attributes</H2>" << endl;
entout << "<! -- Below is the direct ancestry (if any) of ";
entout << ent->Name() << ">\n";
supers = &( ent->Supertypes() );
entNode = ( EntityDescLinkNode * )supers->GetHead();
if( !entNode ) {
entout << "<EM>none</EM>" << endl;
}
while( entNode ) {
// call PrintParentAttrsHTML to explore the parents
// of the entity, for each parent.
const EntityDescriptor * parent = entNode->EntityDesc();
PrintParentAttrsHTML( ent, parent, entout );
entNode = ( EntityDescLinkNode * )entNode->NextNode();
}
// local attributes
entout << "<HR>\n<H2>Local Attributes</H2>" << endl;
if( PrintAttrsHTML( ent, entout ) == 0 ) {
entout << "<EM>none</EM>" << endl;
}
// subtypes
// We're going to traverse the subtypes by using the subtype list
// of the entity, a little more simply than in PrintParentAttrsHTML()
entout << "<HR>\n<H2>Subtypes</H2>" << endl;
entout << "<! -- The following entities inherit from this one>\n";
subs = &( ent->Subtypes() );
entNode = ( EntityDescLinkNode * )subs->GetHead();
if( entNode ) {
entout << "<UL>" << endl;
EntityDescriptor * child;
while( entNode ) {
child = entNode->EntityDesc();
entout << "<LI><A HREF=\"" << child->Name() << ".html\">";
entout << child->Name() << "</A>" << endl;
entNode = ( EntityDescLinkNode * )entNode->NextNode();
}
entout << "</UL>" << endl;
} else {
entout << "<EM>none</EM>" << endl;
}
entout << "<HR>" << endl;
entout << "Click <A HREF=\"index.html\">here</A> to ";
entout << "return to the index." << endl;
}
root << "</UL>" << endl;
cout << "Done!" << endl;
}