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