1 /*
2 * main.cxx
3 *
4 * PWLib application source file for asnparser
5 *
6 * ASN.1 compiler to produce C++ classes.
7 *
8 * Copyright (c) 1997-1999 Equivalence Pty. Ltd.
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is ASN Parser.
21 *
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23 *
24 * Portions of this code were written with the assisance of funding from
25 * Vovida Networks, Inc. http://www.vovida.com.
26 *
27 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
28 * All Rights Reserved.
29 *
30 * Contributor(s): ______________________________________.
31 *
32 * $Revision: 20385 $
33 * $Author: rjongbloed $
34 * $Date: 2008-06-04 05:40:38 -0500 (Wed, 04 Jun 2008) $
35 */
36
37 #include <ptlib.h>
38
39 #include <ptlib/pprocess.h>
40
41 #include "main.h"
42 #include "asn_grammar.h"
43
44
45 #define MAJOR_VERSION 1
46 #define MINOR_VERSION 9
47 #define BUILD_TYPE ReleaseCode
48 #define BUILD_NUMBER 4
49
50
51 unsigned lineNumber;
52 PString fileName;
53
54 unsigned fatals, warnings;
55
56 extern FILE * yyin;
57 extern int yydebug;
58 extern int LexEcho;
59
60 ModuleDefinition * Module;
61
62
63 static const char * UniversalTagClassNames[] = {
64 "UniversalTagClass",
65 "ApplicationTagClass",
66 "ContextSpecificTagClass",
67 "PrivateTagClass"
68 };
69
70 static const char * UniversalTagNames[] = {
71 NULL,
72 "UniversalBoolean",
73 "UniversalInteger",
74 "UniversalBitString",
75 "UniversalOctetString",
76 "UniversalNull",
77 "UniversalObjectId",
78 "UniversalObjectDescriptor",
79 "UniversalExternalType",
80 "UniversalReal",
81 "UniversalEnumeration",
82 "UniversalEmbeddedPDV",
83 NULL,
84 NULL,
85 NULL,
86 NULL,
87 "UniversalSequence",
88 "UniversalSet",
89 "UniversalNumericString",
90 "UniversalPrintableString",
91 "UniversalTeletexString",
92 "UniversalVideotexString",
93 "UniversalIA5String",
94 "UniversalUTCTime",
95 "UniversalGeneralisedTime",
96 "UniversalGraphicString",
97 "UniversalVisibleString",
98 "UniversalGeneralString",
99 "UniversalUniversalString",
100 NULL,
101 "UniversalBMPString"
102 };
103
104
105 static const char * const StandardClasses[] = {
106 "PASN_Null",
107 "PASN_Boolean",
108 "PASN_Integer",
109 "PASN_Enumeration",
110 "PASN_Real",
111 "PASN_ObjectId",
112 "PASN_BitString",
113 "PASN_OctetString",
114 "PASN_NumericString",
115 "PASN_PrintableString",
116 "PASN_VisibleString",
117 "PASN_IA5String",
118 "PASN_GeneralString",
119 "PASN_BMPString",
120 "PASN_Sequence"
121 };
122
123
124 /////////////////////////////////////////
125 //
126 // yyerror
127 // required function for flex
128 //
129
yyerror(char * str)130 void yyerror(char * str)
131 {
132 extern char * yytext;
133 PError << StdError(Fatal) << str << " near token \"" << yytext <<"\"\n";
134 }
135
operator <<(ostream & out,const StdError & e)136 ostream & operator<<(ostream & out, const StdError & e)
137 {
138 out << fileName << '(' << lineNumber << ") : ";
139 if (e.e == Fatal) {
140 fatals++;
141 out << "error";
142 }
143 else {
144 warnings++;
145 out << "warning";
146 }
147 return out << ": ";
148 }
149
150
151 /////////////////////////////////////////////////////////
152 //
153 // Utility
154 //
155
MakeIdentifierC(const PString & identifier)156 static PString MakeIdentifierC(const PString & identifier)
157 {
158 PString s = identifier;
159 s.Replace("-", "_", TRUE);
160 return s;
161 }
162
163
164 class OutputFile : public PTextFile
165 {
166 PCLASSINFO(OutputFile, PTextFile);
167 public:
~OutputFile()168 ~OutputFile() { Close(); }
169
170 PBoolean Open(const PFilePath & path, const PString & suffix, const char * extension);
171 PBoolean Close();
172 };
173
174
Open(const PFilePath & path,const PString & suffix,const char * extension)175 PBoolean OutputFile::Open(const PFilePath & path,
176 const PString & suffix,
177 const char * extension)
178 {
179 PFilePath fn = path.GetDirectory() + path.GetTitle() + suffix;
180 fn.SetType(extension);
181
182 if (PTextFile::Open(fn, WriteOnly))
183 *this << "//\n"
184 "// " << GetFilePath().GetFileName() << "\n"
185 "//\n"
186 "// Code automatically generated by asnparse.\n"
187 "//\n"
188 "\n";
189 else
190 PError << PProcess::Current().GetName() << ": cannot create \""
191 << GetFilePath() << "\" :" << GetErrorText() << endl;
192
193 return IsOpen();
194 }
195
196
Close()197 PBoolean OutputFile::Close()
198 {
199 if (IsOpen())
200 *this << "\n"
201 "// End of " << GetFilePath().GetFileName() << '\n';
202
203 return PTextFile::Close();
204 }
205
206
207 /////////////////////////////////////////////////////////
208 //
209 // Application
210 //
211
212 class App : public PProcess
213 {
214 PCLASSINFO(App, PProcess);
215 public:
216 App();
217 void Main();
218 PBoolean SetClassHeaderFile(PArgList & args);
219 PBoolean SetClassHeader(PArgList & args);
220 void OutputAdditionalHeaders(ostream & hdr, const PString & className);
221 protected:
222 PStringToString classToHeader;
223 };
224
225 PCREATE_PROCESS(App);
226
App()227 App::App()
228 : PProcess("Equivalence", "ASNParse", MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
229 {
230 }
231
Main()232 void App::Main()
233 {
234 cout << GetName() << " version " << GetVersion(TRUE)
235 << " for " << GetOSClass() << ' ' << GetOSName()
236 << " by " << GetManufacturer() << endl;
237
238 PArgList & args = GetArguments();
239 args.Parse("c-c++."
240 "d-debug."
241 "e-echo."
242 "h-hdr-prefix:"
243 "i-inlines."
244 "m-module:"
245 "n-namespace."
246 "o-output:"
247 "r-rename:"
248 "s-split;"
249 "V-version."
250 "v-verbose."
251 "x-xml."
252 "-no-operators."
253 "-classheader:"
254 "-classheaderfile:");
255
256 if (args.HasOption('V'))
257 return;
258
259 unsigned numFiles = 1;
260 if (args.HasOption('s')) {
261 PString numFilesStr = args.GetOptionString('s');
262 if (numFilesStr.IsEmpty())
263 numFiles = 2;
264 else
265 numFiles = numFilesStr.AsUnsigned();
266 }
267
268 if (args.GetCount() < 1 || args.GetCount() > 1 || numFiles == 0) {
269 PError << "usage: asnparse [options] asnfile\n"
270 " -V --version Display version and exit\n"
271 " -v --verbose Verbose output (multiple times for more verbose)\n"
272 " -e --echo Echo input file\n"
273 " -d --debug Debug output (copious!)\n"
274 " -c --c++ Generate C++ files\n"
275 " -n --namespace Use C++ namespace\n"
276 " -h --hdr-prefix str Prefix for C++ include of header (eg directory)\n"
277 " -i --inlines Use C++ inlines\n"
278 " -s[n] --split[n] Split output into n (default 2) files\n"
279 " -m --module name Module name prefix/namespace\n"
280 " -r --rename args Rename import module where arg is:\n"
281 " from=name[,prefix[,fname]]\n"
282 " from is module name in ASN file\n"
283 " name is target header file name\n"
284 " prefix is optional prefix for include\n"
285 " (eg header directory)\n"
286 " fname is optional base name for header files\n"
287 " --no-operators Generate functions instead of operators for choice\n"
288 " sub-object extraction.\n"
289 " -x --xml X.693 support (XER)\n"
290 " -o --output file Output filename/directory\n"
291 << endl;
292 return;
293 }
294
295 PTextFile prcFile;
296 if (!prcFile.Open(args[0], PFile::ReadOnly)) {
297 PError << GetName() << ": cannot open \""
298 << prcFile.GetFilePath() << "\" :" << prcFile.GetErrorText() << endl;
299 return;
300 }
301
302 if (args.HasOption('d'))
303 yydebug = 1;
304 if (args.HasOption('e'))
305 LexEcho = TRUE;
306
307 fileName = prcFile.GetFilePath();
308 lineNumber = 1;
309 fatals = 0;
310 warnings = 0;
311
312 if (args.HasOption("classheaderfile")) {
313 if (!SetClassHeaderFile(args))
314 return;
315 }
316
317 if (args.HasOption("classheader")) {
318 if (!SetClassHeader(args))
319 return;
320 }
321
322 if (args.HasOption('v'))
323 cout << "Parsing..." << endl;
324
325 yyin = _fdopen(prcFile.GetHandle(), "r");
326 PAssert(yyin != NULL, "fdopen failed!");
327 yyparse();
328
329 if (Module != NULL) {
330 if (args.GetOptionCount('v') > 1)
331 PError << "Module " << *Module << endl;
332
333 if (args.HasOption('c'))
334 Module->GenerateCplusplus(args.GetOptionString('o', args[0]),
335 args.GetOptionString('m'),
336 args.GetOptionString('h'),
337 numFiles,
338 args.HasOption('n'),
339 args.HasOption('i'),
340 !args.HasOption("no-operators"),
341 args.HasOption('v'));
342 }
343 }
344
345
SetClassHeaderFile(PArgList & args)346 PBoolean App::SetClassHeaderFile(PArgList & args)
347 {
348 PStringArray lines = args.GetOptionString("classheaderfile").Lines();
349 if (lines.IsEmpty()) {
350 PError << GetName() << ": malformed --classheaderfile option\n";
351 return FALSE;
352 }
353
354 for (PINDEX i = 0; i < lines.GetSize(); i++) {
355 PString str = lines[i];
356 PINDEX pos = str.Find("=");
357 if (pos == P_MAX_INDEX) {
358 PError << GetName() << ": malformed --classheaderfile option\n";
359 return FALSE;
360 }
361
362 PFilePath fn = str.Right(pos+1);
363 PTextFile file(fn, PFile::ReadOnly);
364 if (!file.IsOpen()) {
365 PError << GetName() << ": cannot open file required for --classheaderfile option \"" << fn
366 << "\" :" << file.GetErrorText() << '\n';
367 return FALSE;
368 }
369
370 PString text;
371 PString line;
372 while (file.ReadLine(line))
373 text += PString(PString::Literal, (const char *)line) + '\n';
374 classToHeader.SetAt(str.Left(pos), text);
375 }
376
377 return TRUE;
378 }
379
380
SetClassHeader(PArgList & args)381 PBoolean App::SetClassHeader(PArgList & args)
382 {
383 PStringArray lines = args.GetOptionString("classheader").Lines();
384 if (lines.IsEmpty()) {
385 PError << GetName() << ": malformed --classheader option\n";
386 return FALSE;
387 }
388
389 for (PINDEX i = 0; i < lines.GetSize(); i++) {
390 PString str = lines[i];
391 PINDEX pos = str.Find("=");
392 if (pos == P_MAX_INDEX) {
393 PError << GetName() << ": malformed --classheader option\n";
394 return FALSE;
395 }
396
397 PString text(PString::Literal, (const char *)str.Mid(pos+1));
398 classToHeader.SetAt(str.Left(pos), text);
399 }
400
401 return TRUE;
402 }
403
404
OutputAdditionalHeaders(ostream & hdr,const PString & className)405 void App::OutputAdditionalHeaders(ostream & hdr, const PString & className)
406 {
407 if (classToHeader.Contains(className)) {
408 hdr << "// following code added by command line option\n"
409 "\n"
410 << classToHeader[className] << "\n"
411 "\n"
412 "// end of added code\n"
413 "\n";
414 }
415 }
416
417 /////////////////////////////////////////
418 //
419 // miscellaneous
420 //
421
422 class indent
423 {
424 public:
indent()425 indent() { }
operator <<(ostream & s,const indent &)426 friend ostream & operator<<(ostream & s, const indent &)
427 { return s << setw(Module->GetIndentLevel()*3) << ' '; }
428 };
429
430
431 /////////////////////////////////////////
432 //
433 // intermediate structures from parser
434 //
435
NamedNumber(PString * nam)436 NamedNumber::NamedNumber(PString * nam)
437 : name(*nam)
438 {
439 delete nam;
440 number = 0;
441 autonumber = TRUE;
442 }
443
444
NamedNumber(PString * nam,int num)445 NamedNumber::NamedNumber(PString * nam, int num)
446 : name(*nam)
447 {
448 delete nam;
449 number = num;
450 autonumber = FALSE;
451 }
452
453
NamedNumber(PString * nam,const PString & ref)454 NamedNumber::NamedNumber(PString * nam, const PString & ref)
455 : name(*nam), reference(ref)
456 {
457 delete nam;
458 number = 0;
459 autonumber = FALSE;
460 }
461
462
PrintOn(ostream & strm) const463 void NamedNumber::PrintOn(ostream & strm) const
464 {
465 strm << name << " (";
466 if (reference.IsEmpty())
467 strm << number;
468 else
469 strm << reference;
470 strm << ')';
471 }
472
473
SetAutoNumber(const NamedNumber & prev)474 void NamedNumber::SetAutoNumber(const NamedNumber & prev)
475 {
476 if (autonumber) {
477 number = prev.number + 1;
478 autonumber = FALSE;
479 }
480 }
481
482
483 /////////////////////////////////////////////////////////
484
Tag(unsigned tagNum)485 Tag::Tag(unsigned tagNum)
486 {
487 type = Universal;
488 number = tagNum;
489 mode = Module->GetDefaultTagMode();
490 }
491
492
493 const char * Tag::classNames[] = {
494 "UNIVERSAL", "APPLICATION", "CONTEXTSPECIFIC", "PRIVATE"
495 };
496
497
498 const char * Tag::modeNames[] = {
499 "IMPLICIT", "EXPLICIT", "AUTOMATIC"
500 };
501
502
PrintOn(ostream & strm) const503 void Tag::PrintOn(ostream & strm) const
504 {
505 if (type != Universal || number != IllegalUniversalTag) {
506 strm << '[';
507 if (type != ContextSpecific)
508 strm << classNames[type] << ' ';
509 strm << number << "] " << modeNames[mode] << ' ';
510 }
511 }
512
513
514 /////////////////////////////////////////////////////////
515
Constraint(ConstraintElementBase * elmt)516 Constraint::Constraint(ConstraintElementBase * elmt)
517 {
518 standard.Append(elmt);
519 extendable = FALSE;
520 }
521
522
Constraint(ConstraintElementList * stnd,PBoolean extend,ConstraintElementList * ext)523 Constraint::Constraint(ConstraintElementList * stnd, PBoolean extend, ConstraintElementList * ext)
524 {
525 if (stnd != NULL) {
526 standard = *stnd;
527 delete stnd;
528 }
529 extendable = extend;
530 if (ext != NULL) {
531 extensions = *ext;
532 delete ext;
533 }
534 }
535
536
PrintOn(ostream & strm) const537 void Constraint::PrintOn(ostream & strm) const
538 {
539 strm << '(';
540 for (PINDEX i = 0; i < standard.GetSize(); i++)
541 strm << standard[i];
542 if (extendable) {
543 strm << indent();
544 if (standard.GetSize() > 0)
545 strm << ", ";
546 strm << "..., ";
547 for (PINDEX i = 0; i < extensions.GetSize(); i++)
548 strm << extensions[i];
549 }
550 strm << ')';
551 }
552
553
GenerateCplusplus(const PString & fn,ostream & hdr,ostream & cxx)554 void Constraint::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
555 {
556 switch (standard.GetSize()) {
557 case 0 :
558 return;
559 case 1 :
560 break;
561 default :
562 PError << StdError(Warning) << "unsupported UNION constraints, ignored." << endl;
563 }
564
565 if (extensions.GetSize() > 0)
566 PError << StdError(Warning) << "unsupported extension constraints, ignored." << endl;
567
568 PString fn2 = fn;
569 if (fn.Find("PASN_Object::") == P_MAX_INDEX) {
570 if (extendable)
571 fn2 += "PASN_Object::ExtendableConstraint";
572 else
573 fn2 += "PASN_Object::FixedConstraint";
574 }
575
576 standard[0].GenerateCplusplus(fn2, hdr, cxx);
577 }
578
579
ReferencesType(const TypeBase & type)580 PBoolean Constraint::ReferencesType(const TypeBase & type)
581 {
582 PINDEX i;
583
584 for (i = 0; i < standard.GetSize(); i++) {
585 if (standard[i].ReferencesType(type))
586 return TRUE;
587 }
588
589 for (i = 0; i < extensions.GetSize(); i++) {
590 if (extensions[i].ReferencesType(type))
591 return TRUE;
592 }
593
594 return FALSE;
595 }
596
597
598 /////////////////////////////////////////////////////////
599
ConstraintElementBase()600 ConstraintElementBase::ConstraintElementBase()
601 {
602 exclusions = NULL;
603 }
604
605
GenerateCplusplus(const PString &,ostream &,ostream &)606 void ConstraintElementBase::GenerateCplusplus(const PString &, ostream &, ostream &)
607 {
608 PError << StdError(Warning) << "unsupported constraint, ignored." << endl;
609 }
610
611
ReferencesType(const TypeBase &)612 PBoolean ConstraintElementBase::ReferencesType(const TypeBase &)
613 {
614 return FALSE;
615 }
616
617
618 /////////////////////////////////////////////////////////
619
ConstrainAllConstraintElement(ConstraintElementBase * excl)620 ConstrainAllConstraintElement::ConstrainAllConstraintElement(ConstraintElementBase * excl)
621 {
622 SetExclusions(excl);
623 }
624
625
626 /////////////////////////////////////////////////////////
627
ElementListConstraintElement(ConstraintElementList * list)628 ElementListConstraintElement::ElementListConstraintElement(ConstraintElementList * list)
629 : elements(*list)
630 {
631 delete list;
632 }
633
634
PrintOn(ostream & strm) const635 void ElementListConstraintElement::PrintOn(ostream & strm) const
636 {
637 elements.PrintOn(strm);
638 }
639
640
GenerateCplusplus(const PString & fn,ostream & hdr,ostream & cxx)641 void ElementListConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
642 {
643 for (PINDEX i = 0; i < elements.GetSize(); i++)
644 elements[i].GenerateCplusplus(fn, hdr, cxx);
645 }
646
647
ReferencesType(const TypeBase & type)648 PBoolean ElementListConstraintElement::ReferencesType(const TypeBase & type)
649 {
650 for (PINDEX i = 0; i < elements.GetSize(); i++) {
651 if (elements[i].ReferencesType(type))
652 return TRUE;
653 }
654 return FALSE;
655 }
656
657
658 /////////////////////////////////////////////////////////
659
SingleValueConstraintElement(ValueBase * val)660 SingleValueConstraintElement::SingleValueConstraintElement(ValueBase * val)
661 {
662 value = val;
663 }
664
665
~SingleValueConstraintElement()666 SingleValueConstraintElement::~SingleValueConstraintElement()
667 {
668 delete value;
669 }
670
671
PrintOn(ostream & strm) const672 void SingleValueConstraintElement::PrintOn(ostream & strm) const
673 {
674 strm << *value;
675 }
676
677
GenerateCplusplus(const PString & fn,ostream & hdr,ostream & cxx)678 void SingleValueConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
679 {
680 cxx << fn << ", ";
681 value->GenerateCplusplus(hdr, cxx);
682 cxx << ");\n";
683 }
684
685
686 /////////////////////////////////////////////////////////
687
ValueRangeConstraintElement(ValueBase * lowerBound,ValueBase * upperBound)688 ValueRangeConstraintElement::ValueRangeConstraintElement(ValueBase * lowerBound, ValueBase * upperBound)
689 {
690 lower = lowerBound;
691 upper = upperBound;
692 }
693
694
~ValueRangeConstraintElement()695 ValueRangeConstraintElement::~ValueRangeConstraintElement()
696 {
697 delete lower;
698 delete upper;
699 }
700
701
PrintOn(ostream & strm) const702 void ValueRangeConstraintElement::PrintOn(ostream & strm) const
703 {
704 strm << *lower << ".." << *upper;
705 }
706
707
GenerateCplusplus(const PString & fn,ostream & hdr,ostream & cxx)708 void ValueRangeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
709 {
710 cxx << fn << ", ";
711 lower->GenerateCplusplus(hdr, cxx);
712 cxx << ", ";
713 upper->GenerateCplusplus(hdr, cxx);
714 cxx << ");\n";
715 }
716
717
718 /////////////////////////////////////////////////////////
719
SubTypeConstraintElement(TypeBase * typ)720 SubTypeConstraintElement::SubTypeConstraintElement(TypeBase * typ)
721 {
722 subtype = typ;
723 }
724
725
~SubTypeConstraintElement()726 SubTypeConstraintElement::~SubTypeConstraintElement()
727 {
728 delete subtype;
729 }
730
731
PrintOn(ostream & strm) const732 void SubTypeConstraintElement::PrintOn(ostream & strm) const
733 {
734 strm << subtype->GetTypeName();
735 }
736
737
GenerateCplusplus(const PString &,ostream & hdr,ostream &)738 void SubTypeConstraintElement::GenerateCplusplus(const PString &, ostream & hdr, ostream &)
739 {
740 hdr << subtype->GetTypeName();
741 }
742
743
ReferencesType(const TypeBase & type)744 PBoolean SubTypeConstraintElement::ReferencesType(const TypeBase & type)
745 {
746 return subtype->ReferencesType(type);
747 }
748
749
750 /////////////////////////////////////////////////////////
751
NestedConstraintConstraintElement(Constraint * con)752 NestedConstraintConstraintElement::NestedConstraintConstraintElement(Constraint * con)
753 {
754 constraint = con;
755 }
756
757
~NestedConstraintConstraintElement()758 NestedConstraintConstraintElement::~NestedConstraintConstraintElement()
759 {
760 delete constraint;
761 }
762
763
ReferencesType(const TypeBase & type)764 PBoolean NestedConstraintConstraintElement::ReferencesType(const TypeBase & type)
765 {
766 if (constraint == NULL)
767 return FALSE;
768
769 return constraint->ReferencesType(type);
770 }
771
772
773 /////////////////////////////////////////////////////////
774
SizeConstraintElement(Constraint * constraint)775 SizeConstraintElement::SizeConstraintElement(Constraint * constraint)
776 : NestedConstraintConstraintElement(constraint)
777 {
778 }
779
780
PrintOn(ostream & strm) const781 void SizeConstraintElement::PrintOn(ostream & strm) const
782 {
783 strm << "SIZE" << *constraint;
784 }
785
786
GenerateCplusplus(const PString & fn,ostream & hdr,ostream & cxx)787 void SizeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
788 {
789 constraint->GenerateCplusplus(fn, hdr, cxx);
790 }
791
792
793 /////////////////////////////////////////////////////////
794
FromConstraintElement(Constraint * constraint)795 FromConstraintElement::FromConstraintElement(Constraint * constraint)
796 : NestedConstraintConstraintElement(constraint)
797 {
798 }
799
800
PrintOn(ostream & strm) const801 void FromConstraintElement::PrintOn(ostream & strm) const
802 {
803 strm << "FROM" << *constraint;
804 }
805
806
GenerateCplusplus(const PString & fn,ostream & hdr,ostream & cxx)807 void FromConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
808 {
809 PString newfn = fn;
810 newfn.Replace("SetConstraints(", "SetCharacterSet(");
811 constraint->GenerateCplusplus(newfn, hdr, cxx);
812 }
813
814
815 /////////////////////////////////////////////////////////
816
WithComponentConstraintElement(PString * newName,Constraint * constraint,int pres)817 WithComponentConstraintElement::WithComponentConstraintElement(PString * newName,
818 Constraint * constraint,
819 int pres)
820 : NestedConstraintConstraintElement(constraint)
821 {
822 if (newName != NULL) {
823 name = *newName;
824 delete newName;
825 }
826
827 presence = pres;
828 }
829
830
PrintOn(ostream & strm) const831 void WithComponentConstraintElement::PrintOn(ostream & strm) const
832 {
833 if (name.IsEmpty())
834 strm << "WITH COMPONENT";
835 else
836 strm << name;
837
838 if (constraint != NULL)
839 strm << *constraint;
840
841 switch (presence) {
842 case Present :
843 strm << " PRESENT";
844 break;
845 case Absent :
846 strm << " ABSENT";
847 break;
848 case Optional :
849 strm << " OPTIONAL";
850 break;
851 }
852 }
853
854
GenerateCplusplus(const PString &,ostream &,ostream & cxx)855 void WithComponentConstraintElement::GenerateCplusplus(const PString &, ostream &, ostream & cxx)
856 {
857 if (presence == Present)
858 cxx << " IncludeOptionalField(e_" << name << ");\n";
859 }
860
861
862 /////////////////////////////////////////////////////////
863
InnerTypeConstraintElement(ConstraintElementList * list,PBoolean part)864 InnerTypeConstraintElement::InnerTypeConstraintElement(ConstraintElementList * list,
865 PBoolean part)
866 : ElementListConstraintElement(list)
867 {
868 partial = part;
869 }
870
871
PrintOn(ostream & strm) const872 void InnerTypeConstraintElement::PrintOn(ostream & strm) const
873 {
874 strm << "WITH COMPONENTS { ";
875
876 if (partial)
877 strm << "..., ";
878
879 for (PINDEX i = 0; i < elements.GetSize(); i++) {
880 if (i > 0)
881 strm << ", ";
882 elements[i].PrintOn(strm);
883 }
884
885 strm << " }";
886 }
887
888
GenerateCplusplus(const PString & fn,ostream & hdr,ostream & cxx)889 void InnerTypeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
890 {
891 for (PINDEX i = 0; i < elements.GetSize(); i++)
892 elements[i].GenerateCplusplus(fn, hdr, cxx);
893 }
894
895
896 /////////////////////////////////////////////////////////
897
UserDefinedConstraintElement(TypesList * t)898 UserDefinedConstraintElement::UserDefinedConstraintElement(TypesList * t)
899 {
900 if (t != NULL) {
901 types = *t;
902 delete t;
903 }
904 }
905
906
PrintOn(ostream & strm) const907 void UserDefinedConstraintElement::PrintOn(ostream & strm) const
908 {
909 strm << "CONSTRAINED BY { ";
910 for (PINDEX i = 0; i < types.GetSize(); i++) {
911 if (i > 0)
912 strm << ", ";
913 strm << types[i].GetTypeName();
914 }
915 strm << " }";
916 }
917
918
GenerateCplusplus(const PString &,ostream &,ostream &)919 void UserDefinedConstraintElement::GenerateCplusplus(const PString &, ostream &, ostream &)
920 {
921 }
922
923
924 /////////////////////////////////////////////////////////
925
TypeBase(unsigned tagNum)926 TypeBase::TypeBase(unsigned tagNum)
927 : tag(tagNum), defaultTag(tagNum)
928 {
929 isOptional = FALSE;
930 defaultValue = NULL;
931 isGenerated = FALSE;
932 }
933
934
TypeBase(TypeBase * copy)935 TypeBase::TypeBase(TypeBase * copy)
936 : name(copy->name),
937 identifier(MakeIdentifierC(name)),
938 tag(copy->tag),
939 defaultTag(copy->tag)
940 {
941 isOptional = copy->isOptional;
942 defaultValue = NULL;
943 isGenerated = FALSE;
944 }
945
946
Compare(const PObject & obj) const947 PObject::Comparison TypeBase::Compare(const PObject & obj) const
948 {
949 return name.Compare(((const TypeBase &)obj).name);
950 }
951
952
PrintOn(ostream & strm) const953 void TypeBase::PrintOn(ostream & strm) const
954 {
955 PrintStart(strm);
956 PrintFinish(strm);
957 }
958
959
PrintStart(ostream & strm) const960 void TypeBase::PrintStart(ostream & strm) const
961 {
962 strm << indent();
963 if (!name) {
964 strm << name;
965 if (!parameters.IsEmpty()) {
966 strm << " { ";
967 for (PINDEX i = 0; i < parameters.GetSize(); i++) {
968 if (i > 0)
969 strm << ", ";
970 strm << parameters[i];
971 }
972 strm << " } ";
973 }
974 strm << ": ";
975 }
976 strm << tag << GetClass() << ' ';
977 Module->SetIndentLevel(1);
978 }
979
980
PrintFinish(ostream & strm) const981 void TypeBase::PrintFinish(ostream & strm) const
982 {
983 Module->SetIndentLevel(-1);
984 strm << ' ' << constraints;
985 if (isOptional)
986 strm << " OPTIONAL";
987 if (defaultValue != NULL)
988 strm << " DEFAULT " << *defaultValue;
989 strm << '\n';
990 }
991
992
GetIdentifierTokenContext() const993 int TypeBase::GetIdentifierTokenContext() const
994 {
995 return IDENTIFIER;
996 }
997
998
GetBraceTokenContext() const999 int TypeBase::GetBraceTokenContext() const
1000 {
1001 return '{';
1002 }
1003
1004
SetName(PString * newName)1005 void TypeBase::SetName(PString * newName)
1006 {
1007 name = *newName;
1008 delete newName;
1009 identifier = MakeIdentifierC(name);
1010 }
1011
1012
AdjustIdentifier()1013 void TypeBase::AdjustIdentifier()
1014 {
1015 identifier = Module->GetPrefix() + MakeIdentifierC(name);
1016 }
1017
1018
SetTag(Tag::Type type,unsigned num,Tag::Mode mode)1019 void TypeBase::SetTag(Tag::Type type, unsigned num, Tag::Mode mode)
1020 {
1021 tag.type = type;
1022 tag.number = num;
1023 tag.mode = mode;
1024 }
1025
1026
SetParameters(PStringList * list)1027 void TypeBase::SetParameters(PStringList * list)
1028 {
1029 parameters = *list;
1030 delete list;
1031 }
1032
1033
MoveConstraints(TypeBase * from)1034 void TypeBase::MoveConstraints(TypeBase * from)
1035 {
1036 from->constraints.DisallowDeleteObjects();
1037
1038 while (!from->constraints.IsEmpty())
1039 constraints.Append(from->constraints.RemoveAt(0));
1040
1041 from->constraints.AllowDeleteObjects();
1042 }
1043
1044
FlattenUsedTypes()1045 void TypeBase::FlattenUsedTypes()
1046 {
1047 }
1048
1049
FlattenThisType(const TypeBase &)1050 TypeBase * TypeBase::FlattenThisType(const TypeBase &)
1051 {
1052 return this;
1053 }
1054
1055
IsChoice() const1056 PBoolean TypeBase::IsChoice() const
1057 {
1058 return FALSE;
1059 }
1060
1061
IsParameterizedType() const1062 PBoolean TypeBase::IsParameterizedType() const
1063 {
1064 return FALSE;
1065 }
1066
1067
IsPrimitiveType() const1068 PBoolean TypeBase::IsPrimitiveType() const
1069 {
1070 return TRUE;
1071 }
1072
1073
GenerateCplusplus(ostream & hdr,ostream & cxx)1074 void TypeBase::GenerateCplusplus(ostream & hdr, ostream & cxx)
1075 {
1076 BeginGenerateCplusplus(hdr, cxx);
1077
1078 // Close off the constructor implementation
1079 cxx << ")\n"
1080 "{\n";
1081 GenerateCplusplusConstraints(PString(), hdr, cxx);
1082
1083 EndGenerateCplusplus(hdr, cxx);
1084 }
1085
1086
GenerateForwardDecls(ostream &)1087 void TypeBase::GenerateForwardDecls(ostream &)
1088 {
1089 }
1090
1091
GenerateOperators(ostream &,ostream &,const TypeBase &)1092 void TypeBase::GenerateOperators(ostream &, ostream &, const TypeBase &)
1093 {
1094 }
1095
1096
GetTypeName() const1097 PString TypeBase::GetTypeName() const
1098 {
1099 return GetAncestorClass();
1100 }
1101
1102
CanReferenceType() const1103 PBoolean TypeBase::CanReferenceType() const
1104 {
1105 return FALSE;
1106 }
1107
1108
ReferencesType(const TypeBase &)1109 PBoolean TypeBase::ReferencesType(const TypeBase &)
1110 {
1111 return FALSE;
1112 }
1113
1114
SetImportPrefix(const PString &)1115 void TypeBase::SetImportPrefix(const PString &)
1116 {
1117 }
1118
1119
IsParameterisedImport() const1120 PBoolean TypeBase::IsParameterisedImport() const
1121 {
1122 return FALSE;
1123 }
1124
1125
BeginGenerateCplusplus(ostream & hdr,ostream & cxx)1126 void TypeBase::BeginGenerateCplusplus(ostream & hdr, ostream & cxx)
1127 {
1128 classNameString = GetIdentifier();
1129
1130 if (!parameters.IsEmpty()) {
1131 templatePrefix = "template <";
1132 classNameString += '<';
1133 for (PINDEX i = 0; i < parameters.GetSize(); i++) {
1134 if (i > 0) {
1135 templatePrefix += ", ";
1136 classNameString += ", ";
1137 }
1138 PString ident = MakeIdentifierC(parameters[i]);
1139 templatePrefix += "class " + ident;
1140 classNameString += ident;
1141 }
1142 templatePrefix += ">\n";
1143 classNameString += '>';
1144 }
1145
1146 // Output header file declaration of class
1147 hdr << "//\n"
1148 "// " << GetName() << "\n"
1149 "//\n"
1150 "\n";
1151 GenerateForwardDecls(hdr);
1152 hdr << templatePrefix
1153 << "class " << GetIdentifier() << " : public " << GetTypeName() << "\n"
1154 "{\n"
1155 "#ifndef PASN_LEANANDMEAN\n"
1156 " PCLASSINFO(" << GetIdentifier() << ", " << GetTypeName() << ");\n"
1157 "#endif\n"
1158 " public:\n"
1159 " " << GetIdentifier() << "(unsigned tag = ";
1160 if (tag.type == Tag::Universal &&
1161 tag.number < PARRAYSIZE(UniversalTagNames) &&
1162 UniversalTagNames[tag.number] != NULL)
1163 hdr << UniversalTagNames[tag.number];
1164 else
1165 hdr << tag.number;
1166 hdr << ", TagClass tagClass = " << UniversalTagClassNames[tag.type] << ");\n\n";
1167
1168 App & app = (App &)PProcess::Current();
1169 app.OutputAdditionalHeaders(hdr, GetIdentifier());
1170
1171 // Output cxx file implementation of class
1172 cxx << "//\n"
1173 "// " << GetName() << "\n"
1174 "//\n"
1175 "\n"
1176 << GetTemplatePrefix()
1177 << GetClassNameString() << "::" << GetIdentifier() << "(unsigned tag, PASN_Object::TagClass tagClass)\n"
1178 " : " << GetTypeName() << "(tag, tagClass";
1179 }
1180
1181
EndGenerateCplusplus(ostream & hdr,ostream & cxx)1182 void TypeBase::EndGenerateCplusplus(ostream & hdr, ostream & cxx)
1183 {
1184 cxx << "}\n"
1185 "\n"
1186 "\n";
1187
1188 GenerateOperators(hdr, cxx, *this);
1189
1190 // Output header file declaration of class
1191 hdr << " PObject * Clone() const;\n"
1192 "};\n"
1193 "\n"
1194 "\n";
1195
1196 // Output cxx file implementation of class
1197 cxx << GetTemplatePrefix()
1198 << "PObject * " << GetClassNameString() << "::Clone() const\n"
1199 "{\n"
1200 "#ifndef PASN_LEANANDMEAN\n"
1201 " PAssert(IsClass(" << GetClassNameString() << "::Class()), PInvalidCast);\n"
1202 "#endif\n"
1203 " return new " << GetClassNameString() << "(*this);\n"
1204 "}\n"
1205 "\n"
1206 "\n";
1207
1208 isGenerated = TRUE;
1209 }
1210
1211
GenerateCplusplusConstructor(ostream &,ostream & cxx)1212 void TypeBase::GenerateCplusplusConstructor(ostream &, ostream & cxx)
1213 {
1214 cxx << '(';
1215 if (HasNonStandardTag()) {
1216 if (tag.type == Tag::Universal &&
1217 tag.number < PARRAYSIZE(UniversalTagNames) &&
1218 UniversalTagNames[tag.number] != NULL)
1219 cxx << UniversalTagNames[tag.number];
1220 else
1221 cxx << tag.number;
1222 cxx << ", " << UniversalTagClassNames[tag.type];
1223 }
1224 cxx << ')';
1225 }
1226
1227
GenerateCplusplusConstraints(const PString & prefix,ostream & hdr,ostream & cxx)1228 void TypeBase::GenerateCplusplusConstraints(const PString & prefix, ostream & hdr, ostream & cxx)
1229 {
1230 for (PINDEX i = 0; i < constraints.GetSize(); i++)
1231 constraints[i].GenerateCplusplus(" " + prefix + "SetConstraints(", hdr, cxx);
1232 }
1233
1234
1235 /////////////////////////////////////////////////////////
1236
DefinedType(PString * name,PBoolean parameter)1237 DefinedType::DefinedType(PString * name, PBoolean parameter)
1238 : TypeBase(Tag::IllegalUniversalTag),
1239 referenceName(*name)
1240 {
1241 delete name;
1242 baseType = NULL;
1243 unresolved = !parameter;
1244 }
1245
1246
DefinedType(TypeBase * refType,TypeBase * bType)1247 DefinedType::DefinedType(TypeBase * refType, TypeBase * bType)
1248 : TypeBase(refType),
1249 referenceName(bType->GetName())
1250 {
1251 MoveConstraints(refType);
1252
1253 baseType = bType;
1254 unresolved = FALSE;
1255 }
1256
1257
DefinedType(TypeBase * refType,const PString & refName)1258 DefinedType::DefinedType(TypeBase * refType, const PString & refName)
1259 : TypeBase(refType)
1260 {
1261 MoveConstraints(refType);
1262 ConstructFromType(refType, refName);
1263 }
1264
1265
DefinedType(TypeBase * refType,const TypeBase & parent)1266 DefinedType::DefinedType(TypeBase * refType, const TypeBase & parent)
1267 : TypeBase(refType)
1268 {
1269 if (!name)
1270 ConstructFromType(refType, parent.GetName() + '_' + name);
1271 else
1272 ConstructFromType(refType, parent.GetName() + "_subtype");
1273 }
1274
1275
ConstructFromType(TypeBase * refType,const PString & name)1276 void DefinedType::ConstructFromType(TypeBase * refType, const PString & name)
1277 {
1278 referenceName = name;
1279 refType->SetName(new PString(name));
1280
1281 Module->AppendType(refType);
1282
1283 baseType = refType;
1284 unresolved = FALSE;
1285 }
1286
1287
PrintOn(ostream & strm) const1288 void DefinedType::PrintOn(ostream & strm) const
1289 {
1290 PrintStart(strm);
1291 strm << referenceName << ' ';
1292 PrintFinish(strm);
1293 }
1294
1295
CanReferenceType() const1296 PBoolean DefinedType::CanReferenceType() const
1297 {
1298 return TRUE;
1299 }
1300
1301
IsChoice() const1302 PBoolean DefinedType::IsChoice() const
1303 {
1304 if (baseType != NULL)
1305 return baseType->IsChoice();
1306 return FALSE;
1307 }
1308
1309
IsParameterizedType() const1310 PBoolean DefinedType::IsParameterizedType() const
1311 {
1312 if (baseType != NULL)
1313 return baseType->IsParameterizedType();
1314 return FALSE;
1315 }
1316
1317
ReferencesType(const TypeBase & type)1318 PBoolean DefinedType::ReferencesType(const TypeBase & type)
1319 {
1320 if (unresolved) {
1321 unresolved = FALSE;
1322
1323 if ((baseType = Module->FindType(referenceName)) == NULL)
1324 PError << StdError(Warning) << "unresolved symbol: " << referenceName << endl;
1325 else {
1326 if (!HasNonStandardTag())
1327 defaultTag = tag = baseType->GetTag();
1328 }
1329 }
1330
1331 return type.GetName() == referenceName;
1332 }
1333
1334
GenerateOperators(ostream & hdr,ostream & cxx,const TypeBase & actualType)1335 void DefinedType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1336 {
1337 if (baseType != NULL)
1338 baseType->GenerateOperators(hdr, cxx, actualType);
1339 }
1340
1341
GetAncestorClass() const1342 const char * DefinedType::GetAncestorClass() const
1343 {
1344 if (baseType != NULL)
1345 return baseType->GetAncestorClass();
1346 return NULL;
1347 }
1348
1349
GetTypeName() const1350 PString DefinedType::GetTypeName() const
1351 {
1352 if (baseType == NULL)
1353 return referenceName;
1354
1355 if (HasConstraints() && baseType->IsPrimitiveType())
1356 return baseType->GetTypeName();
1357
1358 return baseType->GetIdentifier();
1359 }
1360
1361
1362 /////////////////////////////////////////////////////////
1363
ParameterizedType(PString * name,TypesList * args)1364 ParameterizedType::ParameterizedType(PString * name, TypesList * args)
1365 : DefinedType(name, FALSE),
1366 arguments(*args)
1367 {
1368 delete args;
1369 }
1370
1371
PrintOn(ostream & strm) const1372 void ParameterizedType::PrintOn(ostream & strm) const
1373 {
1374 PrintStart(strm);
1375 strm << referenceName << " { ";
1376 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1377 if (i > 0)
1378 strm << ", ";
1379 strm << arguments[i].GetTypeName();
1380 }
1381 strm << " }";
1382 PrintFinish(strm);
1383 }
1384
1385
IsParameterizedType() const1386 PBoolean ParameterizedType::IsParameterizedType() const
1387 {
1388 return TRUE;
1389 }
1390
1391
ReferencesType(const TypeBase & type)1392 PBoolean ParameterizedType::ReferencesType(const TypeBase & type)
1393 {
1394 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1395 if (arguments[i].ReferencesType(type))
1396 return TRUE;
1397 }
1398
1399 return DefinedType::ReferencesType(type);
1400 }
1401
1402
GetTypeName() const1403 PString ParameterizedType::GetTypeName() const
1404 {
1405 PString typeName = DefinedType::GetTypeName();
1406 if (!arguments.IsEmpty()) {
1407 typeName += '<';
1408 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1409 if (i > 0)
1410 typeName += ", ";
1411 typeName += arguments[i].GetTypeName();
1412 }
1413 typeName += '>';
1414 }
1415 return typeName;
1416 }
1417
1418
1419 /////////////////////////////////////////////////////////
1420
SelectionType(PString * name,TypeBase * base)1421 SelectionType::SelectionType(PString * name, TypeBase * base)
1422 : TypeBase(Tag::IllegalUniversalTag),
1423 selection(*name)
1424 {
1425 delete name;
1426 baseType = PAssertNULL(base);
1427 }
1428
1429
~SelectionType()1430 SelectionType::~SelectionType()
1431 {
1432 delete baseType;
1433 }
1434
1435
PrintOn(ostream & strm) const1436 void SelectionType::PrintOn(ostream & strm) const
1437 {
1438 PrintStart(strm);
1439 strm << selection << '<' << *baseType;
1440 PrintFinish(strm);
1441 }
1442
1443
FlattenUsedTypes()1444 void SelectionType::FlattenUsedTypes()
1445 {
1446 baseType = baseType->FlattenThisType(*this);
1447 }
1448
1449
FlattenThisType(const TypeBase & parent)1450 TypeBase * SelectionType::FlattenThisType(const TypeBase & parent)
1451 {
1452 return new DefinedType(this, parent);
1453 }
1454
1455
GenerateCplusplus(ostream &,ostream &)1456 void SelectionType::GenerateCplusplus(ostream &, ostream &)
1457 {
1458 PError << StdError(Fatal) << "Cannot generate code for Selection type" << endl;
1459 isGenerated = TRUE;
1460 }
1461
1462
GetAncestorClass() const1463 const char * SelectionType::GetAncestorClass() const
1464 {
1465 return "";
1466 }
1467
1468
CanReferenceType() const1469 PBoolean SelectionType::CanReferenceType() const
1470 {
1471 return TRUE;
1472 }
1473
1474
ReferencesType(const TypeBase & type)1475 PBoolean SelectionType::ReferencesType(const TypeBase & type)
1476 {
1477 return baseType->ReferencesType(type);
1478 }
1479
1480
1481 /////////////////////////////////////////////////////////
1482
BooleanType()1483 BooleanType::BooleanType()
1484 : TypeBase(Tag::UniversalBoolean)
1485 {
1486 }
1487
1488
GenerateOperators(ostream & hdr,ostream & cxx,const TypeBase & actualType)1489 void BooleanType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1490 {
1491 hdr << " " << actualType.GetIdentifier() << " & operator=(PBoolean v)";
1492 if (Module->UsingInlines())
1493 hdr << " { SetValue(v); return *this; }\n";
1494 else {
1495 hdr << ";\n";
1496 cxx << actualType.GetTemplatePrefix()
1497 << actualType.GetIdentifier() << " & "
1498 << actualType.GetClassNameString() << "::operator=(PBoolean v)\n"
1499 "{\n"
1500 " SetValue(v);\n"
1501 " return *this;\n"
1502 "}\n"
1503 "\n"
1504 "\n";
1505 }
1506 }
1507
1508
GetAncestorClass() const1509 const char * BooleanType::GetAncestorClass() const
1510 {
1511 return "PASN_Boolean";
1512 }
1513
1514
1515 /////////////////////////////////////////////////////////
1516
IntegerType()1517 IntegerType::IntegerType()
1518 : TypeBase(Tag::UniversalInteger)
1519 {
1520 }
1521
1522
IntegerType(NamedNumberList * lst)1523 IntegerType::IntegerType(NamedNumberList * lst)
1524 : TypeBase(Tag::UniversalInteger),
1525 allowedValues(*lst)
1526 {
1527 delete lst;
1528 }
1529
1530
GenerateOperators(ostream & hdr,ostream & cxx,const TypeBase & actualType)1531 void IntegerType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1532 {
1533 hdr << " " << actualType.GetIdentifier() << " & operator=(int v)";
1534 if (Module->UsingInlines())
1535 hdr << " { SetValue(v); return *this; }\n";
1536 else {
1537 hdr << ";\n";
1538 cxx << actualType.GetTemplatePrefix()
1539 << actualType.GetIdentifier() << " & "
1540 << actualType.GetClassNameString() << "::operator=(int v)\n"
1541 "{\n"
1542 " SetValue(v);\n"
1543 " return *this;\n"
1544 "}\n"
1545 "\n"
1546 "\n";
1547 }
1548
1549 hdr << " " << actualType.GetIdentifier() << " & operator=(unsigned v)";
1550 if (Module->UsingInlines())
1551 hdr << " { SetValue(v); return *this; }\n";
1552 else {
1553 hdr << ";\n";
1554 cxx << actualType.GetTemplatePrefix()
1555 << actualType.GetIdentifier() << " & "
1556 << actualType.GetClassNameString() << "::operator=(unsigned v)\n"
1557 "{\n"
1558 " SetValue(v);\n"
1559 " return *this;\n"
1560 "}\n"
1561 "\n"
1562 "\n";
1563 }
1564 }
1565
1566
GetAncestorClass() const1567 const char * IntegerType::GetAncestorClass() const
1568 {
1569 return "PASN_Integer";
1570 }
1571
1572
1573 /////////////////////////////////////////////////////////
1574
EnumeratedType(NamedNumberList * enums,PBoolean extend,NamedNumberList * ext)1575 EnumeratedType::EnumeratedType(NamedNumberList * enums, PBoolean extend, NamedNumberList * ext)
1576 : TypeBase(Tag::UniversalEnumeration),
1577 enumerations(*enums)
1578 {
1579 numEnums = enums->GetSize();
1580 delete enums;
1581 extendable = extend;
1582 if (ext != NULL) {
1583 ext->DisallowDeleteObjects();
1584 for (PINDEX i = 0; i < ext->GetSize(); i++)
1585 enumerations.Append(ext->GetAt(i));
1586 delete ext;
1587 }
1588 }
1589
1590
PrintOn(ostream & strm) const1591 void EnumeratedType::PrintOn(ostream & strm) const
1592 {
1593 PrintStart(strm);
1594 strm << '\n';
1595 PINDEX i;
1596 for (i = 0; i < numEnums; i++)
1597 strm << indent() << enumerations[i] << '\n';
1598 if (extendable) {
1599 strm << "...\n";
1600 for (; i < enumerations.GetSize(); i++)
1601 strm << indent() << enumerations[i] << '\n';
1602 }
1603 PrintFinish(strm);
1604 }
1605
1606
FlattenThisType(const TypeBase & parent)1607 TypeBase * EnumeratedType::FlattenThisType(const TypeBase & parent)
1608 {
1609 return new DefinedType(this, parent);
1610 }
1611
1612
GenerateCplusplus(ostream & hdr,ostream & cxx)1613 void EnumeratedType::GenerateCplusplus(ostream & hdr, ostream & cxx)
1614 {
1615 PINDEX i;
1616 PArgList & args = PProcess::Current().GetArguments();
1617 PBoolean xml_output = args.HasOption('x');
1618
1619 cxx << "#ifndef PASN_NOPRINTON\n"
1620 "const static PASN_Names Names_"<< GetIdentifier() << "[]={\n";
1621
1622
1623 for (i = 0; i < enumerations.GetSize(); i++) {
1624 if (i > 0)
1625 cxx << " ,{\"";
1626 else
1627 cxx << " {\"";
1628
1629 int num = enumerations[i].GetNumber();
1630 cxx << enumerations[i].GetName() << "\"," << num << "}\n";
1631 }
1632
1633 cxx << "};\n#endif\n";
1634
1635 BeginGenerateCplusplus(hdr, cxx);
1636
1637 int maxEnumValue = 0;
1638 for (i = 0; i < enumerations.GetSize(); i++) {
1639 int num = enumerations[i].GetNumber();
1640 if (maxEnumValue < num)
1641 maxEnumValue = num;
1642 }
1643
1644 // Generate enumerations and complete the constructor implementation
1645 hdr << " enum Enumerations {\n";
1646 cxx << ", " << maxEnumValue << ", " << (extendable ? "TRUE" : "FALSE") << "\n"
1647 "#ifndef PASN_NOPRINTON\n ,(const PASN_Names *)Names_" << GetIdentifier() << "," <<enumerations.GetSize()<<"\n";
1648
1649 int prevNum = -1;
1650 for (i = 0; i < enumerations.GetSize(); i++) {
1651 if (i > 0) {
1652 hdr << ",\n";
1653 }
1654
1655 hdr << " e_" << MakeIdentifierC(enumerations[i].GetName());
1656
1657 int num = enumerations[i].GetNumber();
1658 if (num != prevNum+1) {
1659 hdr << " = " << num;
1660 }
1661 prevNum = num;
1662
1663 }
1664
1665 hdr << "\n"
1666 " };\n"
1667 "\n";
1668 cxx << "#endif\n"
1669 " )\n"
1670 "{\n";
1671 GenerateCplusplusConstraints(PString(), hdr, cxx);
1672
1673 if (xml_output)
1674 {
1675 hdr << " PBoolean DecodeXER(PXER_Stream & strm);\n"
1676 " void EncodeXER(PXER_Stream & strm) const;\n";
1677
1678 cxx << "}\n"
1679 "\n"
1680 << GetTemplatePrefix()
1681 << "PBoolean " << GetClassNameString() << "::DecodeXER(PXER_Stream & strm)\n"
1682 "{\n"
1683 " PXMLElement * elem = strm.GetCurrentElement();\n"
1684 " PXMLObject * sub_elem = elem->GetElement();\n"
1685 "\n"
1686 " if (!elem || !elem->IsElement())\n"
1687 " return FALSE;\n"
1688 "\n"
1689 " PCaselessString id = ((PXMLElement *)sub_elem)->GetName();\n"
1690 "\n"
1691 " ";
1692
1693 for (i = 0 ; i < enumerations.GetSize() ; i++) {
1694 cxx << " if (id == \"" << enumerations[i].GetName() << "\") {\n"
1695 " value = " << enumerations[i].GetNumber() << ";\n"
1696 " return TRUE;\n"
1697 " }\n"
1698 " else";
1699 }
1700
1701 cxx << "\n"
1702 " return FALSE;\n"
1703 "}\n"
1704 "\n";
1705
1706 cxx << GetTemplatePrefix()
1707 << "void " << GetClassNameString() << "::EncodeXER(PXER_Stream & strm) const\n"
1708 "{\n"
1709 " PXMLElement * elem = strm.GetCurrentElement();\n"
1710 " PString id;\n"
1711 "\n"
1712 " switch(value)\n"
1713 " {\n";
1714
1715 for (i = 0 ; i < enumerations.GetSize() ; i++) {
1716 cxx << " case " << enumerations[i].GetNumber() << ":\n"
1717 " elem->AddChild(new PXMLElement(elem, \"" << enumerations[i].GetName() << "\"));\n"
1718 " break;\n";
1719 }
1720
1721 cxx << " default:\n"
1722 " break;\n"
1723 " }\n";
1724 }
1725
1726 EndGenerateCplusplus(hdr, cxx);
1727 }
1728
1729
GenerateOperators(ostream & hdr,ostream & cxx,const TypeBase & actualType)1730 void EnumeratedType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1731 {
1732 hdr << " " << actualType.GetIdentifier() << " & operator=(unsigned v)";
1733 if (Module->UsingInlines())
1734 hdr << " { SetValue(v); return *this; }\n";
1735 else {
1736 hdr << ";\n";
1737 cxx << actualType.GetTemplatePrefix()
1738 << actualType.GetIdentifier() << " & "
1739 << actualType.GetClassNameString() << "::operator=(unsigned v)\n"
1740 "{\n"
1741 " SetValue(v);\n"
1742 " return *this;\n"
1743 "}\n"
1744 "\n"
1745 "\n";
1746 }
1747 }
1748
1749
GetAncestorClass() const1750 const char * EnumeratedType::GetAncestorClass() const
1751 {
1752 return "PASN_Enumeration";
1753 }
1754
1755
1756 /////////////////////////////////////////////////////////
1757
RealType()1758 RealType::RealType()
1759 : TypeBase(Tag::UniversalReal)
1760 {
1761 }
1762
1763
GetAncestorClass() const1764 const char * RealType::GetAncestorClass() const
1765 {
1766 return "PASN_Real";
1767 }
1768
1769
1770 /////////////////////////////////////////////////////////
1771
BitStringType()1772 BitStringType::BitStringType()
1773 : TypeBase(Tag::UniversalBitString)
1774 {
1775 }
1776
1777
BitStringType(NamedNumberList * lst)1778 BitStringType::BitStringType(NamedNumberList * lst)
1779 : TypeBase(Tag::UniversalBitString),
1780 allowedBits(*lst)
1781 {
1782 delete lst;
1783 }
1784
GetIdentifierTokenContext() const1785 int BitStringType::GetIdentifierTokenContext() const
1786 {
1787 return OID_IDENTIFIER;
1788 }
1789
1790
GetBraceTokenContext() const1791 int BitStringType::GetBraceTokenContext() const
1792 {
1793 return BITSTRING_BRACE;
1794 }
1795
1796
GetAncestorClass() const1797 const char * BitStringType::GetAncestorClass() const
1798 {
1799 return "PASN_BitString";
1800 }
1801
1802
1803 /////////////////////////////////////////////////////////
1804
OctetStringType()1805 OctetStringType::OctetStringType()
1806 : TypeBase(Tag::UniversalOctetString)
1807 {
1808 }
1809
1810
GenerateOperators(ostream & hdr,ostream & cxx,const TypeBase & actualType)1811 void OctetStringType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1812 {
1813 static const char * const types[] = {
1814 "char *", "PString &", "PBYTEArray &"
1815 };
1816
1817 PINDEX i;
1818 for (i = 0; i < PARRAYSIZE(types); i++) {
1819 hdr << " " << actualType.GetIdentifier() << "(const " << types[i] << " v)";
1820 if (Module->UsingInlines())
1821 hdr << " { SetValue(v); }\n";
1822 else {
1823 hdr << ";\n";
1824 cxx << actualType.GetTemplatePrefix()
1825 << actualType.GetIdentifier() << "::" << actualType.GetIdentifier() << "(const " << types[i] << " v)\n"
1826 "{\n"
1827 " SetValue(v);\n"
1828 "}\n"
1829 "\n"
1830 "\n";
1831 }
1832 }
1833
1834 hdr << '\n';
1835
1836 for (i = 0; i < PARRAYSIZE(types); i++) {
1837 hdr << " " << actualType.GetIdentifier() << " & operator=(const " << types[i] << " v)";
1838 if (Module->UsingInlines())
1839 hdr << " { SetValue(v); return *this; }\n";
1840 else {
1841 hdr << ";\n";
1842 cxx << actualType.GetTemplatePrefix()
1843 << actualType.GetIdentifier() << " & "
1844 << actualType.GetClassNameString() << "::operator=(const " << types[i] << " v)\n"
1845 "{\n"
1846 " SetValue(v);\n"
1847 " return *this;\n"
1848 "}\n"
1849 "\n"
1850 "\n";
1851 }
1852 }
1853 }
1854
1855
GetAncestorClass() const1856 const char * OctetStringType::GetAncestorClass() const
1857 {
1858 return "PASN_OctetString";
1859 }
1860
1861
1862 /////////////////////////////////////////////////////////
1863
NullType()1864 NullType::NullType()
1865 : TypeBase(Tag::UniversalNull)
1866 {
1867 }
1868
1869
GetAncestorClass() const1870 const char * NullType::GetAncestorClass() const
1871 {
1872 return "PASN_Null";
1873 }
1874
1875
1876 /////////////////////////////////////////////////////////
1877
SequenceType(TypesList * stnd,PBoolean extend,TypesList * ext,unsigned tagNum)1878 SequenceType::SequenceType(TypesList * stnd,
1879 PBoolean extend,
1880 TypesList * ext,
1881 unsigned tagNum)
1882 : TypeBase(tagNum)
1883 {
1884 if (stnd != NULL) {
1885 numFields = stnd->GetSize();
1886 fields = *stnd;
1887 delete stnd;
1888 }
1889 else
1890 numFields = 0;
1891 extendable = extend;
1892 if (ext != NULL) {
1893 ext->DisallowDeleteObjects();
1894 for (PINDEX i = 0; i < ext->GetSize(); i++)
1895 fields.Append(ext->GetAt(i));
1896 delete ext;
1897 }
1898 }
1899
1900
PrintOn(ostream & strm) const1901 void SequenceType::PrintOn(ostream & strm) const
1902 {
1903 PrintStart(strm);
1904 strm << '\n';
1905 PINDEX i;
1906 for (i = 0; i < numFields; i++)
1907 strm << fields[i];
1908 if (extendable) {
1909 strm << indent() << "...\n";
1910 for (; i < fields.GetSize(); i++)
1911 strm << fields[i];
1912 }
1913 PrintFinish(strm);
1914 }
1915
1916
FlattenUsedTypes()1917 void SequenceType::FlattenUsedTypes()
1918 {
1919 for (PINDEX i = 0; i < fields.GetSize(); i++)
1920 fields.SetAt(i, fields[i].FlattenThisType(*this));
1921 }
1922
1923
FlattenThisType(const TypeBase & parent)1924 TypeBase * SequenceType::FlattenThisType(const TypeBase & parent)
1925 {
1926 return new DefinedType(this, parent);
1927 }
1928
1929
IsPrimitiveType() const1930 PBoolean SequenceType::IsPrimitiveType() const
1931 {
1932 return FALSE;
1933 }
1934
1935
GenerateCplusplus(ostream & hdr,ostream & cxx)1936 void SequenceType::GenerateCplusplus(ostream & hdr, ostream & cxx)
1937 {
1938 PArgList & args = PProcess::Current().GetArguments();
1939 PBoolean xml_output = args.HasOption('x');
1940
1941 PINDEX i;
1942
1943 BeginGenerateCplusplus(hdr, cxx);
1944
1945 PINDEX baseOptions = 0;
1946 for (i = 0; i < fields.GetSize(); i++) {
1947 if (i < numFields && fields[i].IsOptional())
1948 baseOptions++;
1949 }
1950
1951 // Complete ancestor constructor parameters
1952 cxx << ", " << baseOptions << ", "
1953 << (extendable ? "TRUE" : "FALSE") << ", "
1954 << fields.GetSize() - numFields
1955 << ')';
1956
1957 // Output enum for optional parameters
1958 PBoolean outputEnum = FALSE;
1959 for (i = 0; i < fields.GetSize(); i++) {
1960 if (i >= numFields || fields[i].IsOptional()) {
1961 if (outputEnum)
1962 hdr << ",\n";
1963 else {
1964 hdr << " enum OptionalFields {\n";
1965 outputEnum = TRUE;
1966 }
1967 hdr << " e_" << fields[i].GetIdentifier();
1968 }
1969 }
1970
1971 if (outputEnum)
1972 hdr << "\n"
1973 " };\n"
1974 "\n";
1975
1976 // Output the declarations and constructors for member variables
1977 for (i = 0; i < fields.GetSize(); i++) {
1978 PString varname = "m_" + fields[i].GetIdentifier();
1979 hdr << " " << fields[i].GetTypeName() << ' ' << varname << ";\n";
1980 if (fields[i].HasNonStandardTag()) {
1981 cxx << ",\n"
1982 " " << varname;
1983 fields[i].GenerateCplusplusConstructor(hdr, cxx);
1984 }
1985 }
1986
1987 // Output declarations for generated functions
1988 hdr << "\n"
1989 " PINDEX GetDataLength() const;\n"
1990 " PBoolean Decode(PASN_Stream & strm);\n"
1991 " void Encode(PASN_Stream & strm) const;\n"
1992 "#ifndef PASN_NOPRINTON\n"
1993 " void PrintOn(ostream & strm) const;\n"
1994 "#endif\n";
1995
1996 if (xml_output)
1997 {
1998 hdr << " PBoolean PreambleDecodeXER(PXER_Stream & strm);\n";
1999
2000 if (fields.GetSize())
2001 hdr << " void PreambleEncodeXER(PXER_Stream &) const;\n";
2002 }
2003
2004
2005 if (numFields > 0)
2006 hdr << " Comparison Compare(const PObject & obj) const;\n";
2007
2008 cxx << "\n"
2009 "{\n";
2010 GenerateCplusplusConstraints(PString(), hdr, cxx);
2011 for (i = 0; i < fields.GetSize(); i++) {
2012 PString ident = fields[i].GetIdentifier();
2013 fields[i].GenerateCplusplusConstraints("m_" + ident + ".", hdr, cxx);
2014 if (i >= numFields && !fields[i].IsOptional())
2015 cxx << " IncludeOptionalField(e_" << ident << ");\n";
2016 }
2017 cxx << "}\n"
2018 "\n"
2019 "\n"
2020 "#ifndef PASN_NOPRINTON\n"
2021 << GetTemplatePrefix()
2022 << "void " << GetClassNameString() << "::PrintOn(ostream & strm) const\n"
2023 "{\n"
2024 " int indent = strm.precision() + 2;\n"
2025 " strm << \"{\\n\";\n";
2026
2027 for (i = 0; i < fields.GetSize(); i++) {
2028 PString id = fields[i].GetIdentifier();
2029 if (i >= numFields || fields[i].IsOptional())
2030 cxx << " if (HasOptionalField(e_" << id << "))\n"
2031 " ";
2032 cxx << " strm << setw(indent+" << id.GetLength()+3 << ") << \""
2033 << id << " = \" << setprecision(indent) << m_" << id << " << '\\n';\n";
2034 }
2035
2036 cxx << " strm << setw(indent-1) << setprecision(indent-2) << \"}\";\n"
2037 "}\n"
2038 "#endif\n"
2039 "\n"
2040 "\n";
2041
2042 if (xml_output)
2043 {
2044 cxx << GetTemplatePrefix()
2045 << "PBoolean " << GetClassNameString() << "::PreambleDecodeXER(PXER_Stream & strm)\n"
2046 "{\n";
2047
2048 if (fields.GetSize())
2049 {
2050 cxx << " PXMLElement * elem = strm.GetCurrentElement();\n"
2051 " PXMLElement * sub_elem;\n"
2052 " PBoolean result;\n"
2053 "\n";
2054
2055 for (i = 0; i < fields.GetSize(); i++)
2056 {
2057 PString id = fields[i].GetIdentifier();
2058 cxx << " if ((sub_elem = (PXMLElement *)elem->GetElement(\"" << id << "\")) && sub_elem->IsElement())\n"
2059 " {\n";
2060
2061 if (i >= numFields || fields[i].IsOptional())
2062 cxx << " IncludeOptionalField(e_" << id << ");\n";
2063
2064 cxx << " strm.SetCurrentElement(sub_elem);\n"
2065 " result = m_" << id << ".Decode(strm);\n"
2066 " strm.SetCurrentElement(sub_elem);\n"
2067 " if (!result)\n"
2068 " return FALSE;\n"
2069 " }\n"
2070 "\n";
2071 }
2072 }
2073
2074 cxx << " return TRUE;\n"
2075 "}\n"
2076 "\n";
2077
2078 if (fields.GetSize())
2079 {
2080 cxx << GetTemplatePrefix()
2081 << "void " << GetClassNameString() << "::PreambleEncodeXER(PXER_Stream & strm) const\n"
2082 "{\n";
2083
2084 cxx << " PXMLElement * elem = strm.GetCurrentElement();\n"
2085 " PXMLElement * sub_elem;\n"
2086 "\n";
2087
2088 for (i = 0; i < fields.GetSize(); i++)
2089 {
2090 PString id = fields[i].GetIdentifier();
2091
2092 if (i >= numFields || fields[i].IsOptional())
2093 cxx << " if (HasOptionalField(e_" << id << "))\n"
2094 " {\n";
2095
2096 cxx << " sub_elem = elem->AddChild(new PXMLElement(elem, \"" << id << "\"));\n"
2097 " strm.SetCurrentElement(sub_elem);\n"
2098 " m_" << id << ".Encode(strm);\n";
2099
2100 if (i >= numFields || fields[i].IsOptional())
2101 cxx << " }\n";
2102
2103 cxx << "\n";
2104 }
2105
2106 cxx << " strm.SetCurrentElement(elem);\n"
2107 "}\n"
2108 "\n";
2109 }
2110 }
2111
2112 if (numFields > 0) {
2113 cxx << GetTemplatePrefix()
2114 << "PObject::Comparison " << GetClassNameString() << "::Compare(const PObject & obj) const\n"
2115 "{\n"
2116 "#ifndef PASN_LEANANDMEAN\n"
2117 " PAssert(PIsDescendant(&obj, " << GetClassNameString() << "), PInvalidCast);\n"
2118 "#endif\n"
2119 " const " << GetClassNameString() << " & other = (const " << GetClassNameString() << " &)obj;\n"
2120 "\n"
2121 " Comparison result;\n"
2122 "\n";
2123
2124 for (i = 0; i < numFields; i++) {
2125 PString identifier = fields[i].GetIdentifier();
2126 cxx << " if ((result = m_" << identifier << ".Compare(other.m_" << identifier << ")) != EqualTo)\n"
2127 " return result;\n";
2128 }
2129
2130 cxx << "\n"
2131 " return PASN_Sequence::Compare(other);\n"
2132 "}\n"
2133 "\n"
2134 "\n";
2135 }
2136
2137 cxx << GetTemplatePrefix()
2138 << "PINDEX " << GetClassNameString() << "::GetDataLength() const\n"
2139 "{\n"
2140 " PINDEX length = 0;\n";
2141
2142 for (i = 0; i < numFields; i++) {
2143 if (fields[i].IsOptional())
2144 cxx << " if (HasOptionalField(e_" << fields[i].GetIdentifier() << "))\n ";
2145 cxx << " length += m_" << fields[i].GetIdentifier() << ".GetObjectLength();\n";
2146 }
2147
2148 cxx << " return length;\n"
2149 "}\n"
2150 "\n"
2151 "\n"
2152 << GetTemplatePrefix()
2153 << "PBoolean " << GetClassNameString() << "::Decode(PASN_Stream & strm)\n"
2154 "{\n"
2155 " if (!PreambleDecode(strm))\n"
2156 " return FALSE;\n\n";
2157
2158 if (xml_output)
2159 {
2160 cxx << " if (PIsDescendant(&strm, PXER_Stream))\n"
2161 " return TRUE;\n\n";
2162 }
2163
2164 for (i = 0; i < numFields; i++) {
2165 cxx << " if (";
2166 if (fields[i].IsOptional())
2167 cxx << "HasOptionalField(e_" << fields[i].GetIdentifier() << ") && ";
2168 cxx << "!m_" << fields[i].GetIdentifier() << ".Decode(strm))\n"
2169 " return FALSE;\n";
2170 }
2171
2172 for (; i < fields.GetSize(); i++)
2173 cxx << " if (!KnownExtensionDecode(strm, e_"
2174 << fields[i].GetIdentifier()
2175 << ", m_" << fields[i].GetIdentifier() << "))\n"
2176 " return FALSE;\n";
2177
2178 cxx << "\n"
2179 " return UnknownExtensionsDecode(strm);\n"
2180 "}\n"
2181 "\n"
2182 "\n"
2183 << GetTemplatePrefix()
2184 << "void " << GetClassNameString() << "::Encode(PASN_Stream & strm) const\n"
2185 "{\n"
2186 " PreambleEncode(strm);\n\n";
2187
2188 if (xml_output)
2189 {
2190 cxx << " if (PIsDescendant(&strm, PXER_Stream))\n"
2191 " return;\n\n";
2192 }
2193
2194 for (i = 0; i < numFields; i++) {
2195 if (fields[i].IsOptional())
2196 cxx << " if (HasOptionalField(e_" << fields[i].GetIdentifier() << "))\n"
2197 " ";
2198 cxx << " m_" << fields[i].GetIdentifier() << ".Encode(strm);\n";
2199 }
2200
2201 for (; i < fields.GetSize(); i++)
2202 cxx << " KnownExtensionEncode(strm, e_"
2203 << fields[i].GetIdentifier()
2204 << ", m_" << fields[i].GetIdentifier() << ");\n";
2205
2206 cxx << "\n"
2207 " UnknownExtensionsEncode(strm);\n";
2208
2209 EndGenerateCplusplus(hdr, cxx);
2210 }
2211
2212
GetAncestorClass() const2213 const char * SequenceType::GetAncestorClass() const
2214 {
2215 return "PASN_Sequence";
2216 }
2217
2218
CanReferenceType() const2219 PBoolean SequenceType::CanReferenceType() const
2220 {
2221 return TRUE;
2222 }
2223
2224
ReferencesType(const TypeBase & type)2225 PBoolean SequenceType::ReferencesType(const TypeBase & type)
2226 {
2227 for (PINDEX i = 0; i < fields.GetSize(); i++)
2228 if (fields[i].ReferencesType(type))
2229 return TRUE;
2230 return FALSE;
2231 }
2232
2233
2234 /////////////////////////////////////////////////////////
2235
SequenceOfType(TypeBase * base,Constraint * constraint,unsigned tag)2236 SequenceOfType::SequenceOfType(TypeBase * base, Constraint * constraint, unsigned tag)
2237 : TypeBase(tag)
2238 {
2239 baseType = base;
2240 if (constraint != NULL)
2241 AddConstraint(constraint);
2242 }
2243
2244
~SequenceOfType()2245 SequenceOfType::~SequenceOfType()
2246 {
2247 delete baseType;
2248 }
2249
2250
PrintOn(ostream & strm) const2251 void SequenceOfType::PrintOn(ostream & strm) const
2252 {
2253 PrintStart(strm);
2254 if (baseType == NULL)
2255 strm << "!!Null Type!!\n";
2256 else
2257 strm << *baseType << '\n';
2258 PrintFinish(strm);
2259 }
2260
2261
FlattenUsedTypes()2262 void SequenceOfType::FlattenUsedTypes()
2263 {
2264 baseType = baseType->FlattenThisType(*this);
2265 }
2266
2267
FlattenThisType(const TypeBase & parent)2268 TypeBase * SequenceOfType::FlattenThisType(const TypeBase & parent)
2269 {
2270 if (!baseType->IsPrimitiveType() || baseType->HasConstraints())
2271 return new DefinedType(this, parent);
2272
2273 // Search for an existing sequence of type
2274 PString seqName = "ArrayOf_" + baseType->GetTypeName();
2275
2276 TypeBase * existingType = Module->FindType(seqName);
2277 if (existingType != NULL)
2278 return new DefinedType(this, existingType);
2279
2280 return new DefinedType(this, seqName);
2281 }
2282
2283
IsPrimitiveType() const2284 PBoolean SequenceOfType::IsPrimitiveType() const
2285 {
2286 return FALSE;
2287 }
2288
2289
GenerateCplusplus(ostream & hdr,ostream & cxx)2290 void SequenceOfType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2291 {
2292 BeginGenerateCplusplus(hdr, cxx);
2293 cxx << ")\n"
2294 "{\n";
2295 GenerateCplusplusConstraints(PString(), hdr, cxx);
2296 cxx << "}\n"
2297 "\n"
2298 "\n";
2299
2300 PString baseTypeName = baseType->GetTypeName();
2301
2302 // Generate declarations for generated functions
2303 hdr << " PASN_Object * CreateObject() const;\n"
2304 " " << baseTypeName << " & operator[](PINDEX i) const";
2305 if (Module->UsingInlines())
2306 hdr << " { return (" << baseTypeName << " &)array[i]; }\n";
2307 else
2308 hdr << ";\n";
2309
2310 // Generate implementation for functions
2311 cxx << GetTemplatePrefix()
2312 << "PASN_Object * " << GetClassNameString() << "::CreateObject() const\n"
2313 "{\n";
2314
2315 if (baseType->HasConstraints()) {
2316 cxx << " " << baseTypeName << " * obj = new " << baseTypeName << ";\n";
2317 baseType->GenerateCplusplusConstraints("obj->", hdr, cxx);
2318 cxx << " return obj;\n";
2319 }
2320 else
2321 cxx << " return new " << baseTypeName << ";\n";
2322
2323 if (!Module->UsingInlines())
2324 cxx << "}\n"
2325 "\n"
2326 "\n"
2327 << GetTemplatePrefix()
2328 << baseTypeName << " & " << GetClassNameString() << "::operator[](PINDEX i) const\n"
2329 "{\n"
2330 " return (" << baseTypeName << " &)array[i];\n";
2331
2332 EndGenerateCplusplus(hdr, cxx);
2333 }
2334
2335
GenerateForwardDecls(ostream & hdr)2336 void SequenceOfType::GenerateForwardDecls(ostream & hdr)
2337 {
2338 if (baseType->IsParameterizedType())
2339 return;
2340
2341 PString baseTypeName = baseType->GetTypeName();
2342
2343 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2344 typesOutput += GetIdentifier();
2345
2346 if (!typesOutput.Contains(baseTypeName))
2347 hdr << "class " << baseTypeName << ";\n\n";
2348 }
2349
2350
GetAncestorClass() const2351 const char * SequenceOfType::GetAncestorClass() const
2352 {
2353 return "PASN_Array";
2354 }
2355
2356
CanReferenceType() const2357 PBoolean SequenceOfType::CanReferenceType() const
2358 {
2359 return TRUE;
2360 }
2361
2362
ReferencesType(const TypeBase & type)2363 PBoolean SequenceOfType::ReferencesType(const TypeBase & type)
2364 {
2365 return baseType->ReferencesType(type) && baseType->IsParameterizedType();
2366 }
2367
2368
2369 /////////////////////////////////////////////////////////
2370
SetType()2371 SetType::SetType()
2372 : SequenceType(NULL, FALSE, NULL, Tag::UniversalSet)
2373 {
2374 }
2375
2376
SetType(SequenceType * seq)2377 SetType::SetType(SequenceType * seq)
2378 : SequenceType(*seq)
2379 {
2380 tag.number = Tag::UniversalSet;
2381 }
2382
2383
GetAncestorClass() const2384 const char * SetType::GetAncestorClass() const
2385 {
2386 return "PASN_Set";
2387 }
2388
2389
2390 /////////////////////////////////////////////////////////
2391
SetOfType(TypeBase * base,Constraint * constraint)2392 SetOfType::SetOfType(TypeBase * base, Constraint * constraint)
2393 : SequenceOfType(base, constraint, Tag::UniversalSet)
2394 {
2395 }
2396
2397
2398 /////////////////////////////////////////////////////////
2399
ChoiceType(TypesList * stnd,PBoolean extendable,TypesList * extensions)2400 ChoiceType::ChoiceType(TypesList * stnd,
2401 PBoolean extendable,
2402 TypesList * extensions)
2403 : SequenceType(stnd, extendable, extensions, Tag::IllegalUniversalTag)
2404 {
2405 }
2406
GenerateCplusplus(ostream & hdr,ostream & cxx)2407 void ChoiceType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2408 {
2409 PINDEX i;
2410
2411 // Generate the enum's for each choice discriminator, and include strings for
2412 // PrintOn() debug output into acncestor constructor
2413 unsigned namesCount=0;
2414 int prevNum = -1;
2415 PBoolean outputEnum = FALSE;
2416 for (i = 0; i < fields.GetSize(); i++) {
2417 const Tag & fieldTag = fields[i].GetTag();
2418 if (fieldTag.mode == Tag::Automatic || !fields[i].IsChoice()) {
2419 if (outputEnum) {
2420 cxx << " ,{\"";
2421 }
2422 else {
2423 cxx << "\n"
2424 "#ifndef PASN_NOPRINTON\n"
2425 "const static PASN_Names Names_" <<GetIdentifier()<<"[]={\n"
2426 " {\"";
2427 outputEnum = TRUE;
2428 }
2429
2430 cxx << fields[i].GetIdentifier() << "\",";
2431
2432 if (fieldTag.mode != Tag::Automatic)
2433 {
2434 cxx << fieldTag.number;
2435 prevNum = fieldTag.number;
2436 }
2437 else
2438 cxx << ++prevNum;
2439 cxx << "}\n";
2440 namesCount++;
2441 }
2442 }
2443
2444 if (outputEnum) {
2445 cxx << "};\n#endif\n";
2446 }
2447
2448 BeginGenerateCplusplus(hdr, cxx);
2449
2450 // Complete the ancestor constructor parameters
2451 cxx << ", " << numFields << ", " << (extendable ? "TRUE" : "FALSE");
2452
2453 // Generate the enum's for each choice discriminator, and include strings for
2454 // PrintOn() debug output into acncestor constructor
2455 outputEnum = FALSE;
2456 prevNum = -1;
2457 for (i = 0; i < fields.GetSize(); i++) {
2458 const Tag & fieldTag = fields[i].GetTag();
2459 if (fieldTag.mode == Tag::Automatic || !fields[i].IsChoice()) {
2460 if (outputEnum) {
2461 hdr << ",\n";
2462 }
2463 else {
2464 hdr << " enum Choices {\n";
2465 outputEnum = TRUE;
2466 }
2467
2468 hdr << " e_" << fields[i].GetIdentifier();
2469
2470 if (fieldTag.mode != Tag::Automatic && fieldTag.number != (unsigned)(prevNum+1)) {
2471 hdr << " = " << fieldTag.number;
2472 }
2473 prevNum = fieldTag.number;
2474 }
2475 }
2476
2477 if (outputEnum) {
2478 hdr << "\n"
2479 " };\n"
2480 "\n";
2481 }
2482 cxx << "\n"
2483 "#ifndef PASN_NOPRINTON\n"
2484 " ,(const PASN_Names *)Names_" <<GetIdentifier() << "," << namesCount << "\n#endif\n";
2485
2486 cxx << ")\n"
2487 "{\n";
2488 GenerateCplusplusConstraints(PString(), hdr, cxx);
2489 cxx << "}\n"
2490 "\n"
2491 "\n";
2492
2493 // Generate code for type safe cast operators of selected choice object
2494 PBoolean needExtraLine = FALSE;
2495
2496 if (Module->UsingOperators()) {
2497 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2498 typesOutput += GetIdentifier();
2499
2500 for (i = 0; i < fields.GetSize(); i++) {
2501 PString type = fields[i].GetTypeName();
2502 if (!typesOutput.Contains(type)) {
2503 if (Module->UsingInlines()) {
2504 hdr << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2505 " operator " << type << " &() const { return *(" << type << " *)choice; }\n"
2506 "#else\n"
2507 " operator " << type << " &() { return *(" << type << " *)choice; }\n"
2508 " operator const " << type << " &() const { return *(const " << type << " *)choice; }\n"
2509 "#endif\n";
2510 }
2511 else {
2512 hdr << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2513 " operator " << type << " &() const;\n"
2514 "#else\n"
2515 " operator " << type << " &();\n"
2516 " operator const " << type << " &() const;\n"
2517 "#endif\n";
2518 cxx << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2519 << GetTemplatePrefix()
2520 << GetClassNameString() << "::operator " << type << " &() const\n"
2521 "#else\n"
2522 << GetTemplatePrefix()
2523 << GetClassNameString() << "::operator " << type << " &()\n"
2524 "{\n"
2525 "#ifndef PASN_LEANANDMEAN\n"
2526 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2527 "#endif\n"
2528 " return *(" << type << " *)choice;\n"
2529 "}\n"
2530 "\n"
2531 "\n"
2532 << GetTemplatePrefix()
2533 << GetClassNameString() << "::operator const " << type << " &() const\n"
2534 "#endif\n"
2535 "{\n"
2536 "#ifndef PASN_LEANANDMEAN\n"
2537 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2538 "#endif\n"
2539 " return *(" << type << " *)choice;\n"
2540 "}\n"
2541 "\n"
2542 "\n";
2543 }
2544 typesOutput += type;
2545 needExtraLine = TRUE;
2546 }
2547 }
2548 }
2549 else {
2550 for (i = 0; i < fields.GetSize(); i++) {
2551 PString type = fields[i].GetTypeName();
2552 PString fieldName = fields[i].GetIdentifier();
2553 if (Module->UsingInlines()) {
2554 hdr << " " << type << " & m_" << fieldName << "() { return *(" << type << " *)choice; }\n"
2555 " const " << type << " & m_" << fieldName << "() const { return *(const " << type << " *)choice; }\n";
2556 }
2557 else {
2558 hdr << " " << type << " & m_" << fieldName << "();\n"
2559 " const " << type << " & m_" << fieldName << "() const;\n";
2560 cxx << GetTemplatePrefix() << type << " & "
2561 << GetClassNameString() << "::m_" << fieldName << "()\n"
2562 "{\n"
2563 "#ifndef PASN_LEANANDMEAN\n"
2564 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2565 "#endif\n"
2566 " return *(" << type << " *)choice;\n"
2567 "}\n"
2568 "\n"
2569 "\n"
2570 << GetTemplatePrefix() << type << " const & "
2571 << GetClassNameString() << "::m_" << fieldName << "() const\n"
2572 "{\n"
2573 "#ifndef PASN_LEANANDMEAN\n"
2574 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2575 "#endif\n"
2576 " return *(" << type << " *)choice;\n"
2577 "}\n"
2578 "\n"
2579 "\n";
2580 }
2581 }
2582 needExtraLine = TRUE;
2583 }
2584
2585 if (needExtraLine)
2586 hdr << '\n';
2587
2588
2589 // Generate virtual function to create chosen object based on discriminator
2590 hdr << " PBoolean CreateObject();\n";
2591 cxx << GetTemplatePrefix()
2592 << "PBoolean " << GetClassNameString() << "::CreateObject()\n"
2593 "{\n";
2594
2595 // special case: if choice is all NULLs then simply output code
2596 PBoolean allNull = TRUE;
2597 for (i = 0; allNull && i < fields.GetSize(); i++)
2598 allNull = allNull && strcmp(fields[i].GetAncestorClass(), "PASN_Null") == 0;
2599
2600 if (allNull) {
2601 cxx << " choice = (tag <= e_" << fields[fields.GetSize()-1].GetIdentifier() << ") ? new PASN_Null() : NULL;\n"
2602 << " return choice != NULL;\n";
2603 }
2604
2605 else {
2606 // declare an array of flags indicating whether the tag has been output or not
2607 PBYTEArray flags(fields.GetSize());
2608 for (i = 0; i < fields.GetSize(); i++)
2609 flags[i] = 0;
2610
2611 // keep
2612 outputEnum = FALSE;
2613 for (i = 0; i < fields.GetSize(); i++) {
2614
2615 if (fields[i].GetTag().mode == Tag::Automatic || !fields[i].IsChoice()) {
2616
2617 // ignore this tag if output previously
2618 if (flags[i] != 0)
2619 continue;
2620
2621 if (!outputEnum) {
2622 cxx << " switch (tag) {\n";
2623 outputEnum = TRUE;
2624 }
2625
2626 // if the field has constraints, then output it alone
2627 // otherwise, look for all fields with the same type
2628 PString name = fields[i].GetTypeName();
2629 if (fields[i].HasConstraints()) {
2630 cxx << " case e_" << fields[i].GetIdentifier() << " :\n";
2631 flags[i] = 1;
2632 } else {
2633 PINDEX j;
2634 for (j = i; j < fields.GetSize(); j++) {
2635 if (fields[j].GetTypeName() == name) {
2636 cxx << " case e_" << fields[j].GetIdentifier() << " :\n";
2637 flags[j] = 1;
2638 }
2639 }
2640 }
2641
2642 cxx << " choice = new " << name;
2643 fields[i].GenerateCplusplusConstructor(hdr, cxx);
2644 cxx << ";\n";
2645 fields[i].GenerateCplusplusConstraints(" choice->", hdr, cxx);
2646 cxx << " return TRUE;\n";
2647 }
2648 }
2649
2650 if (outputEnum)
2651 cxx << " }\n"
2652 "\n";
2653
2654 for (i = 0; i < fields.GetSize(); i++) {
2655 if (fields[i].GetTag().mode != Tag::Automatic && fields[i].IsChoice())
2656 cxx << " choice = new " << fields[i].GetTypeName() << "(tag, tagClass);\n"
2657 " if (((PASN_Choice*)choice)->CreateObject())\n"
2658 " return TRUE;\n"
2659 " delete choice;\n"
2660 "\n";
2661 }
2662
2663 cxx << " choice = NULL;\n"
2664 " return FALSE;\n";
2665 }
2666
2667 EndGenerateCplusplus(hdr, cxx);
2668 }
2669
2670
GenerateForwardDecls(ostream & hdr)2671 void ChoiceType::GenerateForwardDecls(ostream & hdr)
2672 {
2673 // Output forward declarations for choice pointers, but not standard classes
2674 PBoolean needExtraLine = FALSE;
2675
2676 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2677 typesOutput += GetIdentifier();
2678
2679 PStringSet forwards;
2680
2681 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2682 PString type = fields[i].GetTypeName();
2683 if (!fields[i].IsParameterizedType() &&
2684 !typesOutput.Contains(type) &&
2685 !forwards.Contains(type)) {
2686 hdr << "class " << type << ";\n";
2687 needExtraLine = TRUE;
2688 forwards.Include(type);
2689 }
2690 }
2691
2692 if (needExtraLine)
2693 hdr << '\n';
2694 }
2695
2696
IsPrimitiveType() const2697 PBoolean ChoiceType::IsPrimitiveType() const
2698 {
2699 return FALSE;
2700 }
2701
2702
IsChoice() const2703 PBoolean ChoiceType::IsChoice() const
2704 {
2705 return TRUE;
2706 }
2707
2708
GetAncestorClass() const2709 const char * ChoiceType::GetAncestorClass() const
2710 {
2711 return "PASN_Choice";
2712 }
2713
2714
ReferencesType(const TypeBase & type)2715 PBoolean ChoiceType::ReferencesType(const TypeBase & type)
2716 {
2717 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2718 if (fields[i].ReferencesType(type) && fields[i].IsParameterizedType())
2719 return TRUE;
2720 }
2721 return FALSE;
2722 }
2723
2724
2725 /////////////////////////////////////////////////////////
2726
EmbeddedPDVType()2727 EmbeddedPDVType::EmbeddedPDVType()
2728 : TypeBase(Tag::UniversalEmbeddedPDV)
2729 {
2730 }
2731
2732
GetAncestorClass() const2733 const char * EmbeddedPDVType::GetAncestorClass() const
2734 {
2735 return "PASN_OctetString";
2736 }
2737
2738
2739 /////////////////////////////////////////////////////////
2740
ExternalType()2741 ExternalType::ExternalType()
2742 : TypeBase(Tag::UniversalExternalType)
2743 {
2744 }
2745
2746
GetAncestorClass() const2747 const char * ExternalType::GetAncestorClass() const
2748 {
2749 return "PASN_OctetString";
2750 }
2751
2752
2753 /////////////////////////////////////////////////////////
2754
AnyType(PString * ident)2755 AnyType::AnyType(PString * ident)
2756 : TypeBase(Tag::UniversalExternalType)
2757 {
2758 if (ident != NULL) {
2759 identifier = *ident;
2760 delete ident;
2761 }
2762 }
2763
2764
PrintOn(ostream & strm) const2765 void AnyType::PrintOn(ostream & strm) const
2766 {
2767 PrintStart(strm);
2768 if (!identifier)
2769 strm << "Defined by " << identifier;
2770 PrintFinish(strm);
2771 }
2772
2773
GetAncestorClass() const2774 const char * AnyType::GetAncestorClass() const
2775 {
2776 return "PASN_OctetString";
2777 }
2778
2779
2780 /////////////////////////////////////////////////////////
2781
StringTypeBase(int tag)2782 StringTypeBase::StringTypeBase(int tag)
2783 : TypeBase(tag)
2784 {
2785 }
2786
2787
GetBraceTokenContext() const2788 int StringTypeBase::GetBraceTokenContext() const
2789 {
2790 return STRING_BRACE;
2791 }
2792
2793
GenerateOperator(const char * rhsType,ostream & hdr,ostream & cxx,const TypeBase & actualType)2794 static void GenerateOperator(const char * rhsType, ostream & hdr, ostream & cxx, const TypeBase & actualType)
2795 {
2796 hdr << " " << actualType.GetIdentifier() << " & operator=(const " << rhsType << " v)";
2797 if (Module->UsingInlines())
2798 hdr << " { SetValue(v); return *this; }\n";
2799 else {
2800 hdr << ";\n";
2801 cxx << actualType.GetTemplatePrefix()
2802 << actualType.GetIdentifier() << " & "
2803 << actualType.GetClassNameString() << "::operator=(const " << rhsType << " v)\n"
2804 "{\n"
2805 " SetValue(v);\n"
2806 " return *this;\n"
2807 "}\n"
2808 "\n"
2809 "\n";
2810 }
2811 }
2812
2813
GenerateOperators(ostream & hdr,ostream & cxx,const TypeBase & actualType)2814 void StringTypeBase::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
2815 {
2816 GenerateOperator("char *", hdr, cxx, actualType);
2817 GenerateOperator("PString &", hdr, cxx, actualType);
2818 }
2819
2820
2821 /////////////////////////////////////////////////////////
2822
BMPStringType()2823 BMPStringType::BMPStringType()
2824 : StringTypeBase(Tag::UniversalBMPString)
2825 {
2826 }
2827
2828
GetAncestorClass() const2829 const char * BMPStringType::GetAncestorClass() const
2830 {
2831 return "PASN_BMPString";
2832 }
2833
2834
GenerateOperators(ostream & hdr,ostream & cxx,const TypeBase & actualType)2835 void BMPStringType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
2836 {
2837 StringTypeBase::GenerateOperators(hdr, cxx, actualType);
2838 GenerateOperator("PWCharArray &", hdr, cxx, actualType);
2839 GenerateOperator("PASN_BMPString &", hdr, cxx, actualType);
2840 }
2841
2842
2843 /////////////////////////////////////////////////////////
2844
GeneralStringType()2845 GeneralStringType::GeneralStringType()
2846 : StringTypeBase(Tag::UniversalGeneralString)
2847 {
2848 }
2849
2850
GetAncestorClass() const2851 const char * GeneralStringType::GetAncestorClass() const
2852 {
2853 return "PASN_GeneralString";
2854 }
2855
2856
2857 /////////////////////////////////////////////////////////
2858
GraphicStringType()2859 GraphicStringType::GraphicStringType()
2860 : StringTypeBase(Tag::UniversalGraphicString)
2861 {
2862 }
2863
2864
GetAncestorClass() const2865 const char * GraphicStringType::GetAncestorClass() const
2866 {
2867 return "PASN_GraphicString";
2868 }
2869
2870
2871 /////////////////////////////////////////////////////////
2872
IA5StringType()2873 IA5StringType::IA5StringType()
2874 : StringTypeBase(Tag::UniversalIA5String)
2875 {
2876 }
2877
2878
GetAncestorClass() const2879 const char * IA5StringType::GetAncestorClass() const
2880 {
2881 return "PASN_IA5String";
2882 }
2883
2884
2885 /////////////////////////////////////////////////////////
2886
ISO646StringType()2887 ISO646StringType::ISO646StringType()
2888 : StringTypeBase(Tag::UniversalVisibleString)
2889 {
2890 }
2891
2892
GetAncestorClass() const2893 const char * ISO646StringType::GetAncestorClass() const
2894 {
2895 return "PASN_ISO646String";
2896 }
2897
2898
2899 /////////////////////////////////////////////////////////
2900
NumericStringType()2901 NumericStringType::NumericStringType()
2902 : StringTypeBase(Tag::UniversalNumericString)
2903 {
2904 }
2905
2906
GetAncestorClass() const2907 const char * NumericStringType::GetAncestorClass() const
2908 {
2909 return "PASN_NumericString";
2910 }
2911
2912
2913 /////////////////////////////////////////////////////////
2914
PrintableStringType()2915 PrintableStringType::PrintableStringType()
2916 : StringTypeBase(Tag::UniversalPrintableString)
2917 {
2918 }
2919
2920
GetAncestorClass() const2921 const char * PrintableStringType::GetAncestorClass() const
2922 {
2923 return "PASN_PrintableString";
2924 }
2925
2926
2927 /////////////////////////////////////////////////////////
2928
TeletexStringType()2929 TeletexStringType::TeletexStringType()
2930 : StringTypeBase(Tag::UniversalTeletexString)
2931 {
2932 }
2933
2934
GetAncestorClass() const2935 const char * TeletexStringType::GetAncestorClass() const
2936 {
2937 return "PASN_TeletexString";
2938 }
2939
2940
2941 /////////////////////////////////////////////////////////
2942
T61StringType()2943 T61StringType::T61StringType()
2944 : StringTypeBase(Tag::UniversalTeletexString)
2945 {
2946 }
2947
2948
GetAncestorClass() const2949 const char * T61StringType::GetAncestorClass() const
2950 {
2951 return "PASN_T61String";
2952 }
2953
2954
2955 /////////////////////////////////////////////////////////
2956
UniversalStringType()2957 UniversalStringType::UniversalStringType()
2958 : StringTypeBase(Tag::UniversalUniversalString)
2959 {
2960 }
2961
2962
GetAncestorClass() const2963 const char * UniversalStringType::GetAncestorClass() const
2964 {
2965 return "PASN_UniversalString";
2966 }
2967
2968
2969 /////////////////////////////////////////////////////////
2970
VideotexStringType()2971 VideotexStringType::VideotexStringType()
2972 : StringTypeBase(Tag::UniversalVideotexString)
2973 {
2974 }
2975
2976
GetAncestorClass() const2977 const char * VideotexStringType::GetAncestorClass() const
2978 {
2979 return "PASN_VideotexString";
2980 }
2981
2982
2983 /////////////////////////////////////////////////////////
2984
VisibleStringType()2985 VisibleStringType::VisibleStringType()
2986 : StringTypeBase(Tag::UniversalVisibleString)
2987 {
2988 }
2989
2990
GetAncestorClass() const2991 const char * VisibleStringType::GetAncestorClass() const
2992 {
2993 return "PASN_VisibleString";
2994 }
2995
2996
2997 /////////////////////////////////////////////////////////
2998
UnrestrictedCharacterStringType()2999 UnrestrictedCharacterStringType::UnrestrictedCharacterStringType()
3000 : StringTypeBase(Tag::UniversalUniversalString)
3001 {
3002 }
3003
3004
GetAncestorClass() const3005 const char * UnrestrictedCharacterStringType::GetAncestorClass() const
3006 {
3007 return "PASN_UnrestrictedString";
3008 }
3009
3010
3011 /////////////////////////////////////////////////////////
3012
GeneralizedTimeType()3013 GeneralizedTimeType::GeneralizedTimeType()
3014 : TypeBase(Tag::UniversalGeneralisedTime)
3015 {
3016 }
3017
3018
GetAncestorClass() const3019 const char * GeneralizedTimeType::GetAncestorClass() const
3020 {
3021 return "PASN_GeneralisedTime";
3022 }
3023
3024
3025 /////////////////////////////////////////////////////////
3026
UTCTimeType()3027 UTCTimeType::UTCTimeType()
3028 : TypeBase(Tag::UniversalUTCTime)
3029 {
3030 }
3031
3032
GetAncestorClass() const3033 const char * UTCTimeType::GetAncestorClass() const
3034 {
3035 return "PASN_UniversalTime";
3036 }
3037
3038
3039 /////////////////////////////////////////////////////////
3040
ObjectDescriptorType()3041 ObjectDescriptorType::ObjectDescriptorType()
3042 : TypeBase(Tag::UniversalObjectDescriptor)
3043 {
3044 }
3045
3046
GetAncestorClass() const3047 const char * ObjectDescriptorType::GetAncestorClass() const
3048 {
3049 return "PASN_ObectDescriptor";
3050 }
3051
3052
3053 /////////////////////////////////////////////////////////
3054
ObjectIdentifierType()3055 ObjectIdentifierType::ObjectIdentifierType()
3056 : TypeBase(Tag::UniversalObjectId)
3057 {
3058 }
3059
3060
GetIdentifierTokenContext() const3061 int ObjectIdentifierType::GetIdentifierTokenContext() const
3062 {
3063 return OID_IDENTIFIER;
3064 }
3065
3066
GetBraceTokenContext() const3067 int ObjectIdentifierType::GetBraceTokenContext() const
3068 {
3069 return OID_BRACE;
3070 }
3071
3072
GetAncestorClass() const3073 const char * ObjectIdentifierType::GetAncestorClass() const
3074 {
3075 return "PASN_ObjectId";
3076 }
3077
3078
3079 /////////////////////////////////////////////////////////
3080
ObjectClassFieldType(PString * objclass,PString * field)3081 ObjectClassFieldType::ObjectClassFieldType(PString * objclass, PString * field)
3082 : TypeBase(Tag::IllegalUniversalTag),
3083 asnObjectClassName(*objclass),
3084 asnObjectClassField(*field)
3085 {
3086 delete objclass;
3087 delete field;
3088 }
3089
3090
GetAncestorClass() const3091 const char * ObjectClassFieldType::GetAncestorClass() const
3092 {
3093 return "PASN_OctetString";
3094 }
3095
3096
PrintOn(ostream & strm) const3097 void ObjectClassFieldType::PrintOn(ostream & strm) const
3098 {
3099 PrintStart(strm);
3100 strm << asnObjectClassName << '.' << asnObjectClassField;
3101 PrintFinish(strm);
3102 }
3103
3104
FlattenThisType(const TypeBase & parent)3105 TypeBase * ObjectClassFieldType::FlattenThisType(const TypeBase & parent)
3106 {
3107 return new DefinedType(this, parent);
3108 }
3109
3110
IsPrimitiveType() const3111 PBoolean ObjectClassFieldType::IsPrimitiveType() const
3112 {
3113 return FALSE;
3114 }
3115
3116
GenerateCplusplus(ostream & hdr,ostream & cxx)3117 void ObjectClassFieldType::GenerateCplusplus(ostream & hdr, ostream & cxx)
3118 {
3119 BeginGenerateCplusplus(hdr, cxx);
3120
3121 hdr << " PBoolean DecodeSubType(";
3122 GenerateCplusplusConstraints(PString(), hdr, cxx);
3123 hdr << " & obj) { return PASN_OctetString::DecodeSubType(obj); }\n"
3124 " void EncodeSubType(const ";
3125 GenerateCplusplusConstraints(PString(), hdr, cxx);
3126 hdr << " & obj) { PASN_OctetString::EncodeSubType(obj); } \n"
3127 "\n";
3128
3129 cxx << ")\n"
3130 "{\n";
3131
3132 EndGenerateCplusplus(hdr, cxx);
3133 }
3134
3135
CanReferenceType() const3136 PBoolean ObjectClassFieldType::CanReferenceType() const
3137 {
3138 return TRUE;
3139 }
3140
3141
ReferencesType(const TypeBase & type)3142 PBoolean ObjectClassFieldType::ReferencesType(const TypeBase & type)
3143 {
3144 for (PINDEX i = 0; i < constraints.GetSize(); i++) {
3145 if (constraints[i].ReferencesType(type))
3146 return TRUE;
3147 }
3148 return FALSE;
3149 }
3150
3151
3152 /////////////////////////////////////////////////////////
3153
ImportedType(PString * theName,PBoolean param)3154 ImportedType::ImportedType(PString * theName, PBoolean param)
3155 : TypeBase(Tag::IllegalUniversalTag)
3156 {
3157 identifier = name = *theName;
3158 delete theName;
3159
3160 parameterised = param;
3161 }
3162
3163
GetAncestorClass() const3164 const char * ImportedType::GetAncestorClass() const
3165 {
3166 return identifier;
3167 }
3168
3169
AdjustIdentifier()3170 void ImportedType::AdjustIdentifier()
3171 {
3172 identifier = modulePrefix + '_' + MakeIdentifierC(name);
3173 }
3174
3175
GenerateCplusplus(ostream &,ostream &)3176 void ImportedType::GenerateCplusplus(ostream &, ostream &)
3177 {
3178 }
3179
3180
SetImportPrefix(const PString & prefix)3181 void ImportedType::SetImportPrefix(const PString & prefix)
3182 {
3183 modulePrefix = prefix;
3184 }
3185
3186
IsParameterisedImport() const3187 PBoolean ImportedType::IsParameterisedImport() const
3188 {
3189 return parameterised;
3190 }
3191
3192
3193 /////////////////////////////////////////////////////////
3194
SearchType(const PString & theName)3195 SearchType::SearchType(const PString & theName)
3196 : TypeBase(Tag::IllegalUniversalTag)
3197 {
3198 identifier = name = theName;
3199 }
3200
3201
GetAncestorClass() const3202 const char * SearchType::GetAncestorClass() const
3203 {
3204 return identifier;
3205 }
3206
3207
3208 /////////////////////////////////////////////////////////
3209
SetValueName(PString * name)3210 void ValueBase::SetValueName(PString * name)
3211 {
3212 valueName = *name;
3213 delete name;
3214 }
3215
3216
PrintBase(ostream & strm) const3217 void ValueBase::PrintBase(ostream & strm) const
3218 {
3219 if (!valueName)
3220 strm << '\n' << indent() << valueName << '=';
3221 }
3222
3223
GenerateCplusplus(ostream &,ostream &)3224 void ValueBase::GenerateCplusplus(ostream &, ostream &)
3225 {
3226 PError << StdError(Warning) << "unsupported value type." << endl;
3227 }
3228
3229
3230 /////////////////////////////////////////////////////////
3231
DefinedValue(PString * name)3232 DefinedValue::DefinedValue(PString * name)
3233 : referenceName(*name)
3234 {
3235 delete name;
3236 actualValue = NULL;
3237 unresolved = TRUE;
3238 }
3239
3240
PrintOn(ostream & strm) const3241 void DefinedValue::PrintOn(ostream & strm) const
3242 {
3243 PrintBase(strm);
3244 strm << referenceName;
3245 }
3246
3247
GenerateCplusplus(ostream & hdr,ostream & cxx)3248 void DefinedValue::GenerateCplusplus(ostream & hdr, ostream & cxx)
3249 {
3250 if (unresolved) {
3251 unresolved = FALSE;
3252
3253 const ValuesList & values = Module->GetValues();
3254 for (PINDEX i = 0; i < values.GetSize(); i++) {
3255 if (values[i].GetName() == referenceName) {
3256 actualValue = &values[i];
3257 break;
3258 }
3259 }
3260 }
3261
3262 if (actualValue != NULL)
3263 actualValue->GenerateCplusplus(hdr, cxx);
3264 else
3265 cxx << "e_" << referenceName;
3266 }
3267
3268
3269 /////////////////////////////////////////////////////////
3270
BooleanValue(PBoolean newVal)3271 BooleanValue::BooleanValue(PBoolean newVal)
3272 {
3273 value = newVal;
3274 }
3275
3276
PrintOn(ostream & strm) const3277 void BooleanValue::PrintOn(ostream & strm) const
3278 {
3279 PrintBase(strm);
3280 strm << (value ? "TRUE" : "FALSE");
3281 }
3282
3283
GenerateCplusplus(ostream &,ostream & cxx)3284 void BooleanValue::GenerateCplusplus(ostream &, ostream & cxx)
3285 {
3286 cxx << (value ? "TRUE" : "FALSE");
3287 }
3288
3289
3290 /////////////////////////////////////////////////////////
3291
IntegerValue(PInt64 newVal)3292 IntegerValue::IntegerValue(PInt64 newVal)
3293 {
3294 value = newVal;
3295 }
3296
3297
PrintOn(ostream & strm) const3298 void IntegerValue::PrintOn(ostream & strm) const
3299 {
3300 PrintBase(strm);
3301
3302 strm << value;
3303 }
3304
3305
GenerateCplusplus(ostream &,ostream & cxx)3306 void IntegerValue::GenerateCplusplus(ostream &, ostream & cxx)
3307 {
3308 cxx << value;
3309 if (value > INT_MAX)
3310 cxx << 'U';
3311 }
3312
3313
3314 /////////////////////////////////////////////////////////
3315
RealValue(double newVal)3316 RealValue::RealValue(double newVal)
3317 {
3318 value = newVal;
3319 }
3320
3321
3322 /////////////////////////////////////////////////////////
3323
OctetStringValue(PString * newVal)3324 OctetStringValue::OctetStringValue(PString * newVal)
3325 {
3326 // value = *newVal;
3327 delete newVal;
3328 }
3329
3330
3331 /////////////////////////////////////////////////////////
3332
BitStringValue(PString * newVal)3333 BitStringValue::BitStringValue(PString * newVal)
3334 {
3335 // value = *newVal;
3336 delete newVal;
3337 }
3338
3339
BitStringValue(PStringList * newVal)3340 BitStringValue::BitStringValue(PStringList * newVal)
3341 {
3342 // value = *newVal;
3343 delete newVal;
3344 }
3345
3346
3347 /////////////////////////////////////////////////////////
3348
CharacterValue(BYTE c)3349 CharacterValue::CharacterValue(BYTE c)
3350 {
3351 value = c;
3352 }
3353
3354
CharacterValue(BYTE t1,BYTE t2)3355 CharacterValue::CharacterValue(BYTE t1, BYTE t2)
3356 {
3357 value = (t1<<8) + t2;
3358 }
3359
3360
CharacterValue(BYTE q1,BYTE q2,BYTE q3,BYTE q4)3361 CharacterValue::CharacterValue(BYTE q1, BYTE q2, BYTE q3, BYTE q4)
3362 {
3363 value = (q1<<24) + (q2<<16) + (q3<<8) + q4;
3364 }
3365
3366
PrintOn(ostream & strm) const3367 void CharacterValue::PrintOn(ostream & strm) const
3368 {
3369 strm << "'\\x" << hex << value << '\'';
3370 }
3371
3372
GenerateCplusplus(ostream &,ostream & cxx)3373 void CharacterValue::GenerateCplusplus(ostream &, ostream & cxx)
3374 {
3375 cxx << value;
3376 }
3377
3378
3379 /////////////////////////////////////////////////////////
3380
CharacterStringValue(PString * newVal)3381 CharacterStringValue::CharacterStringValue(PString * newVal)
3382 {
3383 value = *newVal;
3384 delete newVal;
3385 }
3386
3387
CharacterStringValue(PStringList * newVal)3388 CharacterStringValue::CharacterStringValue(PStringList * newVal)
3389 {
3390 for (PINDEX i = 0; i < newVal->GetSize(); i++)
3391 value += (*newVal)[i];
3392 delete newVal;
3393 }
3394
3395
PrintOn(ostream & strm) const3396 void CharacterStringValue::PrintOn(ostream & strm) const
3397 {
3398 strm << value;
3399 }
3400
3401
GenerateCplusplus(ostream &,ostream & cxx)3402 void CharacterStringValue::GenerateCplusplus(ostream &, ostream & cxx)
3403 {
3404 cxx << value;
3405 }
3406
3407
3408 /////////////////////////////////////////////////////////
3409
ObjectIdentifierValue(PString * newVal)3410 ObjectIdentifierValue::ObjectIdentifierValue(PString * newVal)
3411 {
3412 value.Append(newVal);
3413 }
3414
3415
ObjectIdentifierValue(PStringList * newVal)3416 ObjectIdentifierValue::ObjectIdentifierValue(PStringList * newVal)
3417 {
3418 value = *newVal;
3419 delete newVal;
3420 }
3421
3422
PrintOn(ostream & strm) const3423 void ObjectIdentifierValue::PrintOn(ostream & strm) const
3424 {
3425 PrintBase(strm);
3426 if (value.IsEmpty())
3427 strm << "empty object identifier";
3428 else {
3429 strm << value[0];
3430 for (PINDEX i = 1; i < value.GetSize(); i++)
3431 strm << '.' << value[i];
3432 }
3433 strm << '\n';
3434 }
3435
3436
3437 /////////////////////////////////////////////////////////
3438
PrintOn(ostream & strm) const3439 void MinValue::PrintOn(ostream & strm) const
3440 {
3441 strm << "MIN";
3442 }
3443
3444
GenerateCplusplus(ostream &,ostream & cxx)3445 void MinValue::GenerateCplusplus(ostream &, ostream & cxx)
3446 {
3447 cxx << "MinimumValue";
3448 }
3449
3450
3451 /////////////////////////////////////////////////////////
3452
PrintOn(ostream & strm) const3453 void MaxValue::PrintOn(ostream & strm) const
3454 {
3455 strm << "MAX";
3456 }
3457
3458
GenerateCplusplus(ostream &,ostream & cxx)3459 void MaxValue::GenerateCplusplus(ostream &, ostream & cxx)
3460 {
3461 cxx << "MaximumValue";
3462 }
3463
3464
3465 /////////////////////////////////////////////////////////
3466
SequenceValue(ValuesList * list)3467 SequenceValue::SequenceValue(ValuesList * list)
3468 {
3469 if (list != NULL) {
3470 values = *list;
3471 delete list;
3472 }
3473 }
3474
3475
PrintOn(ostream & strm) const3476 void SequenceValue::PrintOn(ostream & strm) const
3477 {
3478 strm << "{ ";
3479 for (PINDEX i = 0; i < values.GetSize(); i++) {
3480 if (i > 0)
3481 strm << ", ";
3482 strm << values[i];
3483 }
3484 strm << " }";
3485 }
3486
3487
3488 /////////////////////////////////////////////////////////
3489
MibBase(PString * nam,PString * descr,PString * refer,ValueBase * val)3490 MibBase::MibBase(PString * nam,
3491 PString * descr,
3492 PString * refer,
3493 ValueBase * val)
3494 : name(*nam)
3495 {
3496 delete nam;
3497 if (descr != NULL) {
3498 description = *descr;
3499 delete descr;
3500 }
3501 if (refer != NULL) {
3502 reference = *refer;
3503 delete refer;
3504 }
3505 value = val;
3506 }
3507
3508
~MibBase()3509 MibBase::~MibBase()
3510 {
3511 delete value;
3512 }
3513
3514
3515 /////////////////////////////////////////////////////////
3516
MibObject(PString * nam,TypeBase * typ,Access acc,Status stat,PString * descr,PString * refer,PStringList * idx,ValueBase * defVal,ValueBase * setVal)3517 MibObject::MibObject(PString * nam,
3518 TypeBase * typ,
3519 Access acc,
3520 Status stat,
3521 PString * descr,
3522 PString * refer,
3523 PStringList * idx,
3524 ValueBase * defVal,
3525 ValueBase * setVal)
3526 : MibBase(nam, descr, refer, setVal)
3527 {
3528 type = typ;
3529 access = acc;
3530 status = stat;
3531 if (idx != NULL) {
3532 index = *idx;
3533 delete idx;
3534 }
3535 defaultValue = defVal;
3536 }
3537
3538
~MibObject()3539 MibObject::~MibObject()
3540 {
3541 delete type;
3542 delete defaultValue;
3543 }
3544
3545
PrintOn(ostream & strm) const3546 void MibObject::PrintOn(ostream & strm) const
3547 {
3548 strm << " Object: " << name << "\n " << *type
3549 << " " << description << "\n"
3550 " " << *value << '\n';
3551 }
3552
3553
3554 /////////////////////////////////////////////////////////
3555
MibTrap(PString * nam,ValueBase * ent,ValuesList * var,PString * descr,PString * refer,ValueBase * val)3556 MibTrap::MibTrap(PString * nam, ValueBase * ent, ValuesList * var,
3557 PString * descr, PString * refer, ValueBase * val)
3558 : MibBase(nam, descr, refer, val)
3559 {
3560 enterprise = ent;
3561 if (var != NULL) {
3562 variables = *var;
3563 delete var;
3564 }
3565 }
3566
3567
~MibTrap()3568 MibTrap::~MibTrap()
3569 {
3570 delete enterprise;
3571 }
3572
3573
PrintOn(ostream & strm) const3574 void MibTrap::PrintOn(ostream & strm) const
3575 {
3576 strm << " Trap: " << name << "\n " << *enterprise
3577 << " " << description << "\n"
3578 " " << *value << '\n';
3579 }
3580
3581
3582 /////////////////////////////////////////////////////////
3583
ImportModule(PString * name,TypesList * syms)3584 ImportModule::ImportModule(PString * name, TypesList * syms)
3585 : fullModuleName(*name),
3586 shortModuleName(Module->GetImportModuleName(*name)),
3587 filename(shortModuleName.ToLower())
3588 {
3589 delete name;
3590 symbols = *syms;
3591 delete syms;
3592
3593 PStringArray renameArgs = shortModuleName.Tokenise(',');
3594 switch (renameArgs.GetSize())
3595 {
3596 case 3 :
3597 filename = renameArgs[2];
3598 case 2 :
3599 directoryPrefix = renameArgs[1];
3600 shortModuleName = renameArgs[0];
3601 }
3602
3603 for (PINDEX i = 0; i < symbols.GetSize(); i++) {
3604 symbols[i].SetImportPrefix(shortModuleName);
3605 Module->AppendType(&symbols[i]);
3606 }
3607 }
3608
3609
PrintOn(ostream & strm) const3610 void ImportModule::PrintOn(ostream & strm) const
3611 {
3612 strm << " " << fullModuleName << " (" << shortModuleName << "):\n";
3613 for (PINDEX i = 0; i < symbols.GetSize(); i++)
3614 strm << " " << symbols[i];
3615 strm << '\n';
3616 }
3617
3618
GenerateCplusplus(ostream & hdr,ostream & cxx)3619 void ImportModule::GenerateCplusplus(ostream & hdr, ostream & cxx)
3620 {
3621 hdr << "#include \"" << directoryPrefix << filename << ".h\"\n";
3622
3623 for (PINDEX i = 0; i < symbols.GetSize(); i++) {
3624 if (symbols[i].IsParameterisedImport()) {
3625 cxx << "#include \"" << filename << "_t.cxx\"\n";
3626 break;
3627 }
3628 }
3629 }
3630
3631
3632 /////////////////////////////////////////////////////////
3633
ModuleDefinition(PString * name,PStringList * id,Tag::Mode defTagMode)3634 ModuleDefinition::ModuleDefinition(PString * name, PStringList * id, Tag::Mode defTagMode)
3635 : moduleName(*name),
3636 definitiveId(*id)
3637 {
3638 delete name;
3639 delete id;
3640 defaultTagMode = defTagMode;
3641 exportAll = FALSE;
3642 indentLevel = 1;
3643
3644 PArgList & args = PProcess::Current().GetArguments();
3645 if (args.HasOption('r')) {
3646 PStringArray renames = args.GetOptionString('r').Lines();
3647 for (PINDEX i = 0; i < renames.GetSize(); i++) {
3648 PINDEX equal = renames[i].Find('=');
3649 if (equal > 0 && equal != P_MAX_INDEX)
3650 importNames.SetAt(renames[i].Left(equal).Trim(), renames[i].Mid(equal+1).Trim());
3651 }
3652 }
3653 }
3654
3655
SetExportAll()3656 void ModuleDefinition::SetExportAll()
3657 {
3658 exportAll = TRUE;
3659 }
3660
3661
SetExports(TypesList * syms)3662 void ModuleDefinition::SetExports(TypesList * syms)
3663 {
3664 exports = *syms;
3665 delete syms;
3666 }
3667
3668
PrintOn(ostream & strm) const3669 void ModuleDefinition::PrintOn(ostream & strm) const
3670 {
3671 strm << moduleName << "\n"
3672 "Default Tags: " << Tag::modeNames[defaultTagMode] << "\n"
3673 "Exports:";
3674 if (exportAll)
3675 strm << " ALL";
3676 else {
3677 strm << "\n ";
3678 for (PINDEX i = 0; i < exports.GetSize(); i++)
3679 strm << exports[i] << ' ';
3680 strm << '\n';
3681 }
3682 strm << "Imports:\n" << imports << "\n"
3683 "Types:\n" << types << "\n"
3684 "Values:\n" << values << "\n"
3685 "MIBs:\n" << mibs << endl;
3686 }
3687
3688
AppendType(TypeBase * type)3689 void ModuleDefinition::AppendType(TypeBase * type)
3690 {
3691 types.Append(type);
3692 sortedTypes.Append(type);
3693 }
3694
3695
FindType(const PString & name)3696 TypeBase * ModuleDefinition::FindType(const PString & name)
3697 {
3698 PINDEX pos = sortedTypes.GetValuesIndex(SearchType(name));
3699 if (pos != P_MAX_INDEX)
3700 return &sortedTypes[pos];
3701 return NULL;
3702 }
3703
3704
GetImportModuleName(const PString & moduleName)3705 PString ModuleDefinition::GetImportModuleName(const PString & moduleName)
3706 {
3707 if (importNames.Contains(moduleName))
3708 return importNames[moduleName];
3709
3710 PINDEX pos = moduleName.Find('-');
3711 if (pos > 32)
3712 pos = 32;
3713 return moduleName.Left(pos);
3714 }
3715
3716
GenerateCplusplus(const PFilePath & path,const PString & modName,const PString & headerPrefix,unsigned numFiles,PBoolean useNamespaces,PBoolean useInlines,PBoolean useOperators,PBoolean verbose)3717 void ModuleDefinition::GenerateCplusplus(const PFilePath & path,
3718 const PString & modName,
3719 const PString & headerPrefix,
3720 unsigned numFiles,
3721 PBoolean useNamespaces,
3722 PBoolean useInlines,
3723 PBoolean useOperators,
3724 PBoolean verbose)
3725 {
3726 PArgList & args = PProcess::Current().GetArguments();
3727 PBoolean xml_output = args.HasOption('x');
3728 PINDEX i;
3729
3730 usingInlines = useInlines;
3731 usingOperators = useOperators;
3732
3733 // Adjust the module name to what is specified to a default
3734 if (!modName)
3735 moduleName = modName;
3736 else
3737 moduleName = MakeIdentifierC(moduleName);
3738
3739 // Set the prefix on all external class names
3740 if (!useNamespaces)
3741 classNamePrefix = moduleName + '_';
3742
3743
3744 if (verbose)
3745 cout << "Sorting " << types.GetSize() << " types..." << endl;
3746
3747
3748 // Create sorted list for faster searching.
3749 sortedTypes.DisallowDeleteObjects();
3750 for (i = 0; i < types.GetSize(); i++)
3751 sortedTypes.Append(&types[i]);
3752
3753 // Flatten types by generating types for "inline" definitions
3754 for (i = 0; i < types.GetSize(); i++)
3755 types[i].FlattenUsedTypes();
3756
3757 // Reorder types
3758 // Determine if we need a separate file for template closure
3759 PBoolean hasTemplates = FALSE;
3760 types.DisallowDeleteObjects();
3761 PINDEX loopDetect = 0;
3762 PINDEX bubble = 0;
3763 while (bubble < types.GetSize()) {
3764 PBoolean makesReference = FALSE;
3765
3766 TypeBase & bubbleType = types[bubble];
3767 if (bubbleType.CanReferenceType()) {
3768 for (i = bubble; i < types.GetSize(); i++) {
3769 if (bubbleType.ReferencesType(types[i])) {
3770 makesReference = TRUE;
3771 break;
3772 }
3773 }
3774 }
3775
3776 if (makesReference) {
3777 types.Append(types.RemoveAt(bubble));
3778 if (loopDetect > types.GetSize()) {
3779 PError << StdError(Fatal)
3780 << "Recursive type definition: " << bubbleType.GetName() << endl;
3781 break;
3782 }
3783 loopDetect++;
3784 }
3785 else {
3786 loopDetect = bubble;
3787 bubble++;
3788 }
3789
3790 if (bubbleType.HasParameters())
3791 hasTemplates = TRUE;
3792 }
3793 types.AllowDeleteObjects();
3794
3795 // Adjust all of the C++ identifiers prepending module name
3796 for (i = 0; i < types.GetSize(); i++)
3797 types[i].AdjustIdentifier();
3798
3799
3800 // Generate the code
3801 if (verbose)
3802 cout << "Generating code (" << types.GetSize() << " classes) ..." << endl;
3803
3804
3805 // Output the special template closure file, if necessary
3806 PString templateFilename;
3807 if (hasTemplates) {
3808 OutputFile templateFile;
3809 if (!templateFile.Open(path, "_t", ".cxx"))
3810 return;
3811
3812 for (i = 0; i < types.GetSize(); i++) {
3813 if (types[i].HasParameters()) {
3814 PStringStream dummy;
3815 types[i].GenerateCplusplus(dummy, templateFile);
3816 }
3817 }
3818
3819 if (verbose)
3820 cout << "Completed " << templateFile.GetFilePath() << endl;
3821
3822 templateFilename = templateFile.GetFilePath().GetFileName();
3823 }
3824
3825 // Start the header file
3826 OutputFile hdrFile;
3827 if (!hdrFile.Open(path, "", ".h"))
3828 return;
3829
3830 hdrFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3831
3832 hdrFile << "#ifndef __" << moduleName.ToUpper() << "_H\n"
3833 "#define __" << moduleName.ToUpper() << "_H\n"
3834 "\n"
3835 "#ifdef P_USE_PRAGMA\n"
3836 "#pragma interface\n"
3837 "#endif\n"
3838 "\n";
3839
3840 if (xml_output)
3841 hdrFile << "#define P_EXPAT 1\n"
3842 "#include <ptclib/pxml.h>\n";
3843
3844 hdrFile << "#include <ptclib/asner.h>\n"
3845 "\n";
3846
3847 // Start the first (and maybe only) cxx file
3848 OutputFile cxxFile;
3849 if (!cxxFile.Open(path, numFiles > 1 ? "_1" : "", ".cxx"))
3850 return;
3851
3852 PString headerName = hdrFile.GetFilePath().GetFileName();
3853
3854 cxxFile << "#ifdef P_USE_PRAGMA\n"
3855 "#pragma implementation \"" << headerName << "\"\n"
3856 "#endif\n"
3857 "\n"
3858 "#include <ptlib.h>\n"
3859 "#include \"" << headerPrefix << headerName << "\"\n"
3860 "\n"
3861 "#define new PNEW\n"
3862 "\n"
3863 "\n";
3864
3865 cxxFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3866
3867 // Include the template closure file.
3868 if (hasTemplates)
3869 cxxFile << "#include \"" << templateFilename << "\"\n\n";
3870
3871
3872 for (i = 0; i < imports.GetSize(); i++)
3873 imports[i].GenerateCplusplus(hdrFile, cxxFile);
3874 if (!imports.IsEmpty()) {
3875 hdrFile << "\n\n";
3876 cxxFile << "\n\n";
3877 }
3878
3879
3880 if (useNamespaces) {
3881 hdrFile << "namespace " << moduleName << " {\n"
3882 "\n";
3883 cxxFile << "using namespace " << moduleName << ";\n"
3884 "\n";
3885 }
3886
3887
3888 PINDEX classesPerFile = (types.GetSize()+numFiles-1)/numFiles;
3889 for (i = 0; i < types.GetSize(); i++) {
3890 if (i > 0 && i%classesPerFile == 0) {
3891
3892 cxxFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
3893 "\n";
3894
3895 cxxFile.Close();
3896
3897 if (verbose)
3898 cout << "Completed " << cxxFile.GetFilePath() << endl;
3899
3900 if (!cxxFile.Open(path, psprintf("_%u", i/classesPerFile+1), ".cxx"))
3901 return;
3902
3903 cxxFile << "#include <ptlib.h>\n"
3904 "#include \"" << headerPrefix << headerName << "\"\n"
3905 "\n";
3906
3907 if (useNamespaces)
3908 cxxFile << "using namespace " << moduleName << ";\n"
3909 "\n";
3910 cxxFile << "#define new PNEW\n"
3911 "\n"
3912 "\n";
3913
3914 cxxFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3915
3916 }
3917
3918 if (types[i].HasParameters()) {
3919 PStringStream dummy;
3920 types[i].GenerateCplusplus(hdrFile, dummy);
3921 }
3922 else
3923 types[i].GenerateCplusplus(hdrFile, cxxFile);
3924 }
3925
3926
3927 // Close off the files
3928 if (useNamespaces)
3929 hdrFile << "};\n"
3930 "\n";
3931
3932 hdrFile << "#endif // __" << moduleName.ToUpper() << "_H\n"
3933 "\n";
3934
3935 hdrFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
3936 "\n";
3937
3938 cxxFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
3939 "\n";
3940
3941 if (verbose)
3942 cout << "Completed " << cxxFile.GetFilePath() << endl;
3943 }
3944
3945
3946 //////////////////////////////////////////////////////////////////////////////
3947