Statistics
| Branch: | Revision:

root / src / nedxml / dtdclassgen.pl @ 68da4f12

History | View | Annotate | Download (27.7 KB)

1 01873262 Georg Kunz
#
2
# generate classes from NED DTD
3
#
4
5
#
6
# NOTE: some REDHAT Perl versions are broken, and cannot recognize the \s,
7
# so this code had to be patched up!!!
8
#
9
# If you have a good perl version and want readable REs in here, do these
10
# replacements throughout:
11
#
12
# [ \t\n]   --> \s
13
# [^ \t\n]  --> [^\s]
14
#
15
$verbose=0;
16
17
$filename = $ARGV[0];
18
$filename =~ /./ || die "*** no file name given\n";
19
20
$buf="";
21
open(IN,$filename) || die "*** cannot open input file $filename";
22
while (<IN>) {
23
    s/\r$//; # cygwin/mingw perl does not do CR/LF translation
24
    $buf .= $_;
25
}
26
$buf =~ s/<!--.*?-->//sg;
27
28
close(IN);
29
30
$hfile = "nedelements.h";
31
$ccfile = "nedelements.cc";
32
$validatorhfile = "nedvalidator.h";
33
$validatorccfile = "nedvalidator.cc";
34
$dtdvalidatorbasehfile = "neddtdvalidatorbase.h";
35
$dtdvalidatorhfile = "neddtdvalidator.h";
36
$dtdvalidatorccfile = "neddtdvalidator.cc";
37
38
$copyright = '//==========================================================================
39
// Part of the OMNeT++/OMNEST Discrete Event Simulation System
40
//
41
// Generated from ned.dtd by dtdclassgen.pl
42
//
43
//==========================================================================
44
45
/*--------------------------------------------------------------*
46
  Copyright (C) 2002-2008 Andras Varga
47
48
  This file is distributed WITHOUT ANY WARRANTY. See the file
49
  `license\' for details on this and other legal matters.
50
*--------------------------------------------------------------*/
51
52
//
53
// THIS IS A GENERATED FILE, DO NOT EDIT!
54
//
55
56
';
57
58
$elements = ();
59
60
#
61
# Parse ELEMENTs in DTD
62
#
63
while ($buf =~ s/(<!ELEMENT[ \t\n]+([^ \t\n]+)[ \t\n]+(.*?)>)//s) {
64
    $decl = $1;
65
    $element = $2;
66
    push(@elements,$element);
67
68
    $elementsdef = $3;
69
    $elementsdef =~ s/[ \t\n]//g;
70
    $elementdef{$element} = $elementsdef;
71
    $elementsdef =~ s/[*+?,|()]/ /g;  # simplify it a bit...
72
    $elementsdef =~ s/[ \t\n]+/ /g;  # simplify it a bit...
73
    @children = ();
74
    @childmult = ();
75
    foreach $child (split(' ',$elementsdef)) {
76
        if ($child eq 'EMPTY') {next;}
77
        if ($child eq 'ANY') {next;}
78
        $mult = 1;
79
        if ($child =~ s/([*+?])$//) {
80
           $mult = $1;
81
        }
82
        push(@children,$child);
83
        push(@childmult,$mult);
84
    }
85
    $elementdecl{$element} = $decl;
86
    $children{$element} = [ @children ];
87
    $childmult{$element} = [ @childmult ];
88
89
    print "$element: $elementdef{$element}\n" if ($verbose);
90
91
}
92
93
#
94
# Parse ATTLISTs in DTD
95
#
96
while ($buf =~ s/(<!ATTLIST[ \t\n]+([^ \t\n]+)[ \t\n]+(.*?)>)//s) {
97
    $decl = $1;
98
    $element = $2;
99
    $attlist = $3."\n";
100
101
    @attnames = ();
102
    @atttypes = ();
103
    @attvals = ();
104
    while ($attlist =~ s/^([^\n]*)\n//s) {
105
        $line = $1;
106
        if ($line =~ /^[ \t\n]+$/) {
107
            next;
108
        }
109
        if ($line =~ /^[ \t\n]*([^ \t\n]+)[ \t\n]+([^ \t\n]+)[ \t\n]+([^ \t\n]+)[ \t\n]*$/) {
110
            push(@attnames,$1);
111
            push(@atttypes,$2);
112
            push(@attvals,$3);
113
        } elsif ($line ne '') {
114
            print STDERR "unrecognized line in DTD: '$line'\n";
115
        }
116
    }
117
118
    $attlistdecl{$element} = $decl;
119
    $att_names{$element} = [ @attnames ];
120
    $att_types{$element} = [ @atttypes ];
121
    $att_vals{$element} =  [ @attvals ];
122
}
123
124
125
#
126
# Create class names, enum names, variable names, etc.
127
#
128
foreach $element (@elements)
129
{
130
    @attnames = @{$att_names{$element}};
131
    @atttypes = @{$att_types{$element}};
132
    @attvals = @{$att_vals{$element}};
133
    @children = @{$children{$element}};
134
    @childmult = @{$childmult{$element}};
135
136
    $attcount = $#attnames+1;
137
    $childcount = $#children+1;
138
139
    # element class
140
    $elementclass = $element;
141
    $elementclass =~ s/-(.)/-uc($1)/eg;
142
    $elementclass =~ s/[^a-zA-Z0-9_]//g;
143
    $elementclass =~ s/(.)(.*)/uc($1).$2/e;
144
    $elementclass{$element} = $elementclass."Element";
145
    $shortelementclass{$element} = $elementclass;
146
147
    # enum name
148
    $enumname = 'NED_'.uc($element);
149
    $enumname =~ s/-/_/g;
150
    $enumname{$element} = $enumname;
151
152
    # children
153
    @childvars = ();
154
    for ($i=0; $i<$childcount; $i++)
155
    {
156
        $varname = @children[$i];
157
        $varname =~ s/-(.)/-uc($1)/eg;
158
        $varname =~ s/[^a-zA-Z0-9_]//g;
159
        $varname =~ s/(.)(.*)/uc($1).$2/e;
160
        push(@childvars,$varname);
161
    }
162
    $childvars{$element} = [ @childvars ];
163
164
    # attribute names, types
165
    @varnames = ();
166
    @ucvarnames = ();
167
    @argtypes = ();
168
    @enumnames = ();
169
    for ($i=0; $i<$attcount; $i++)
170
    {
171
        $varname = $attnames[$i];
172
        $varname =~ s/-(.)/-uc($1)/eg;
173
        $varname =~ s/[^a-zA-Z0-9_]//g;
174
        $varname =~ s/(.)(.*)/lc($1).$2/e;
175
176
        $ucvarname = $varname;
177
        $ucvarname =~ s/(.)(.*)/uc($1).$2/e;
178
179
        $enumname = "";
180
        if ($atttypes[$i] eq '(true|false)') {
181
           $argtype = "bool";
182
        }
183
        elsif ($atttypes[$i] =~ /^\(.*\)$/) {
184
           $argtype = "int";
185
           if ($atttypes[$i] eq '(input|output|inout)') {
186
              $enumname = "gatetype";
187
           }
188
           elsif ($atttypes[$i] eq '(double|int|string|bool|xml)') {
189
              $enumname = "partype";
190
           }
191
           elsif ($atttypes[$i] eq '(double|int|string|bool|spec)') {
192
              $enumname = "littype";
193
           }
194
           elsif ($atttypes[$i] eq '(l2r|r2l|bidir)') {
195
              $enumname = "arrowdir";
196
           }
197
           elsif ($atttypes[$i] eq '(i|o)') {
198
              $enumname = "subgate";
199
           }
200
201
           else {
202
              die "Error: unrecognized enum $atttypes[$i]\n";
203
           }
204
        }
205
        else {
206
           $argtype = "const char *";
207
        }
208
        push(@varnames,$varname);
209
        push(@ucvarnames,$ucvarname);
210
        push(@argtypes,$argtype);
211
        push(@enumnames,$enumname);
212
    }
213
214
    $att_varnames{$element} = [ @varnames ];
215
    $att_ucvarnames{$element} = [ @ucvarnames ];
216
    $att_argtypes{$element} = [ @argtypes ];
217
    $att_enumnames{$element} = [ @enumnames ];
218
}
219
220
#------------------------------------------------------------------------
221
#
222
# Data classes
223
#
224
225
open(H,">$hfile") || die "*** cannot open output file $hfile";
226
open(CC,">$ccfile") || die "*** cannot open output file $ccfile";
227
228
print H "$copyright\n";
229
print H "#ifndef __NEDELEMENTS_H\n";
230
print H "#define __NEDELEMENTS_H\n\n";
231
print H "#include \"nedelement.h\"\n\n";
232
print H "NAMESPACE_BEGIN\n\n";
233
234
print CC "$copyright\n";
235
print CC "#include <string.h>\n";
236
print CC "#include \"nederror.h\"\n";
237
print CC "#include \"nedexception.h\"\n";
238
print CC "#include \"$hfile\"\n\n";
239
print CC "NAMESPACE_BEGIN\n\n";
240
241
# forward declarations
242
foreach $element (@elements)
243
{
244
    print H "class $elementclass{$element};\n";
245
}
246
print H "\n\n";
247
248
# tag codes
249
print H "/**\n";
250
print H " * Tag codes\n";
251
print H " *\n";
252
print H " * \@ingroup Data\n";
253
print H " */\n";
254
print H "enum NEDElementCode {\n";
255
print H "    NED_NULL = 0,  // 0 is reserved\n";
256
foreach $element (@elements)
257
{
258
    print H "    $enumname{$element}";
259
    print H "," unless ($element eq $elements[$#elements]);
260
    print H "\n";
261
}
262
print H "};\n\n";
263
264
print H "// Note: zero *must* be a valid value for all enums, because that gets set in the ctor if there's not default\n";
265
print H "enum {NED_GATETYPE_NONE, NED_GATETYPE_INPUT, NED_GATETYPE_OUTPUT, NED_GATETYPE_INOUT};\n";
266
print H "enum {NED_ARROWDIR_R2L, NED_ARROWDIR_L2R, NED_ARROWDIR_BIDIR};\n";
267
print H "enum {NED_PARTYPE_NONE, NED_PARTYPE_DOUBLE, NED_PARTYPE_INT, NED_PARTYPE_STRING, NED_PARTYPE_BOOL, NED_PARTYPE_XML};\n";
268
print H "enum {NED_CONST_DOUBLE, NED_CONST_INT, NED_CONST_STRING, NED_CONST_BOOL, NED_CONST_SPEC};\n";
269
print H "enum {NED_SUBGATE_NONE, NED_SUBGATE_I, NED_SUBGATE_O};\n";
270
271
print H "\n";
272
273
print CC "static const char *gatetype_vals[] = {\"\", \"input\", \"output\", \"inout\"};\n";
274
print CC "static int gatetype_nums[] = {NED_GATETYPE_NONE, NED_GATETYPE_INPUT, NED_GATETYPE_OUTPUT, NED_GATETYPE_INOUT};\n";
275
print CC "static const int gatetype_n = 4;\n";
276
print CC "\n";
277
print CC "static const char *arrowdir_vals[] = {\"l2r\", \"r2l\", \"bidir\"};\n";
278
print CC "static int arrowdir_nums[] = {NED_ARROWDIR_L2R, NED_ARROWDIR_R2L, NED_ARROWDIR_BIDIR};\n";
279
print CC "static const int arrowdir_n = 3;\n";
280
print CC "\n";
281
print CC "static const char *partype_vals[] = {\"\", \"double\", \"int\", \"string\", \"bool\", \"xml\"};\n";
282
print CC "static int partype_nums[] = {NED_PARTYPE_NONE, NED_PARTYPE_DOUBLE, NED_PARTYPE_INT, NED_PARTYPE_STRING, NED_PARTYPE_BOOL, NED_PARTYPE_XML};\n";
283
print CC "static const int partype_n = 6;\n";
284
print CC "\n";
285
print CC "static const char *littype_vals[] = {\"double\", \"int\", \"string\", \"bool\", \"spec\"};\n";
286
print CC "static int littype_nums[] = {NED_CONST_DOUBLE, NED_CONST_INT, NED_CONST_STRING, NED_CONST_BOOL, NED_CONST_SPEC};\n";
287
print CC "static const int littype_n = 5;\n";
288
print CC "\n";
289
print CC "static const char *subgate_vals[] = {\"\", \"i\", \"o\"};\n";
290
print CC "static int subgate_nums[] = {NED_SUBGATE_NONE, NED_SUBGATE_I, NED_SUBGATE_O};\n";
291
print CC "static const int subgate_n = 3;\n";
292
print CC "\n";
293
294
295
foreach $element (@elements)
296
{
297
    $elementclass = $elementclass{$element};
298
    $shortelementclass = $shortelementclass{$element};
299
300
    @attnames = @{$att_names{$element}};
301
    @atttypes = @{$att_types{$element}};
302
    @attvals = @{$att_vals{$element}};
303
    @children = @{$children{$element}};
304
    @childmult = @{$childmult{$element}};
305
306
    @childvars = @{$childvars{$element}};
307
    @varnames = @{$att_varnames{$element}};
308
    @ucvarnames = @{$att_ucvarnames{$element}};
309
    @argtypes = @{$att_argtypes{$element}};
310
    @enumnames = @{$att_enumnames{$element}};
311
312
    $attcount = $#attnames+1;
313
    $childcount = $#children+1;
314
315
    $decl = $elementdecl{$element}."\n".$attlistdecl{$element}."\n";
316
    $decl =~ s/^/ * /mg;
317
    $decl =~ s/</\\</mg;
318
    $decl =~ s/>/\\>/mg;
319
    $decl =~ s/#/\\#/mg;
320
    $decl =~ s/ *$//mg;
321
322
    print H "/**\n";
323
    print H " * GENERATED CLASS. Represents the \\<$element\\> XML element in memory. DTD declaration:\n";
324
    print H " *\n";
325
    print H " * <pre>\n";
326
    print H $decl;
327
    print H " * </pre>\n";
328
    print H " *\n";
329
    print H " * \@ingroup Data\n";
330
    print H " */\n";
331
    print H "class NEDXML_API $elementclass : public NEDElement\n";
332
    print H "{\n";
333
    print H "  private:\n";
334
    for ($i=0; $i<$attcount; $i++)
335
    {
336
        $vartype = ($argtypes[$i] eq "const char *") ? "std::string" : $argtypes[$i];
337
        print H "    $vartype $varnames[$i];\n";
338
    }
339
    print H "  public:\n";
340
    print H "    /** \@name Constructors, destructor */\n";
341
    print H "    //\@{\n";
342
    print H "    $elementclass();\n";
343
    print H "    $elementclass(NEDElement *parent);\n";
344
    print H "    virtual ~$elementclass() {}\n";
345
    print H "    //\@}\n";
346
    print H "\n";
347
    print H "    /** \@name Redefined NEDElement methods, incl. generic access to attributes */\n";
348
    print H "    //\@{\n";
349
    print H "    virtual const char *getTagName() const {return \"$element\";}\n";
350
    print H "    virtual int getTagCode() const {return $enumname{$element};}\n";
351
    print H "    virtual int getNumAttributes() const;\n";
352
    print H "    virtual const char *getAttributeName(int k) const;\n";
353
    print H "    virtual const char *getAttribute(int k) const;\n";
354
    print H "    virtual const char *getAttribute(const char *name) const {return NEDElement::getAttribute(name);} // needed because of a C++ language quirk\n";
355
    print H "    virtual void setAttribute(int k, const char *val);\n";
356
    print H "    virtual void setAttribute(const char *name, const char *val) {NEDElement::setAttribute(name, val);} // ditto\n";
357
    print H "    virtual const char *getAttributeDefault(int k) const;\n";
358
    print H "    virtual $elementclass *dup() const;\n";
359
    print H "    //\@}\n";
360
361
    print H "\n";
362
    print H "    /** \@name Typed access to attributes, children and siblings */\n";
363
    print H "    //\@{\n";
364
    for ($i=0; $i<$attcount; $i++)
365
    {
366
        if ($argtypes[$i] eq "const char *") {
367
            print H "    $argtypes[$i] get$ucvarnames[$i]() const  {return $varnames[$i].c_str();}\n";
368
        } else {
369
            print H "    $argtypes[$i] get$ucvarnames[$i]() const  {return $varnames[$i];}\n";
370
        }
371
        if ($argtypes[$i] eq "int") {
372
            print H "    void set$ucvarnames[$i]($argtypes[$i] val);\n";
373
            print CC "void $elementclass\:\:set$ucvarnames[$i]($argtypes[$i] val)\n";
374
            print CC "{\n";
375
            print CC "    validateEnum(val, $enumnames[$i]_vals, $enumnames[$i]_nums, $enumnames[$i]_n);\n";
376
            print CC "    $varnames[$i] = val;\n";
377
            print CC "}\n\n";
378
        } else {
379
            print H "    void set$ucvarnames[$i]($argtypes[$i] val)  {$varnames[$i] = val;}\n";
380
        }
381
382
    }
383
384
    print H "\n";
385
    print H "    virtual $elementclass *getNext${shortelementclass}Sibling() const;\n";
386
    for ($i=0; $i<$childcount; $i++)
387
    {
388
        print H "    virtual $elementclass{$children[$i]} *getFirst$childvars[$i]Child() const;\n";
389
    }
390
    print H "    //\@}\n";
391
    print H "};\n\n";
392
393
    print CC "$elementclass\:\:$elementclass()\n";
394
    print CC "{\n";
395
    for ($i=0; $i<$attcount; $i++)
396
    {
397
        print CC "    $varnames[$i] = false;\n" if ($argtypes[$i] eq "bool");
398
        print CC "    $varnames[$i] = 0;\n" if ($argtypes[$i] eq "int");
399
    }
400
    print CC "    applyDefaults();\n";
401
    print CC "}\n\n";
402
403
    print CC "$elementclass\:\:$elementclass(NEDElement *parent) : NEDElement(parent)\n";
404
    print CC "{\n";
405
    for ($i=0; $i<$attcount; $i++)
406
    {
407
        print CC "    $varnames[$i] = false;\n" if ($argtypes[$i] eq "bool");
408
        print CC "    $varnames[$i] = 0;\n" if ($argtypes[$i] eq "int");
409
    }
410
    print CC "    applyDefaults();\n";
411
    print CC "}\n\n";
412
413
    print CC "int $elementclass\:\:getNumAttributes() const\n";
414
    print CC "{\n";
415
    print CC "    return $attcount;\n";
416
    print CC "}\n\n";
417
418
    print CC "const char *$elementclass\:\:getAttributeName(int k) const\n";
419
    print CC "{\n";
420
    print CC "    switch (k) {\n";
421
    for ($i=0; $i<$attcount; $i++)
422
    {
423
        print CC "        case $i: return \"$attnames[$i]\";\n";
424
    }
425
    print CC "        default: return 0;\n";
426
    print CC "    }\n";
427
    print CC "}\n\n";
428
429
    print CC "const char *$elementclass\:\:getAttribute(int k) const\n";
430
    print CC "{\n";
431
    print CC "    switch (k) {\n";
432
    for ($i=0; $i<$attcount; $i++)
433
    {
434
        if ($argtypes[$i] eq "const char *") {
435
            print CC "        case $i: return $varnames[$i].c_str();\n";
436
        }
437
        elsif ($argtypes[$i] eq "bool") {
438
            print CC "        case $i: return boolToString($varnames[$i]);\n";
439
        }
440
        elsif ($argtypes[$i] eq "int") {
441
            print CC "        case $i: return enumToString($varnames[$i], $enumnames[$i]_vals, $enumnames[$i]_nums, $enumnames[$i]_n);\n";
442
        }
443
    }
444
    print CC "        default: return 0;\n";
445
    print CC "    }\n";
446
    print CC "}\n\n";
447
448
    print CC "void $elementclass\:\:setAttribute(int k, const char *val)\n";
449
    print CC "{\n";
450
    print CC "    switch (k) {\n";
451
    for ($i=0; $i<$attcount; $i++)
452
    {
453
        if ($argtypes[$i] eq "const char *") {
454
            print CC "        case $i: $varnames[$i] = val; break;\n";
455
        }
456
        elsif ($argtypes[$i] eq "bool") {
457
            print CC "        case $i: $varnames[$i] = stringToBool(val); break;\n";
458
        }
459
        elsif ($argtypes[$i] eq "int") {
460
            print CC "        case $i: $varnames[$i] = stringToEnum(val, $enumnames[$i]_vals, $enumnames[$i]_nums, $enumnames[$i]_n); break;\n";
461
        }
462
    }
463
    print CC "        default: ;\n";
464
    print CC "    }\n";
465
    print CC "}\n\n";
466
467
    print CC "const char *$elementclass\:\:getAttributeDefault(int k) const\n";
468
    print CC "{\n";
469
    print CC "    switch (k) {\n";
470
    for ($i=0; $i<$attcount; $i++)
471
    {
472
        $attval = $attvals[$i];
473
        $attval =~ s/\&#10;/\\n/g;
474
        if ($attval eq "#IMPLIED") {
475
            print CC "        case $i: return \"\";\n";
476
        } elsif ($attval eq "#REQUIRED") {
477
            print CC "        case $i: return NULL;\n";
478
        } else {
479
            print CC "        case $i: return $attval;\n";
480
        }
481
    }
482
    print CC "        default: return 0;\n";
483
    print CC "    }\n";
484
    print CC "}\n\n";
485
486
    print CC "$elementclass *$elementclass\:\:dup() const\n";
487
    print CC "{\n";
488
    print CC "    $elementclass *element = new $elementclass();\n";
489
    for ($i=0; $i<$attcount; $i++)
490
    {
491
        print CC "    element->$varnames[$i] = this->$varnames[$i];\n"
492
    }
493
    print CC "    return element;\n";
494
    print CC "}\n\n";
495
496
    print CC "$elementclass *$elementclass\:\:getNext${shortelementclass}Sibling() const\n";
497
    print CC "{\n";
498
    print CC "    return ($elementclass *)getNextSiblingWithTag($enumname{$element});\n";
499
    print CC "}\n\n";
500
501
    for ($i=0; $i<$childcount; $i++)
502
    {
503
        $childclass = $elementclass{$children[$i]};
504
        print CC "$childclass *$elementclass\:\:getFirst$childvars[$i]Child() const\n";
505
        print CC "{\n";
506
        print CC "    return ($childclass *)getFirstChildWithTag($enumname{$children[$i]});\n";
507
        print CC "}\n\n";
508
    }
509
}
510
511
512
#-------------------------------------------------------------------------------------
513
#
514
# Factory class
515
#
516
print H "/**\n";
517
print H " * GENERATED CLASS. Factory for NEDElement subclasses.\n";
518
print H " *\n";
519
print H " * \@ingroup Data\n";
520
print H " */\n";
521
print H "class NEDXML_API NEDElementFactory\n";
522
print H "{\n";
523
print H "  private:\n";
524
print H "    static NEDElementFactory *f;\n";
525
print H "    // ctor is private, because only one instance is allowed\n";
526
print H "    NEDElementFactory() {}\n";
527
print H "  public:\n";
528
print H "    /** Destructor */\n";
529
print H "    virtual ~NEDElementFactory() {}\n";
530
print H "    /** Returns factory instance */\n";
531
print H "    static NEDElementFactory *getInstance();\n";
532
print H "    /** Creates NEDElement subclass which corresponds to tagname */\n";
533
print H "    virtual NEDElement *createElementWithTag(const char *tagname);\n";
534
print H "    /** Creates NEDElement subclass which corresponds to tagcode */\n";
535
print H "    virtual NEDElement *createElementWithTag(int tagcode);\n";
536
print H "};\n\nNAMESPACE_END\n\n";
537
print H "#endif\n\n";
538
539
print CC "NEDElementFactory *NEDElementFactory::f;\n\n";
540
print CC "NEDElementFactory *NEDElementFactory::getInstance()\n";
541
print CC "{\n";
542
print CC "    if (!f) f=new NEDElementFactory();\n";
543
print CC "    return f;\n";
544
print CC "}\n\n";
545
print CC "NEDElement *NEDElementFactory::createElementWithTag(const char *tagname)\n";
546
print CC "{\n";
547
foreach $element (@elements)
548
{
549
    $element =~ /^(.)/;
550
    $startletter = $1;
551
    print CC "    if (tagname[0]=='$startletter' && !strcmp(tagname,\"$element\"))  return new $elementclass{$element}();\n";
552
}
553
print CC "    throw NEDException(\"unknown tag '%s', cannot create object to represent it\", tagname);\n";
554
print CC "}\n\n";
555
print CC "NEDElement *NEDElementFactory::createElementWithTag(int tagcode)\n";
556
print CC "{\n";
557
print CC "    switch (tagcode) {\n";
558
foreach $element (@elements)
559
{
560
    $element =~ /^(.)/;
561
    $startletter = $1;
562
    print CC "        case $enumname{$element}: return new $elementclass{$element}();\n";
563
}
564
print CC "    }\n";
565
print CC "    throw NEDException(\"unknown tag code %d, cannot create object to represent it\", tagcode);\n";
566
print CC "}\n\nNAMESPACE_END\n\n";
567
568
569
#-------------------------------------------------------------------------------------
570
#
571
# Validator classes
572
#
573
open(VAL_H,">$validatorhfile") || die "*** cannot open output file $validatorhfile";
574
open(VAL_CC,">$validatorccfile") || die "*** cannot open output file $validatorccfile";
575
576
print VAL_H "$copyright\n";
577
print VAL_H "#ifndef __NEDVALIDATOR_H\n";
578
print VAL_H "#define __NEDVALIDATOR_H\n\n";
579
print VAL_H "#include \"nederror.h\"\n";
580
print VAL_H "#include \"nedexception.h\"\n";
581
print VAL_H "#include \"nedelements.h\"\n\n";
582
print VAL_H "NAMESPACE_BEGIN\n\n";
583
584
print VAL_CC "$copyright\n";
585
print VAL_CC "#include <stdio.h>\n";
586
print VAL_CC "#include \"nederror.h\"\n";
587
print VAL_CC "#include \"nedexception.h\"\n";
588
print VAL_CC "#include \"$validatorhfile\"\n\n";
589
print VAL_CC "NAMESPACE_BEGIN\n\n";
590
591
print VAL_H "/**\n";
592
print VAL_H " * GENERATED CLASS. Abtract base class for NED validators.\n";
593
print VAL_H " *\n";
594
print VAL_H " * \@ingroup Validation\n";
595
print VAL_H " */\n";
596
print VAL_H "class NEDXML_API NEDValidatorBase\n";
597
print VAL_H "{\n";
598
print VAL_H "  protected:\n";
599
print VAL_H "    NEDErrorStore *errors;\n";
600
print VAL_H "  public:\n";
601
print VAL_H "    /** \@name Constructor, destructor */\n";
602
print VAL_H "    //\@{\n";
603
print VAL_H "    NEDValidatorBase(NEDErrorStore *e) {errors = e;}\n";
604
print VAL_H "    virtual ~NEDValidatorBase() {}\n";
605
print VAL_H "    //\@}\n\n";
606
print VAL_H "    /** Validates the node recursively */\n";
607
print VAL_H "    virtual void validate(NEDElement *node);\n";
608
print VAL_H "    /** Dispatches to the corresponding overloaded validateElement() function */\n";
609
print VAL_H "    virtual void validateElement(NEDElement *node);\n";
610
print VAL_H "\n";
611
print VAL_H "  protected:\n";
612
print VAL_H "    /** \@name Validation functions, to be implemented in subclasses */\n";
613
print VAL_H "    //\@{\n";
614
foreach $element (@elements)
615
{
616
    print VAL_H "    virtual void validateElement($elementclass{$element} *node) = 0;\n";
617
}
618
print VAL_H "    //\@}\n";
619
print VAL_H "};\n\nNAMESPACE_END\n\n";
620
print VAL_H "#endif\n\n";
621
622
print VAL_CC "void  NEDValidatorBase::validate(NEDElement *node)\n";
623
print VAL_CC "{\n";
624
print VAL_CC "    validateElement(node);\n";
625
print VAL_CC "    for (NEDElement *child=node->getFirstChild(); child; child=child->getNextSibling())\n";
626
print VAL_CC "        validate(child);\n";
627
print VAL_CC "}\n\n";
628
629
print VAL_CC "void  NEDValidatorBase::validateElement(NEDElement *node)\n";
630
print VAL_CC "{\n";
631
print VAL_CC "    try {\n";
632
print VAL_CC "        switch (node->getTagCode()) {\n";
633
foreach $element (@elements)
634
{
635
    $element =~ /^(.)/;
636
    $startletter = $1;
637
    print VAL_CC "            case $enumname{$element}: validateElement(($elementclass{$element} *) node); break;\n";
638
}
639
print VAL_CC "            default: INTERNAL_ERROR1(node,\"validateElement(): unknown tag '%s'\", node->getTagName());\n";
640
print VAL_CC "        }\n";
641
print VAL_CC "    }\n";
642
print VAL_CC "    catch (NEDException& e)\n";
643
print VAL_CC "    {\n";
644
print VAL_CC "        INTERNAL_ERROR1(node,\"validateElement(): NEDException: %s\", e.what());\n";
645
print VAL_CC "    }\n";
646
print VAL_CC "}\n\nNAMESPACE_END\n\n";
647
648
649
#-------------------------------------------------------------------------------------
650
#
651
# DTD Validator classes
652
#
653
open(DTDVAL_H,">$dtdvalidatorhfile") || die "*** cannot open output file $dtdvalidatorhfile";
654
open(DTDVAL_CC,">$dtdvalidatorccfile") || die "*** cannot open output file $dtdvalidatorccfile";
655
656
print DTDVAL_H "$copyright\n";
657
print DTDVAL_H "#ifndef __DTDVALIDATOR_H\n";
658
print DTDVAL_H "#define __DTDVALIDATOR_H\n\n";
659
print DTDVAL_H "#include \"nedelements.h\"\n";
660
print DTDVAL_H "#include \"$dtdvalidatorbasehfile\"\n\n";
661
print DTDVAL_H "NAMESPACE_BEGIN\n\n";
662
663
print DTDVAL_CC "$copyright\n";
664
print DTDVAL_CC "#include <stdio.h>\n";
665
print DTDVAL_CC "#include \"nederror.h\"\n";
666
print DTDVAL_CC "#include \"$dtdvalidatorhfile\"\n\n";
667
print DTDVAL_CC "NAMESPACE_BEGIN\n\n";
668
669
print DTDVAL_H "/**\n";
670
print DTDVAL_H " * GENERATED CLASS. Validates a NEDElement tree by the DTD.\n";
671
print DTDVAL_H " *\n";
672
print DTDVAL_H " * \@ingroup Validation\n";
673
print DTDVAL_H " */\n";
674
print DTDVAL_H "class NEDXML_API NEDDTDValidator : public NEDDTDValidatorBase\n";
675
print DTDVAL_H "{\n";
676
print DTDVAL_H "  public:\n";
677
print DTDVAL_H "    NEDDTDValidator(NEDErrorStore *e) : NEDDTDValidatorBase(e) {}\n";
678
print DTDVAL_H "    virtual ~NEDDTDValidator() {}\n";
679
print DTDVAL_H "\n";
680
print DTDVAL_H "  protected:\n";
681
print DTDVAL_H "    /** \@name Validation functions */\n";
682
print DTDVAL_H "    //\@{\n";
683
foreach $element (@elements)
684
{
685
    print DTDVAL_H "    virtual void validateElement($elementclass{$element} *node);\n";
686
}
687
print DTDVAL_H "    //\@}\n";
688
print DTDVAL_H "};\n\nNAMESPACE_END\n\n";
689
print DTDVAL_H "#endif\n\n";
690
691
foreach $element (@elements)
692
{
693
    print DTDVAL_CC "void NEDDTDValidator\:\:validateElement($elementclass{$element} *node)\n";
694
    print DTDVAL_CC "{\n";
695
    if ($elementdef{$element} =~ /^\(([^|]*)\)$/) {  # in parens, does not contain "|"
696
       @a = split(',',$1);
697
       $tags='';
698
       $mult='';
699
       foreach $e (@a) {
700
          $e =~ /^(.*?)([*?+]?)$/;
701
          $tags .= $enumname{$1}.",";
702
          $mult .= "'".$2."'," if ($2 ne '');
703
          $mult .= "'1'," if ($2 eq '');
704
       }
705
       print DTDVAL_CC "    int tags[] = {$tags NED_NULL};\n";
706
       print DTDVAL_CC "    char mult[] = {$mult 0};\n";
707
       print DTDVAL_CC "    checkSequence(node, tags, mult);\n";
708
    }
709
    elsif ($elementdef{$element} =~ /^\(\(([^,]*)\)([*?+]?)\)$/) { # like ((a|b|c)*)
710
       @a = split('\|',$1);
711
       $mult = $2;
712
       if ($mult eq '') {$mult='1';}
713
       $tags='';
714
       foreach $e (@a) {
715
          $tags .= $enumname{$e}.",";
716
       }
717
       print DTDVAL_CC "    int tags[] = {$tags NED_NULL};\n";
718
       print DTDVAL_CC "    checkChoice(node, tags, \'$mult\');\n";
719
    }
720
    elsif ($elementdef{$element} =~ /^\((.*)\)$/) {  # fallback: in parens
721
       print DTDVAL_CC "    Choice choices[] = {\n";
722
       #print "DBG: parsing $1\n";
723
       @seqs = split(',',$1);
724
       foreach $seq (@seqs) {
725
          if ($seq =~ /^\((.*)\)([*?+]?$)/) {
726
              #print "DBG:   CHOICE=( $1 )  MUL=$2\n";
727
              @choicetags = split('\|',$1);
728
              $mul = $2;
729
              if ($mul eq '') {$mul = '1';}
730
731
              print DTDVAL_CC "        {{";
732
              foreach $choicetag (@choicetags) {
733
                  if (! $choicetag =~ /^[a-zA-Z0-9-_]+$/) {
734
                      die "Cannot parse element def for $element: $elementdef{$element}: $choicetag does not look like an element name\n";
735
                  }
736
                  print DTDVAL_CC $enumname{$choicetag}.", ";
737
              }
738
              print DTDVAL_CC "NED_NULL}, '$mul'},\n";
739
          }
740
          elsif ($seq =~ /^([a-zA-Z0-9-_]+)([*?+]?$)/) {
741
              #print "DBG:   NAME=$1  MUL=$2\n";
742
              $name = $1;
743
              $mul = $2;
744
              if ($mul eq '') {$mul = '1';}
745
              print DTDVAL_CC "        {{".$enumname{$name}.", NED_NULL}, '$mul'},\n";
746
          }
747
          else {
748
              die "Cannot parse $seq in element def for $element: $elementdef{$element}\n";
749
          }
750
       }
751
       print DTDVAL_CC "    };\n";
752
       print DTDVAL_CC "    checkSeqOfChoices(node, choices, sizeof(choices)/sizeof(Choice));\n";
753
    }
754
    elsif ($elementdef{$element} eq 'EMPTY') {
755
       print DTDVAL_CC "    checkEmpty(node);\n";
756
    }
757
    elsif ($elementdef{$element} eq 'ANY') {
758
       print DTDVAL_CC "    // ANY\n";
759
    }
760
    else {
761
       die "Cannot parse element def for $element: $elementdef{$element}\n";
762
    }
763
764
    @attnames = @{$att_names{$element}};
765
    @atttypes = @{$att_types{$element}};
766
    @attvals = @{$att_vals{$element}};
767
    $attcount = $#attnames+1;
768
769
    print DTDVAL_CC "\n";
770
771
    for ($i=0; $i<$attcount; $i++)
772
    {
773
        $attname = $attnames[$i];
774
        $attval = $attvals[$i];
775
        $atttype = $atttypes[$i];
776
777
        if ($attval eq "#REQUIRED") {
778
            print DTDVAL_CC "    checkRequiredAttribute(node, \"$attname\");\n";
779
        }
780
781
        if ($atttype =~ /^\((.*)\)$/) {
782
            @a = split('\|',$1);
783
            $vals='';
784
            foreach $e (@a) {
785
               $vals .= "\"".$e."\",";
786
            }
787
            $vals =~ s/,$//;
788
            if ($attval eq "#IMPLIED") {
789
               $vals .= ",\"\"";
790
            }
791
            print DTDVAL_CC "    const char *vals${i}[] = {$vals};\n";
792
            print DTDVAL_CC "    checkEnumeratedAttribute(node, \"$attname\", vals$i, sizeof(vals$i)/sizeof(const char *));\n";
793
        }
794
        elsif ($attname eq "comment" || $attname =~ /-comment$/) {
795
            print DTDVAL_CC "    checkCommentAttribute(node, \"$attname\");\n";
796
        }
797
        elsif ($atttype eq "NMTOKEN") {
798
            print DTDVAL_CC "    checkNameAttribute(node, \"$attname\");\n";
799
        }
800
    }
801
    print DTDVAL_CC "}\n\n";
802
}
803
804
print DTDVAL_CC "NAMESPACE_END\n\n";