Fixed problem with XER and the new RTTI system
[pwlib.git] / tools / asnparser / main.cxx
blobb119abc86555e447115fc75b8e2d4f00cfe0a1a2
1 /*
2 * main.cxx
4 * PWLib application source file for asnparser
6 * ASN.1 compiler to produce C++ classes.
8 * Copyright (c) 1997-1999 Equivalence Pty. Ltd.
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/
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.
20 * The Original Code is ASN Parser.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions of this code were written with the assisance of funding from
25 * Vovida Networks, Inc. http://www.vovida.com.
27 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
28 * All Rights Reserved.
30 * Contributor(s): ______________________________________.
32 * $Log$
33 * Revision 1.50 2004/04/21 00:32:02 csoutheren
34 * Fixed problem with XER and the new RTTI system
35 * Thanks to Federico Pinna and Reitek S.p.A.
37 * Revision 1.49 2004/04/13 11:33:55 csoutheren
38 * Fixed XER output, thanks to Federico Pinna
40 * Revision 1.48 2004/04/03 08:22:23 csoutheren
41 * Remove pseudo-RTTI and replaced with real RTTI
43 * Revision 1.47 2004/02/17 10:24:04 rjongbloed
44 * Updated version number so will rebuild ASN files.
46 * Revision 1.46 2004/02/17 09:38:24 csoutheren
47 * Added change to remove duplicate forward declarations
48 * See SourceForge bug 832245
49 * Thanks to Vyacheslav E. Andrejev
51 * Revision 1.45 2003/10/03 00:13:04 rjongbloed
52 * Added ability to specify CHOICE field selection by function rather than operator as the operator technique does not work with some dumb compilers.
53 * Added ability to specify that the header file name be different from the module name and module prefix string.
55 * Revision 1.44 2003/02/27 04:05:30 robertj
56 * Added ability to have alternate directories for header file
57 * includes in generated C++ code.
58 * Added constructors to PASN_OctetString descendant classes to help
59 * with doing simple assignments.
61 * Revision 1.43 2003/02/26 01:57:44 robertj
62 * Added XML encoding rules to ASN system, thanks Federico Pinna
64 * Revision 1.42 2003/02/19 14:18:55 craigs
65 * Fixed ifdef problem with multipart cxx files
67 * Revision 1.41 2003/02/18 10:50:41 craigs
68 * Added minor optimisation of outputted ASN code
69 * Added automatic insertion of defines to allow disabling of generated code
71 * Revision 1.40 2002/11/27 11:42:52 robertj
72 * Rearranged code to avoid GNU compiler problem.
73 * Changed new classheader parameters to be full C literal like string for
74 * improved backslash conversion.
75 * Incremented version number.
77 * Revision 1.39 2002/11/26 11:39:10 craigs
78 * Added option to allow adding functions to generated header files
80 * Revision 1.38 2002/09/16 01:08:59 robertj
81 * Added #define so can select if #pragma interface/implementation is used on
82 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
84 * Revision 1.37 2001/10/02 00:56:14 robertj
85 * Fixed problem with autonumering enumerated types.
87 * Revision 1.36 2001/08/06 01:39:02 robertj
88 * Added assignement operator with RHS of PASN_BMPString to classes
89 * descended from PASN_BMPString.
91 * Revision 1.35 2001/08/03 09:01:02 robertj
92 * Added assignement operator with RHS of PWORDArray to classes
93 * descended from PASN_BMPString.
95 * Revision 1.34 2001/06/14 02:09:20 robertj
96 * Corrected support for ASN object class type reference constructs
97 * ie TYPE-IDENTIFIER.&Type encoded as octet string.
99 * Revision 1.33 2001/04/26 08:15:58 robertj
100 * Fixed problem with ASN compile of single constraints on enumerations.
102 * Revision 1.32 2001/04/23 04:40:14 robertj
103 * Added ASN standard types GeneralizedTime and UTCTime
105 * Revision 1.31 2001/02/22 23:31:42 robertj
106 * Fixed display of version number just added.
108 * Revision 1.30 2001/02/22 22:31:01 robertj
109 * Added command line flag to display version number only.
111 * Revision 1.29 2000/10/12 23:11:48 robertj
112 * Fixed problem with BER encoding of ASN with optional fields.
114 * Revision 1.28 2000/06/26 13:14:46 robertj
115 * Nucleus++ port.
117 * Revision 1.27 2000/03/21 21:23:23 robertj
118 * Added option to rename imported module names, allows include filename matching.
120 * Revision 1.26 2000/01/19 12:33:07 robertj
121 * Fixed parsing of OID's in IMPORTS section.
123 * Revision 1.25 2000/01/19 03:38:12 robertj
124 * Fixed support for parsing multiple IMPORTS
126 * Revision 1.24 1999/09/18 04:17:40 robertj
127 * Added generation of C++ inlines for some functions.
128 * Optimised CreateObject() switch statements, collapsing common cases.
130 * Revision 1.23 1999/09/18 02:42:27 craigs
131 * Added optimisation to collapse switch arms in CreateObject functions
133 * Revision 1.22 1999/09/07 09:56:04 robertj
134 * Fixed failure to put "using anmespace" in every generated .cxx file.
136 * Revision 1.21 1999/08/28 01:48:55 robertj
137 * Fixed anomaly to always include non-optional extensions in encodings.
139 * Revision 1.20 1999/08/09 13:02:36 robertj
140 * Added ASN compiler #defines for backward support of pre GCC 2.9 compilers.
141 * Added ASN compiler #defines to reduce its memory footprint.
142 * Added ASN compiler code generation of assignment operators for string classes.
144 * Revision 1.19 1999/07/22 06:48:55 robertj
145 * Added comparison operation to base ASN classes and compiled ASN code.
146 * Added support for ANY type in ASN parser.
148 * Revision 1.18 1999/07/06 05:00:26 robertj
149 * Incremented release number
151 * Revision 1.17 1999/07/01 12:21:46 robertj
152 * Changed PASN_Choice cast operators so no longer "break" const-ness of object.
154 * Revision 1.16 1999/06/30 08:57:19 robertj
155 * Fixed bug in encodeing sequence of constrained primitive type. Constraint not set.
156 * Fixed bug in not emitting namespace use clause.
157 * Added "normalisation" of separate sequence of <base type> to be single class.
159 * Revision 1.15 1999/06/14 13:00:15 robertj
160 * Fixed bug in code generation for string constraints.
162 * Revision 1.14 1999/06/09 06:58:09 robertj
163 * Adjusted heading comments.
165 * Revision 1.13 1999/06/09 02:07:49 robertj
166 * Fixed backward compatibility of generated template code with G++ 2.7.x
168 * Revision 1.12 1999/06/07 01:56:25 robertj
169 * Added header comment on license.
173 #include <ptlib.h>
175 #include "main.h"
176 #include "asn_grammar.h"
179 #define MAJOR_VERSION 1
180 #define MINOR_VERSION 9
181 #define BUILD_TYPE ReleaseCode
182 #define BUILD_NUMBER 1
185 unsigned lineNumber;
186 PString fileName;
188 unsigned fatals, warnings;
190 extern FILE * yyin;
191 extern int yydebug;
192 extern int LexEcho;
194 ModuleDefinition * Module;
197 static const char * UniversalTagClassNames[] = {
198 "UniversalTagClass",
199 "ApplicationTagClass",
200 "ContextSpecificTagClass",
201 "PrivateTagClass"
204 static const char * UniversalTagNames[] = {
205 NULL,
206 "UniversalBoolean",
207 "UniversalInteger",
208 "UniversalBitString",
209 "UniversalOctetString",
210 "UniversalNull",
211 "UniversalObjectId",
212 "UniversalObjectDescriptor",
213 "UniversalExternalType",
214 "UniversalReal",
215 "UniversalEnumeration",
216 "UniversalEmbeddedPDV",
217 NULL,
218 NULL,
219 NULL,
220 NULL,
221 "UniversalSequence",
222 "UniversalSet",
223 "UniversalNumericString",
224 "UniversalPrintableString",
225 "UniversalTeletexString",
226 "UniversalVideotexString",
227 "UniversalIA5String",
228 "UniversalUTCTime",
229 "UniversalGeneralisedTime",
230 "UniversalGraphicString",
231 "UniversalVisibleString",
232 "UniversalGeneralString",
233 "UniversalUniversalString",
234 NULL,
235 "UniversalBMPString"
239 static const char * const StandardClasses[] = {
240 "PASN_Null",
241 "PASN_Boolean",
242 "PASN_Integer",
243 "PASN_Enumeration",
244 "PASN_Real",
245 "PASN_ObjectId",
246 "PASN_BitString",
247 "PASN_OctetString",
248 "PASN_NumericString",
249 "PASN_PrintableString",
250 "PASN_VisibleString",
251 "PASN_IA5String",
252 "PASN_GeneralString",
253 "PASN_BMPString",
254 "PASN_Sequence"
258 /////////////////////////////////////////
260 // yyerror
261 // required function for flex
264 void yyerror(char * str)
266 extern char * yytext;
267 PError << StdError(Fatal) << str << " near token \"" << yytext <<"\"\n";
270 ostream & operator<<(ostream & out, const StdError & e)
272 out << fileName << '(' << lineNumber << ") : ";
273 if (e.e == Fatal) {
274 fatals++;
275 out << "error";
277 else {
278 warnings++;
279 out << "warning";
281 return out << ": ";
285 /////////////////////////////////////////////////////////
287 // Utility
290 static PString MakeIdentifierC(const PString & identifier)
292 PString s = identifier;
293 s.Replace("-", "_", TRUE);
294 return s;
298 class OutputFile : public PTextFile
300 PCLASSINFO(OutputFile, PTextFile);
301 public:
302 ~OutputFile() { Close(); }
304 BOOL Open(const PFilePath & path, const PString & suffix, const char * extension);
305 BOOL Close();
309 BOOL OutputFile::Open(const PFilePath & path,
310 const PString & suffix,
311 const char * extension)
313 PFilePath fn = path.GetDirectory() + path.GetTitle() + suffix;
314 fn.SetType(extension);
316 if (PTextFile::Open(fn, WriteOnly))
317 *this << "//\n"
318 "// " << GetFilePath().GetFileName() << "\n"
319 "//\n"
320 "// Code automatically generated by asnparse.\n"
321 "//\n"
322 "\n";
323 else
324 PError << PProcess::Current().GetName() << ": cannot create \""
325 << GetFilePath() << "\" :" << GetErrorText() << endl;
327 return IsOpen();
331 BOOL OutputFile::Close()
333 if (IsOpen())
334 *this << "\n"
335 "// End of " << GetFilePath().GetFileName() << '\n';
337 return PTextFile::Close();
341 /////////////////////////////////////////////////////////
343 // Application
346 class App : public PProcess
348 PCLASSINFO(App, PProcess);
349 public:
350 App();
351 void Main();
352 BOOL SetClassHeaderFile(PArgList & args);
353 BOOL SetClassHeader(PArgList & args);
354 void OutputAdditionalHeaders(ostream & hdr, const PString & className);
355 protected:
356 PStringToString classToHeader;
359 PCREATE_PROCESS(App);
361 App::App()
362 : PProcess("Equivalence", "ASNParse", MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
366 void App::Main()
368 cout << GetName() << " version " << GetVersion(TRUE)
369 << " for " << GetOSClass() << ' ' << GetOSName()
370 << " by " << GetManufacturer() << endl;
372 PArgList & args = GetArguments();
373 args.Parse("c-c++."
374 "d-debug."
375 "e-echo."
376 "h-hdr-prefix:"
377 "i-inlines."
378 "m-module:"
379 "n-namespace."
380 "o-output:"
381 "r-rename:"
382 "s-split;"
383 "V-version."
384 "v-verbose."
385 "x-xml."
386 "-no-operators."
387 "-classheader:"
388 "-classheaderfile:");
390 if (args.HasOption('V'))
391 return;
393 unsigned numFiles = 1;
394 if (args.HasOption('s')) {
395 PString numFilesStr = args.GetOptionString('s');
396 if (numFilesStr.IsEmpty())
397 numFiles = 2;
398 else
399 numFiles = numFilesStr.AsUnsigned();
402 if (args.GetCount() < 1 || args.GetCount() > 1 || numFiles == 0) {
403 PError << "usage: asnparse [options] asnfile\n"
404 " -V --version Display version and exit\n"
405 " -v --verbose Verbose output (multiple times for more verbose)\n"
406 " -e --echo Echo input file\n"
407 " -d --debug Debug output (copious!)\n"
408 " -c --c++ Generate C++ files\n"
409 " -n --namespace Use C++ namespace\n"
410 " -h --hdr-prefix str Prefix for C++ include of header (eg directory)\n"
411 " -i --inlines Use C++ inlines\n"
412 " -s[n] --split[n] Split output into n (default 2) files\n"
413 " -m --module name Module name prefix/namespace\n"
414 " -r --rename args Rename import module where arg is:\n"
415 " from=name[,prefix[,fname]]\n"
416 " from is module name in ASN file\n"
417 " name is target header file name\n"
418 " prefix is optional prefix for include\n"
419 " (eg header directory)\n"
420 " fname is optional base name for header files\n"
421 " --no-operators Generate functions instead of operators for choice\n"
422 " sub-object extraction.\n"
423 " -x --xml X.693 support (XER)\n"
424 " -o --output file Output filename/directory\n"
425 << endl;
426 return;
429 PTextFile prcFile;
430 if (!prcFile.Open(args[0], PFile::ReadOnly)) {
431 PError << GetName() << ": cannot open \""
432 << prcFile.GetFilePath() << "\" :" << prcFile.GetErrorText() << endl;
433 return;
436 if (args.HasOption('d'))
437 yydebug = 1;
438 if (args.HasOption('e'))
439 LexEcho = TRUE;
441 fileName = prcFile.GetFilePath();
442 lineNumber = 1;
443 fatals = 0;
444 warnings = 0;
446 if (args.HasOption("classheaderfile")) {
447 if (!SetClassHeaderFile(args))
448 return;
451 if (args.HasOption("classheader")) {
452 if (!SetClassHeader(args))
453 return;
456 if (args.HasOption('v'))
457 cout << "Parsing..." << endl;
459 yyin = _fdopen(prcFile.GetHandle(), "r");
460 PAssertNULL(yyin);
461 yyparse();
463 if (Module != NULL) {
464 if (args.GetOptionCount('v') > 1)
465 PError << "Module " << *Module << endl;
467 if (args.HasOption('c'))
468 Module->GenerateCplusplus(args.GetOptionString('o', args[0]),
469 args.GetOptionString('m'),
470 args.GetOptionString('h'),
471 numFiles,
472 args.HasOption('n'),
473 args.HasOption('i'),
474 !args.HasOption("no-operators"),
475 args.HasOption('v'));
480 BOOL App::SetClassHeaderFile(PArgList & args)
482 PStringArray lines = args.GetOptionString("classheaderfile").Lines();
483 if (lines.IsEmpty()) {
484 PError << GetName() << ": malformed --classheaderfile option\n";
485 return FALSE;
488 for (PINDEX i = 0; i < lines.GetSize(); i++) {
489 PString str = lines[i];
490 PINDEX pos = str.Find("=");
491 if (pos == P_MAX_INDEX) {
492 PError << GetName() << ": malformed --classheaderfile option\n";
493 return FALSE;
496 PFilePath fn = str.Right(pos+1);
497 PTextFile file(fn, PFile::ReadOnly);
498 if (!file.IsOpen()) {
499 PError << GetName() << ": cannot open file required for --classheaderfile option \"" << fn
500 << "\" :" << file.GetErrorText() << '\n';
501 return FALSE;
504 PString text;
505 PString line;
506 while (file.ReadLine(line))
507 text += PString(PString::Literal, (const char *)line) + '\n';
508 classToHeader.SetAt(str.Left(pos), text);
511 return TRUE;
515 BOOL App::SetClassHeader(PArgList & args)
517 PStringArray lines = args.GetOptionString("classheader").Lines();
518 if (lines.IsEmpty()) {
519 PError << GetName() << ": malformed --classheader option\n";
520 return FALSE;
523 for (PINDEX i = 0; i < lines.GetSize(); i++) {
524 PString str = lines[i];
525 PINDEX pos = str.Find("=");
526 if (pos == P_MAX_INDEX) {
527 PError << GetName() << ": malformed --classheader option\n";
528 return FALSE;
531 PString text(PString::Literal, (const char *)str.Mid(pos+1));
532 classToHeader.SetAt(str.Left(pos), text);
535 return TRUE;
539 void App::OutputAdditionalHeaders(ostream & hdr, const PString & className)
541 if (classToHeader.Contains(className)) {
542 hdr << "// following code added by command line option\n"
543 "\n"
544 << classToHeader[className] << "\n"
545 "\n"
546 "// end of added code\n"
547 "\n";
551 /////////////////////////////////////////
553 // miscellaneous
556 class indent
558 public:
559 indent() { }
560 friend ostream & operator<<(ostream & s, const indent &)
561 { return s << setw(Module->GetIndentLevel()*3) << ' '; }
565 /////////////////////////////////////////
567 // intermediate structures from parser
570 NamedNumber::NamedNumber(PString * nam)
571 : name(*nam)
573 delete nam;
574 number = 0;
575 autonumber = TRUE;
579 NamedNumber::NamedNumber(PString * nam, int num)
580 : name(*nam)
582 delete nam;
583 number = num;
584 autonumber = FALSE;
588 NamedNumber::NamedNumber(PString * nam, const PString & ref)
589 : name(*nam), reference(ref)
591 delete nam;
592 number = 0;
593 autonumber = FALSE;
597 void NamedNumber::PrintOn(ostream & strm) const
599 strm << name << " (";
600 if (reference.IsEmpty())
601 strm << number;
602 else
603 strm << reference;
604 strm << ')';
608 void NamedNumber::SetAutoNumber(const NamedNumber & prev)
610 if (autonumber) {
611 number = prev.number + 1;
612 autonumber = FALSE;
617 /////////////////////////////////////////////////////////
619 Tag::Tag(unsigned tagNum)
621 type = Universal;
622 number = tagNum;
623 mode = Module->GetDefaultTagMode();
627 const char * Tag::classNames[] = {
628 "UNIVERSAL", "APPLICATION", "CONTEXTSPECIFIC", "PRIVATE"
632 const char * Tag::modeNames[] = {
633 "IMPLICIT", "EXPLICIT", "AUTOMATIC"
637 void Tag::PrintOn(ostream & strm) const
639 if (type != Universal || number != IllegalUniversalTag) {
640 strm << '[';
641 if (type != ContextSpecific)
642 strm << classNames[type] << ' ';
643 strm << number << "] " << modeNames[mode] << ' ';
648 /////////////////////////////////////////////////////////
650 Constraint::Constraint(ConstraintElementBase * elmt)
652 standard.Append(elmt);
653 extendable = FALSE;
657 Constraint::Constraint(ConstraintElementList * stnd, BOOL extend, ConstraintElementList * ext)
659 if (stnd != NULL) {
660 standard = *stnd;
661 delete stnd;
663 extendable = extend;
664 if (ext != NULL) {
665 extensions = *ext;
666 delete ext;
671 void Constraint::PrintOn(ostream & strm) const
673 strm << '(';
674 for (PINDEX i = 0; i < standard.GetSize(); i++)
675 strm << standard[i];
676 if (extendable) {
677 strm << indent();
678 if (standard.GetSize() > 0)
679 strm << ", ";
680 strm << "..., ";
681 for (PINDEX i = 0; i < extensions.GetSize(); i++)
682 strm << extensions[i];
684 strm << ')';
688 void Constraint::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
690 switch (standard.GetSize()) {
691 case 0 :
692 return;
693 case 1 :
694 break;
695 default :
696 PError << StdError(Warning) << "unsupported UNION constraints, ignored." << endl;
699 if (extensions.GetSize() > 0)
700 PError << StdError(Warning) << "unsupported extension constraints, ignored." << endl;
702 PString fn2 = fn;
703 if (fn.Find("PASN_Object::") == P_MAX_INDEX) {
704 if (extendable)
705 fn2 += "PASN_Object::ExtendableConstraint";
706 else
707 fn2 += "PASN_Object::FixedConstraint";
710 standard[0].GenerateCplusplus(fn2, hdr, cxx);
714 BOOL Constraint::ReferencesType(const TypeBase & type)
716 PINDEX i;
718 for (i = 0; i < standard.GetSize(); i++) {
719 if (standard[i].ReferencesType(type))
720 return TRUE;
723 for (i = 0; i < extensions.GetSize(); i++) {
724 if (extensions[i].ReferencesType(type))
725 return TRUE;
728 return FALSE;
732 /////////////////////////////////////////////////////////
734 ConstraintElementBase::ConstraintElementBase()
736 exclusions = NULL;
740 void ConstraintElementBase::GenerateCplusplus(const PString &, ostream &, ostream &)
742 PError << StdError(Warning) << "unsupported constraint, ignored." << endl;
746 BOOL ConstraintElementBase::ReferencesType(const TypeBase &)
748 return FALSE;
752 /////////////////////////////////////////////////////////
754 ConstrainAllConstraintElement::ConstrainAllConstraintElement(ConstraintElementBase * excl)
756 SetExclusions(excl);
760 /////////////////////////////////////////////////////////
762 ElementListConstraintElement::ElementListConstraintElement(ConstraintElementList * list)
763 : elements(*list)
765 delete list;
769 void ElementListConstraintElement::PrintOn(ostream & strm) const
771 elements.PrintOn(strm);
775 void ElementListConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
777 for (PINDEX i = 0; i < elements.GetSize(); i++)
778 elements[i].GenerateCplusplus(fn, hdr, cxx);
782 BOOL ElementListConstraintElement::ReferencesType(const TypeBase & type)
784 for (PINDEX i = 0; i < elements.GetSize(); i++) {
785 if (elements[i].ReferencesType(type))
786 return TRUE;
788 return FALSE;
792 /////////////////////////////////////////////////////////
794 SingleValueConstraintElement::SingleValueConstraintElement(ValueBase * val)
796 value = val;
800 SingleValueConstraintElement::~SingleValueConstraintElement()
802 delete value;
806 void SingleValueConstraintElement::PrintOn(ostream & strm) const
808 strm << *value;
812 void SingleValueConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
814 cxx << fn << ", ";
815 value->GenerateCplusplus(hdr, cxx);
816 cxx << ");\n";
820 /////////////////////////////////////////////////////////
822 ValueRangeConstraintElement::ValueRangeConstraintElement(ValueBase * lowerBound, ValueBase * upperBound)
824 lower = lowerBound;
825 upper = upperBound;
829 ValueRangeConstraintElement::~ValueRangeConstraintElement()
831 delete lower;
832 delete upper;
836 void ValueRangeConstraintElement::PrintOn(ostream & strm) const
838 strm << *lower << ".." << *upper;
842 void ValueRangeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
844 cxx << fn << ", ";
845 lower->GenerateCplusplus(hdr, cxx);
846 cxx << ", ";
847 upper->GenerateCplusplus(hdr, cxx);
848 cxx << ");\n";
852 /////////////////////////////////////////////////////////
854 SubTypeConstraintElement::SubTypeConstraintElement(TypeBase * typ)
856 subtype = typ;
860 SubTypeConstraintElement::~SubTypeConstraintElement()
862 delete subtype;
866 void SubTypeConstraintElement::PrintOn(ostream & strm) const
868 strm << subtype->GetTypeName();
872 void SubTypeConstraintElement::GenerateCplusplus(const PString &, ostream & hdr, ostream &)
874 hdr << subtype->GetTypeName();
878 BOOL SubTypeConstraintElement::ReferencesType(const TypeBase & type)
880 return subtype->ReferencesType(type);
884 /////////////////////////////////////////////////////////
886 NestedConstraintConstraintElement::NestedConstraintConstraintElement(Constraint * con)
888 constraint = con;
892 NestedConstraintConstraintElement::~NestedConstraintConstraintElement()
894 delete constraint;
898 BOOL NestedConstraintConstraintElement::ReferencesType(const TypeBase & type)
900 if (constraint == NULL)
901 return FALSE;
903 return constraint->ReferencesType(type);
907 /////////////////////////////////////////////////////////
909 SizeConstraintElement::SizeConstraintElement(Constraint * constraint)
910 : NestedConstraintConstraintElement(constraint)
915 void SizeConstraintElement::PrintOn(ostream & strm) const
917 strm << "SIZE" << *constraint;
921 void SizeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
923 constraint->GenerateCplusplus(fn, hdr, cxx);
927 /////////////////////////////////////////////////////////
929 FromConstraintElement::FromConstraintElement(Constraint * constraint)
930 : NestedConstraintConstraintElement(constraint)
935 void FromConstraintElement::PrintOn(ostream & strm) const
937 strm << "FROM" << *constraint;
941 void FromConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
943 PString newfn = fn;
944 newfn.Replace("SetConstraints(", "SetCharacterSet(");
945 constraint->GenerateCplusplus(newfn, hdr, cxx);
949 /////////////////////////////////////////////////////////
951 WithComponentConstraintElement::WithComponentConstraintElement(PString * newName,
952 Constraint * constraint,
953 int pres)
954 : NestedConstraintConstraintElement(constraint)
956 if (newName != NULL) {
957 name = *newName;
958 delete newName;
961 presence = pres;
965 void WithComponentConstraintElement::PrintOn(ostream & strm) const
967 if (name.IsEmpty())
968 strm << "WITH COMPONENT";
969 else
970 strm << name;
972 if (constraint != NULL)
973 strm << *constraint;
975 switch (presence) {
976 case Present :
977 strm << " PRESENT";
978 break;
979 case Absent :
980 strm << " ABSENT";
981 break;
982 case Optional :
983 strm << " OPTIONAL";
984 break;
989 void WithComponentConstraintElement::GenerateCplusplus(const PString &, ostream &, ostream & cxx)
991 if (presence == Present)
992 cxx << " IncludeOptionalField(e_" << name << ");\n";
996 /////////////////////////////////////////////////////////
998 InnerTypeConstraintElement::InnerTypeConstraintElement(ConstraintElementList * list,
999 BOOL part)
1000 : ElementListConstraintElement(list)
1002 partial = part;
1006 void InnerTypeConstraintElement::PrintOn(ostream & strm) const
1008 strm << "WITH COMPONENTS { ";
1010 if (partial)
1011 strm << "..., ";
1013 for (PINDEX i = 0; i < elements.GetSize(); i++) {
1014 if (i > 0)
1015 strm << ", ";
1016 elements[i].PrintOn(strm);
1019 strm << " }";
1023 void InnerTypeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
1025 for (PINDEX i = 0; i < elements.GetSize(); i++)
1026 elements[i].GenerateCplusplus(fn, hdr, cxx);
1030 /////////////////////////////////////////////////////////
1032 UserDefinedConstraintElement::UserDefinedConstraintElement(TypesList * t)
1034 if (t != NULL) {
1035 types = *t;
1036 delete t;
1041 void UserDefinedConstraintElement::PrintOn(ostream & strm) const
1043 strm << "CONSTRAINED BY { ";
1044 for (PINDEX i = 0; i < types.GetSize(); i++) {
1045 if (i > 0)
1046 strm << ", ";
1047 strm << types[i].GetTypeName();
1049 strm << " }";
1053 void UserDefinedConstraintElement::GenerateCplusplus(const PString &, ostream &, ostream &)
1058 /////////////////////////////////////////////////////////
1060 TypeBase::TypeBase(unsigned tagNum)
1061 : tag(tagNum), defaultTag(tagNum)
1063 isOptional = FALSE;
1064 defaultValue = NULL;
1065 isGenerated = FALSE;
1069 TypeBase::TypeBase(TypeBase * copy)
1070 : name(copy->name),
1071 identifier(MakeIdentifierC(name)),
1072 tag(copy->tag),
1073 defaultTag(copy->tag)
1075 isOptional = copy->isOptional;
1076 defaultValue = NULL;
1077 isGenerated = FALSE;
1081 PObject::Comparison TypeBase::Compare(const PObject & obj) const
1083 return name.Compare(((const TypeBase &)obj).name);
1087 void TypeBase::PrintOn(ostream & strm) const
1089 PrintStart(strm);
1090 PrintFinish(strm);
1094 void TypeBase::PrintStart(ostream & strm) const
1096 strm << indent();
1097 if (!name) {
1098 strm << name;
1099 if (!parameters.IsEmpty()) {
1100 strm << " { ";
1101 for (PINDEX i = 0; i < parameters.GetSize(); i++) {
1102 if (i > 0)
1103 strm << ", ";
1104 strm << parameters[i];
1106 strm << " } ";
1108 strm << ": ";
1110 strm << tag << GetClass() << ' ';
1111 Module->SetIndentLevel(1);
1115 void TypeBase::PrintFinish(ostream & strm) const
1117 Module->SetIndentLevel(-1);
1118 strm << ' ' << constraints;
1119 if (isOptional)
1120 strm << " OPTIONAL";
1121 if (defaultValue != NULL)
1122 strm << " DEFAULT " << *defaultValue;
1123 strm << '\n';
1127 int TypeBase::GetIdentifierTokenContext() const
1129 return IDENTIFIER;
1133 int TypeBase::GetBraceTokenContext() const
1135 return '{';
1139 void TypeBase::SetName(PString * newName)
1141 name = *newName;
1142 delete newName;
1143 identifier = MakeIdentifierC(name);
1147 void TypeBase::AdjustIdentifier()
1149 identifier = Module->GetPrefix() + MakeIdentifierC(name);
1153 void TypeBase::SetTag(Tag::Type type, unsigned num, Tag::Mode mode)
1155 tag.type = type;
1156 tag.number = num;
1157 tag.mode = mode;
1161 void TypeBase::SetParameters(PStringList * list)
1163 parameters = *list;
1164 delete list;
1168 void TypeBase::MoveConstraints(TypeBase * from)
1170 from->constraints.DisallowDeleteObjects();
1172 while (!from->constraints.IsEmpty())
1173 constraints.Append(from->constraints.RemoveAt(0));
1175 from->constraints.AllowDeleteObjects();
1179 void TypeBase::FlattenUsedTypes()
1184 TypeBase * TypeBase::FlattenThisType(const TypeBase &)
1186 return this;
1190 BOOL TypeBase::IsChoice() const
1192 return FALSE;
1196 BOOL TypeBase::IsParameterizedType() const
1198 return FALSE;
1202 BOOL TypeBase::IsPrimitiveType() const
1204 return TRUE;
1208 void TypeBase::GenerateCplusplus(ostream & hdr, ostream & cxx)
1210 BeginGenerateCplusplus(hdr, cxx);
1212 // Close off the constructor implementation
1213 cxx << ")\n"
1214 "{\n";
1215 GenerateCplusplusConstraints(PString(), hdr, cxx);
1217 EndGenerateCplusplus(hdr, cxx);
1221 void TypeBase::GenerateForwardDecls(ostream &)
1226 void TypeBase::GenerateOperators(ostream &, ostream &, const TypeBase &)
1231 PString TypeBase::GetTypeName() const
1233 return GetAncestorClass();
1237 BOOL TypeBase::CanReferenceType() const
1239 return FALSE;
1243 BOOL TypeBase::ReferencesType(const TypeBase &)
1245 return FALSE;
1249 void TypeBase::SetImportPrefix(const PString &)
1254 BOOL TypeBase::IsParameterisedImport() const
1256 return FALSE;
1260 void TypeBase::BeginGenerateCplusplus(ostream & hdr, ostream & cxx)
1262 classNameString = GetIdentifier();
1264 if (!parameters.IsEmpty()) {
1265 templatePrefix = "template <";
1266 classNameString += '<';
1267 for (PINDEX i = 0; i < parameters.GetSize(); i++) {
1268 if (i > 0) {
1269 templatePrefix += ", ";
1270 classNameString += ", ";
1272 PString ident = MakeIdentifierC(parameters[i]);
1273 templatePrefix += "class " + ident;
1274 classNameString += ident;
1276 templatePrefix += ">\n";
1277 classNameString += '>';
1280 // Output header file declaration of class
1281 hdr << "//\n"
1282 "// " << GetName() << "\n"
1283 "//\n"
1284 "\n";
1285 GenerateForwardDecls(hdr);
1286 hdr << templatePrefix
1287 << "class " << GetIdentifier() << " : public " << GetTypeName() << "\n"
1288 "{\n"
1289 "#ifndef PASN_LEANANDMEAN\n"
1290 " PCLASSINFO(" << GetIdentifier() << ", " << GetTypeName() << ");\n"
1291 "#endif\n"
1292 " public:\n"
1293 " " << GetIdentifier() << "(unsigned tag = ";
1294 if (tag.type == Tag::Universal &&
1295 tag.number < PARRAYSIZE(UniversalTagNames) &&
1296 UniversalTagNames[tag.number] != NULL)
1297 hdr << UniversalTagNames[tag.number];
1298 else
1299 hdr << tag.number;
1300 hdr << ", TagClass tagClass = " << UniversalTagClassNames[tag.type] << ");\n\n";
1302 App & app = (App &)PProcess::Current();
1303 app.OutputAdditionalHeaders(hdr, GetIdentifier());
1305 // Output cxx file implementation of class
1306 cxx << "//\n"
1307 "// " << GetName() << "\n"
1308 "//\n"
1309 "\n"
1310 << GetTemplatePrefix()
1311 << GetClassNameString() << "::" << GetIdentifier() << "(unsigned tag, PASN_Object::TagClass tagClass)\n"
1312 " : " << GetTypeName() << "(tag, tagClass";
1316 void TypeBase::EndGenerateCplusplus(ostream & hdr, ostream & cxx)
1318 cxx << "}\n"
1319 "\n"
1320 "\n";
1322 GenerateOperators(hdr, cxx, *this);
1324 // Output header file declaration of class
1325 hdr << " PObject * Clone() const;\n"
1326 "};\n"
1327 "\n"
1328 "\n";
1330 // Output cxx file implementation of class
1331 cxx << GetTemplatePrefix()
1332 << "PObject * " << GetClassNameString() << "::Clone() const\n"
1333 "{\n"
1334 "#ifndef PASN_LEANANDMEAN\n"
1335 " PAssert(IsClass(" << GetClassNameString() << "::Class()), PInvalidCast);\n"
1336 "#endif\n"
1337 " return new " << GetClassNameString() << "(*this);\n"
1338 "}\n"
1339 "\n"
1340 "\n";
1342 isGenerated = TRUE;
1346 void TypeBase::GenerateCplusplusConstructor(ostream &, ostream & cxx)
1348 cxx << '(';
1349 if (HasNonStandardTag()) {
1350 if (tag.type == Tag::Universal &&
1351 tag.number < PARRAYSIZE(UniversalTagNames) &&
1352 UniversalTagNames[tag.number] != NULL)
1353 cxx << UniversalTagNames[tag.number];
1354 else
1355 cxx << tag.number;
1356 cxx << ", " << UniversalTagClassNames[tag.type];
1358 cxx << ')';
1362 void TypeBase::GenerateCplusplusConstraints(const PString & prefix, ostream & hdr, ostream & cxx)
1364 for (PINDEX i = 0; i < constraints.GetSize(); i++)
1365 constraints[i].GenerateCplusplus(" " + prefix + "SetConstraints(", hdr, cxx);
1369 /////////////////////////////////////////////////////////
1371 DefinedType::DefinedType(PString * name, BOOL parameter)
1372 : TypeBase(Tag::IllegalUniversalTag),
1373 referenceName(*name)
1375 delete name;
1376 baseType = NULL;
1377 unresolved = !parameter;
1381 DefinedType::DefinedType(TypeBase * refType, TypeBase * bType)
1382 : TypeBase(refType),
1383 referenceName(bType->GetName())
1385 MoveConstraints(refType);
1387 baseType = bType;
1388 unresolved = FALSE;
1392 DefinedType::DefinedType(TypeBase * refType, const PString & refName)
1393 : TypeBase(refType)
1395 MoveConstraints(refType);
1396 ConstructFromType(refType, refName);
1400 DefinedType::DefinedType(TypeBase * refType, const TypeBase & parent)
1401 : TypeBase(refType)
1403 if (!name)
1404 ConstructFromType(refType, parent.GetName() + '_' + name);
1405 else
1406 ConstructFromType(refType, parent.GetName() + "_subtype");
1410 void DefinedType::ConstructFromType(TypeBase * refType, const PString & name)
1412 referenceName = name;
1413 refType->SetName(new PString(name));
1415 Module->AppendType(refType);
1417 baseType = refType;
1418 unresolved = FALSE;
1422 void DefinedType::PrintOn(ostream & strm) const
1424 PrintStart(strm);
1425 strm << referenceName << ' ';
1426 PrintFinish(strm);
1430 BOOL DefinedType::CanReferenceType() const
1432 return TRUE;
1436 BOOL DefinedType::IsChoice() const
1438 if (baseType != NULL)
1439 return baseType->IsChoice();
1440 return FALSE;
1444 BOOL DefinedType::IsParameterizedType() const
1446 if (baseType != NULL)
1447 return baseType->IsParameterizedType();
1448 return FALSE;
1452 BOOL DefinedType::ReferencesType(const TypeBase & type)
1454 if (unresolved) {
1455 unresolved = FALSE;
1457 if ((baseType = Module->FindType(referenceName)) == NULL)
1458 PError << StdError(Warning) << "unresolved symbol: " << referenceName << endl;
1459 else {
1460 if (!HasNonStandardTag())
1461 defaultTag = tag = baseType->GetTag();
1465 return type.GetName() == referenceName;
1469 void DefinedType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1471 if (baseType != NULL)
1472 baseType->GenerateOperators(hdr, cxx, actualType);
1476 const char * DefinedType::GetAncestorClass() const
1478 if (baseType != NULL)
1479 return baseType->GetAncestorClass();
1480 return NULL;
1484 PString DefinedType::GetTypeName() const
1486 if (baseType == NULL)
1487 return referenceName;
1489 if (HasConstraints() && baseType->IsPrimitiveType())
1490 return baseType->GetTypeName();
1492 return baseType->GetIdentifier();
1496 /////////////////////////////////////////////////////////
1498 ParameterizedType::ParameterizedType(PString * name, TypesList * args)
1499 : DefinedType(name, FALSE),
1500 arguments(*args)
1502 delete args;
1506 void ParameterizedType::PrintOn(ostream & strm) const
1508 PrintStart(strm);
1509 strm << referenceName << " { ";
1510 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1511 if (i > 0)
1512 strm << ", ";
1513 strm << arguments[i].GetTypeName();
1515 strm << " }";
1516 PrintFinish(strm);
1520 BOOL ParameterizedType::IsParameterizedType() const
1522 return TRUE;
1526 BOOL ParameterizedType::ReferencesType(const TypeBase & type)
1528 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1529 if (arguments[i].ReferencesType(type))
1530 return TRUE;
1533 return DefinedType::ReferencesType(type);
1537 PString ParameterizedType::GetTypeName() const
1539 PString typeName = DefinedType::GetTypeName();
1540 if (!arguments.IsEmpty()) {
1541 typeName += '<';
1542 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1543 if (i > 0)
1544 typeName += ", ";
1545 typeName += arguments[i].GetTypeName();
1547 typeName += '>';
1549 return typeName;
1553 /////////////////////////////////////////////////////////
1555 SelectionType::SelectionType(PString * name, TypeBase * base)
1556 : TypeBase(Tag::IllegalUniversalTag),
1557 selection(*name)
1559 delete name;
1560 baseType = PAssertNULL(base);
1564 SelectionType::~SelectionType()
1566 delete baseType;
1570 void SelectionType::PrintOn(ostream & strm) const
1572 PrintStart(strm);
1573 strm << selection << '<' << *baseType;
1574 PrintFinish(strm);
1578 void SelectionType::FlattenUsedTypes()
1580 baseType = baseType->FlattenThisType(*this);
1584 TypeBase * SelectionType::FlattenThisType(const TypeBase & parent)
1586 return new DefinedType(this, parent);
1590 void SelectionType::GenerateCplusplus(ostream &, ostream &)
1592 PError << StdError(Fatal) << "Cannot generate code for Selection type" << endl;
1593 isGenerated = TRUE;
1597 const char * SelectionType::GetAncestorClass() const
1599 return "";
1603 BOOL SelectionType::CanReferenceType() const
1605 return TRUE;
1609 BOOL SelectionType::ReferencesType(const TypeBase & type)
1611 return baseType->ReferencesType(type);
1615 /////////////////////////////////////////////////////////
1617 BooleanType::BooleanType()
1618 : TypeBase(Tag::UniversalBoolean)
1623 void BooleanType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1625 hdr << " " << actualType.GetIdentifier() << " & operator=(BOOL v)";
1626 if (Module->UsingInlines())
1627 hdr << " { SetValue(v); return *this; }\n";
1628 else {
1629 hdr << ";\n";
1630 cxx << actualType.GetTemplatePrefix()
1631 << actualType.GetIdentifier() << " & "
1632 << actualType.GetClassNameString() << "::operator=(BOOL v)\n"
1633 "{\n"
1634 " SetValue(v);\n"
1635 " return *this;\n"
1636 "}\n"
1637 "\n"
1638 "\n";
1643 const char * BooleanType::GetAncestorClass() const
1645 return "PASN_Boolean";
1649 /////////////////////////////////////////////////////////
1651 IntegerType::IntegerType()
1652 : TypeBase(Tag::UniversalInteger)
1657 IntegerType::IntegerType(NamedNumberList * lst)
1658 : TypeBase(Tag::UniversalInteger),
1659 allowedValues(*lst)
1661 delete lst;
1665 void IntegerType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1667 hdr << " " << actualType.GetIdentifier() << " & operator=(int v)";
1668 if (Module->UsingInlines())
1669 hdr << " { SetValue(v); return *this; }\n";
1670 else {
1671 hdr << ";\n";
1672 cxx << actualType.GetTemplatePrefix()
1673 << actualType.GetIdentifier() << " & "
1674 << actualType.GetClassNameString() << "::operator=(int v)\n"
1675 "{\n"
1676 " SetValue(v);\n"
1677 " return *this;\n"
1678 "}\n"
1679 "\n"
1680 "\n";
1683 hdr << " " << actualType.GetIdentifier() << " & operator=(unsigned v)";
1684 if (Module->UsingInlines())
1685 hdr << " { SetValue(v); return *this; }\n";
1686 else {
1687 hdr << ";\n";
1688 cxx << actualType.GetTemplatePrefix()
1689 << actualType.GetIdentifier() << " & "
1690 << actualType.GetClassNameString() << "::operator=(unsigned v)\n"
1691 "{\n"
1692 " SetValue(v);\n"
1693 " return *this;\n"
1694 "}\n"
1695 "\n"
1696 "\n";
1701 const char * IntegerType::GetAncestorClass() const
1703 return "PASN_Integer";
1707 /////////////////////////////////////////////////////////
1709 EnumeratedType::EnumeratedType(NamedNumberList * enums, BOOL extend, NamedNumberList * ext)
1710 : TypeBase(Tag::UniversalEnumeration),
1711 enumerations(*enums)
1713 numEnums = enums->GetSize();
1714 delete enums;
1715 extendable = extend;
1716 if (ext != NULL) {
1717 ext->DisallowDeleteObjects();
1718 for (PINDEX i = 0; i < ext->GetSize(); i++)
1719 enumerations.Append(ext->GetAt(i));
1720 delete ext;
1725 void EnumeratedType::PrintOn(ostream & strm) const
1727 PrintStart(strm);
1728 strm << '\n';
1729 PINDEX i;
1730 for (i = 0; i < numEnums; i++)
1731 strm << indent() << enumerations[i] << '\n';
1732 if (extendable) {
1733 strm << "...\n";
1734 for (; i < enumerations.GetSize(); i++)
1735 strm << indent() << enumerations[i] << '\n';
1737 PrintFinish(strm);
1741 TypeBase * EnumeratedType::FlattenThisType(const TypeBase & parent)
1743 return new DefinedType(this, parent);
1747 void EnumeratedType::GenerateCplusplus(ostream & hdr, ostream & cxx)
1749 PINDEX i;
1750 PArgList & args = PProcess::Current().GetArguments();
1751 BOOL xml_output = args.HasOption('x');
1753 BeginGenerateCplusplus(hdr, cxx);
1755 int maxEnumValue = 0;
1756 for (i = 0; i < enumerations.GetSize(); i++) {
1757 int num = enumerations[i].GetNumber();
1758 if (maxEnumValue < num)
1759 maxEnumValue = num;
1762 // Generate enumerations and complete the constructor implementation
1763 hdr << " enum Enumerations {\n";
1764 cxx << ", " << maxEnumValue << ", " << (extendable ? "TRUE" : "FALSE") << "\n"
1765 "#ifndef PASN_NOPRINTON\n"
1766 " , \"";
1768 int prevNum = -1;
1769 for (i = 0; i < enumerations.GetSize(); i++) {
1770 if (i > 0) {
1771 hdr << ",\n";
1772 cxx << " \"";
1775 hdr << " e_" << MakeIdentifierC(enumerations[i].GetName());
1776 cxx << enumerations[i].GetName();
1778 int num = enumerations[i].GetNumber();
1779 if (num != prevNum+1) {
1780 hdr << " = " << num;
1781 cxx << '=' << num;
1783 prevNum = num;
1785 cxx << " \"\n";
1788 hdr << "\n"
1789 " };\n"
1790 "\n";
1791 cxx << "#endif\n"
1792 " )\n"
1793 "{\n";
1794 GenerateCplusplusConstraints(PString(), hdr, cxx);
1796 if (xml_output)
1798 hdr << " BOOL DecodeXER(PXER_Stream & strm);\n"
1799 " void EncodeXER(PXER_Stream & strm) const;\n";
1801 cxx << "}\n"
1802 "\n"
1803 << GetTemplatePrefix()
1804 << "BOOL " << GetClassNameString() << "::DecodeXER(PXER_Stream & strm)\n"
1805 "{\n"
1806 " PXMLElement * elem = strm.GetCurrentElement();\n"
1807 " PXMLObject * sub_elem = elem->GetElement();\n"
1808 "\n"
1809 " if (!elem || !elem->IsElement())\n"
1810 " return FALSE;\n"
1811 "\n"
1812 " PCaselessString id = ((PXMLElement *)sub_elem)->GetName();\n"
1813 "\n"
1814 " ";
1816 for (i = 0 ; i < enumerations.GetSize() ; i++) {
1817 cxx << " if (id == \"" << enumerations[i].GetName() << "\") {\n"
1818 " value = " << enumerations[i].GetNumber() << ";\n"
1819 " return TRUE;\n"
1820 " }\n"
1821 " else";
1824 cxx << "\n"
1825 " return FALSE;\n"
1826 "}\n"
1827 "\n";
1829 cxx << GetTemplatePrefix()
1830 << "void " << GetClassNameString() << "::EncodeXER(PXER_Stream & strm) const\n"
1831 "{\n"
1832 " PXMLElement * elem = strm.GetCurrentElement();\n"
1833 " PString id;\n"
1834 "\n"
1835 " switch(value)\n"
1836 " {\n";
1838 for (i = 0 ; i < enumerations.GetSize() ; i++) {
1839 cxx << " case " << enumerations[i].GetNumber() << ":\n"
1840 " elem->AddChild(new PXMLElement(elem, \"" << enumerations[i].GetName() << "\"));\n"
1841 " break;\n";
1844 cxx << " default:\n"
1845 " break;\n"
1846 " }\n";
1849 EndGenerateCplusplus(hdr, cxx);
1853 void EnumeratedType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1855 hdr << " " << actualType.GetIdentifier() << " & operator=(unsigned v)";
1856 if (Module->UsingInlines())
1857 hdr << " { SetValue(v); return *this; }\n";
1858 else {
1859 hdr << ";\n";
1860 cxx << actualType.GetTemplatePrefix()
1861 << actualType.GetIdentifier() << " & "
1862 << actualType.GetClassNameString() << "::operator=(unsigned v)\n"
1863 "{\n"
1864 " SetValue(v);\n"
1865 " return *this;\n"
1866 "}\n"
1867 "\n"
1868 "\n";
1873 const char * EnumeratedType::GetAncestorClass() const
1875 return "PASN_Enumeration";
1879 /////////////////////////////////////////////////////////
1881 RealType::RealType()
1882 : TypeBase(Tag::UniversalReal)
1887 const char * RealType::GetAncestorClass() const
1889 return "PASN_Real";
1893 /////////////////////////////////////////////////////////
1895 BitStringType::BitStringType()
1896 : TypeBase(Tag::UniversalBitString)
1901 BitStringType::BitStringType(NamedNumberList * lst)
1902 : TypeBase(Tag::UniversalBitString),
1903 allowedBits(*lst)
1905 delete lst;
1908 int BitStringType::GetIdentifierTokenContext() const
1910 return OID_IDENTIFIER;
1914 int BitStringType::GetBraceTokenContext() const
1916 return BITSTRING_BRACE;
1920 const char * BitStringType::GetAncestorClass() const
1922 return "PASN_BitString";
1926 /////////////////////////////////////////////////////////
1928 OctetStringType::OctetStringType()
1929 : TypeBase(Tag::UniversalOctetString)
1934 void OctetStringType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1936 static const char * const types[] = {
1937 "char *", "PString &", "PBYTEArray &"
1940 PINDEX i;
1941 for (i = 0; i < PARRAYSIZE(types); i++) {
1942 hdr << " " << actualType.GetIdentifier() << "(const " << types[i] << " v)";
1943 if (Module->UsingInlines())
1944 hdr << " { SetValue(v); }\n";
1945 else {
1946 hdr << ";\n";
1947 cxx << actualType.GetTemplatePrefix()
1948 << actualType.GetIdentifier() << "::" << actualType.GetIdentifier() << "(const " << types[i] << " v)\n"
1949 "{\n"
1950 " SetValue(v);\n"
1951 "}\n"
1952 "\n"
1953 "\n";
1957 hdr << '\n';
1959 for (i = 0; i < PARRAYSIZE(types); i++) {
1960 hdr << " " << actualType.GetIdentifier() << " & operator=(const " << types[i] << " v)";
1961 if (Module->UsingInlines())
1962 hdr << " { SetValue(v); return *this; }\n";
1963 else {
1964 hdr << ";\n";
1965 cxx << actualType.GetTemplatePrefix()
1966 << actualType.GetIdentifier() << " & "
1967 << actualType.GetClassNameString() << "::operator=(const " << types[i] << " v)\n"
1968 "{\n"
1969 " SetValue(v);\n"
1970 " return *this;\n"
1971 "}\n"
1972 "\n"
1973 "\n";
1979 const char * OctetStringType::GetAncestorClass() const
1981 return "PASN_OctetString";
1985 /////////////////////////////////////////////////////////
1987 NullType::NullType()
1988 : TypeBase(Tag::UniversalNull)
1993 const char * NullType::GetAncestorClass() const
1995 return "PASN_Null";
1999 /////////////////////////////////////////////////////////
2001 SequenceType::SequenceType(TypesList * stnd,
2002 BOOL extend,
2003 TypesList * ext,
2004 unsigned tagNum)
2005 : TypeBase(tagNum)
2007 if (stnd != NULL) {
2008 numFields = stnd->GetSize();
2009 fields = *stnd;
2010 delete stnd;
2012 else
2013 numFields = 0;
2014 extendable = extend;
2015 if (ext != NULL) {
2016 ext->DisallowDeleteObjects();
2017 for (PINDEX i = 0; i < ext->GetSize(); i++)
2018 fields.Append(ext->GetAt(i));
2019 delete ext;
2024 void SequenceType::PrintOn(ostream & strm) const
2026 PrintStart(strm);
2027 strm << '\n';
2028 PINDEX i;
2029 for (i = 0; i < numFields; i++)
2030 strm << fields[i];
2031 if (extendable) {
2032 strm << indent() << "...\n";
2033 for (; i < fields.GetSize(); i++)
2034 strm << fields[i];
2036 PrintFinish(strm);
2040 void SequenceType::FlattenUsedTypes()
2042 for (PINDEX i = 0; i < fields.GetSize(); i++)
2043 fields.SetAt(i, fields[i].FlattenThisType(*this));
2047 TypeBase * SequenceType::FlattenThisType(const TypeBase & parent)
2049 return new DefinedType(this, parent);
2053 BOOL SequenceType::IsPrimitiveType() const
2055 return FALSE;
2059 void SequenceType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2061 PArgList & args = PProcess::Current().GetArguments();
2062 BOOL xml_output = args.HasOption('x');
2064 PINDEX i;
2066 BeginGenerateCplusplus(hdr, cxx);
2068 PINDEX baseOptions = 0;
2069 for (i = 0; i < fields.GetSize(); i++) {
2070 if (i < numFields && fields[i].IsOptional())
2071 baseOptions++;
2074 // Complete ancestor constructor parameters
2075 cxx << ", " << baseOptions << ", "
2076 << (extendable ? "TRUE" : "FALSE") << ", "
2077 << fields.GetSize() - numFields
2078 << ')';
2080 // Output enum for optional parameters
2081 BOOL outputEnum = FALSE;
2082 for (i = 0; i < fields.GetSize(); i++) {
2083 if (i >= numFields || fields[i].IsOptional()) {
2084 if (outputEnum)
2085 hdr << ",\n";
2086 else {
2087 hdr << " enum OptionalFields {\n";
2088 outputEnum = TRUE;
2090 hdr << " e_" << fields[i].GetIdentifier();
2094 if (outputEnum)
2095 hdr << "\n"
2096 " };\n"
2097 "\n";
2099 // Output the declarations and constructors for member variables
2100 for (i = 0; i < fields.GetSize(); i++) {
2101 PString varname = "m_" + fields[i].GetIdentifier();
2102 hdr << " " << fields[i].GetTypeName() << ' ' << varname << ";\n";
2103 if (fields[i].HasNonStandardTag()) {
2104 cxx << ",\n"
2105 " " << varname;
2106 fields[i].GenerateCplusplusConstructor(hdr, cxx);
2110 // Output declarations for generated functions
2111 hdr << "\n"
2112 " PINDEX GetDataLength() const;\n"
2113 " BOOL Decode(PASN_Stream & strm);\n"
2114 " void Encode(PASN_Stream & strm) const;\n"
2115 "#ifndef PASN_NOPRINTON\n"
2116 " void PrintOn(ostream & strm) const;\n"
2117 "#endif\n";
2119 if (xml_output)
2121 hdr << " BOOL PreambleDecodeXER(PXER_Stream & strm);\n";
2123 if (fields.GetSize())
2124 hdr << " void PreambleEncodeXER(PXER_Stream &) const;\n";
2128 if (numFields > 0)
2129 hdr << " Comparison Compare(const PObject & obj) const;\n";
2131 cxx << "\n"
2132 "{\n";
2133 GenerateCplusplusConstraints(PString(), hdr, cxx);
2134 for (i = 0; i < fields.GetSize(); i++) {
2135 PString ident = fields[i].GetIdentifier();
2136 fields[i].GenerateCplusplusConstraints("m_" + ident + ".", hdr, cxx);
2137 if (i >= numFields && !fields[i].IsOptional())
2138 cxx << " IncludeOptionalField(e_" << ident << ");\n";
2140 cxx << "}\n"
2141 "\n"
2142 "\n"
2143 "#ifndef PASN_NOPRINTON\n"
2144 << GetTemplatePrefix()
2145 << "void " << GetClassNameString() << "::PrintOn(ostream & strm) const\n"
2146 "{\n"
2147 " int indent = strm.precision() + 2;\n"
2148 " strm << \"{\\n\";\n";
2150 for (i = 0; i < fields.GetSize(); i++) {
2151 PString id = fields[i].GetIdentifier();
2152 if (i >= numFields || fields[i].IsOptional())
2153 cxx << " if (HasOptionalField(e_" << id << "))\n"
2154 " ";
2155 cxx << " strm << setw(indent+" << id.GetLength()+3 << ") << \""
2156 << id << " = \" << setprecision(indent) << m_" << id << " << '\\n';\n";
2159 cxx << " strm << setw(indent-1) << \"}\";\n"
2160 "}\n"
2161 "#endif\n"
2162 "\n"
2163 "\n";
2165 if (xml_output)
2167 cxx << GetTemplatePrefix()
2168 << "BOOL " << GetClassNameString() << "::PreambleDecodeXER(PXER_Stream & strm)\n"
2169 "{\n";
2171 if (fields.GetSize())
2173 cxx << " PXMLElement * elem = strm.GetCurrentElement();\n"
2174 " PXMLElement * sub_elem;\n"
2175 " BOOL result;\n"
2176 "\n";
2178 for (i = 0; i < fields.GetSize(); i++)
2180 PString id = fields[i].GetIdentifier();
2181 cxx << " if ((sub_elem = (PXMLElement *)elem->GetElement(\"" << id << "\")) && sub_elem->IsElement())\n"
2182 " {\n";
2184 if (i >= numFields || fields[i].IsOptional())
2185 cxx << " IncludeOptionalField(e_" << id << ");\n";
2187 cxx << " strm.SetCurrentElement(sub_elem);\n"
2188 " result = m_" << id << ".Decode(strm);\n"
2189 " strm.SetCurrentElement(sub_elem);\n"
2190 " if (!result)\n"
2191 " return FALSE;\n"
2192 " }\n"
2193 "\n";
2197 cxx << " return TRUE;\n"
2198 "}\n"
2199 "\n";
2201 if (fields.GetSize())
2203 cxx << GetTemplatePrefix()
2204 << "void " << GetClassNameString() << "::PreambleEncodeXER(PXER_Stream & strm) const\n"
2205 "{\n";
2207 cxx << " PXMLElement * elem = strm.GetCurrentElement();\n"
2208 " PXMLElement * sub_elem;\n"
2209 "\n";
2211 for (i = 0; i < fields.GetSize(); i++)
2213 PString id = fields[i].GetIdentifier();
2215 if (i >= numFields || fields[i].IsOptional())
2216 cxx << " if (HasOptionalField(e_" << id << "))\n"
2217 " {\n";
2219 cxx << " sub_elem = elem->AddChild(new PXMLElement(elem, \"" << id << "\"));\n"
2220 " strm.SetCurrentElement(sub_elem);\n"
2221 " m_" << id << ".Encode(strm);\n";
2223 if (i >= numFields || fields[i].IsOptional())
2224 cxx << " }\n";
2226 cxx << "\n";
2229 cxx << " strm.SetCurrentElement(elem);\n"
2230 "}\n"
2231 "\n";
2235 if (numFields > 0) {
2236 cxx << GetTemplatePrefix()
2237 << "PObject::Comparison " << GetClassNameString() << "::Compare(const PObject & obj) const\n"
2238 "{\n"
2239 "#ifndef PASN_LEANANDMEAN\n"
2240 " PAssert(PIsDescendant(this, " << GetClassNameString() << "), PInvalidCast);\n"
2241 "#endif\n"
2242 " const " << GetClassNameString() << " & other = (const " << GetClassNameString() << " &)obj;\n"
2243 "\n"
2244 " Comparison result;\n"
2245 "\n";
2247 for (i = 0; i < numFields; i++) {
2248 PString identifier = fields[i].GetIdentifier();
2249 cxx << " if ((result = m_" << identifier << ".Compare(other.m_" << identifier << ")) != EqualTo)\n"
2250 " return result;\n";
2253 cxx << "\n"
2254 " return PASN_Sequence::Compare(other);\n"
2255 "}\n"
2256 "\n"
2257 "\n";
2260 cxx << GetTemplatePrefix()
2261 << "PINDEX " << GetClassNameString() << "::GetDataLength() const\n"
2262 "{\n"
2263 " PINDEX length = 0;\n";
2265 for (i = 0; i < numFields; i++) {
2266 if (fields[i].IsOptional())
2267 cxx << " if (HasOptionalField(e_" << fields[i].GetIdentifier() << "))\n ";
2268 cxx << " length += m_" << fields[i].GetIdentifier() << ".GetObjectLength();\n";
2271 cxx << " return length;\n"
2272 "}\n"
2273 "\n"
2274 "\n"
2275 << GetTemplatePrefix()
2276 << "BOOL " << GetClassNameString() << "::Decode(PASN_Stream & strm)\n"
2277 "{\n"
2278 " if (!PreambleDecode(strm))\n"
2279 " return FALSE;\n\n";
2281 if (xml_output)
2283 cxx << " if (PIsDescendant(&strm, PXER_Stream))\n"
2284 " return TRUE;\n\n";
2287 for (i = 0; i < numFields; i++) {
2288 cxx << " if (";
2289 if (fields[i].IsOptional())
2290 cxx << "HasOptionalField(e_" << fields[i].GetIdentifier() << ") && ";
2291 cxx << "!m_" << fields[i].GetIdentifier() << ".Decode(strm))\n"
2292 " return FALSE;\n";
2295 for (; i < fields.GetSize(); i++)
2296 cxx << " if (!KnownExtensionDecode(strm, e_"
2297 << fields[i].GetIdentifier()
2298 << ", m_" << fields[i].GetIdentifier() << "))\n"
2299 " return FALSE;\n";
2301 cxx << "\n"
2302 " return UnknownExtensionsDecode(strm);\n"
2303 "}\n"
2304 "\n"
2305 "\n"
2306 << GetTemplatePrefix()
2307 << "void " << GetClassNameString() << "::Encode(PASN_Stream & strm) const\n"
2308 "{\n"
2309 " PreambleEncode(strm);\n\n";
2311 if (xml_output)
2313 cxx << " if (PIsDescendant(&strm, PXER_Stream))\n"
2314 " return;\n\n";
2317 for (i = 0; i < numFields; i++) {
2318 if (fields[i].IsOptional())
2319 cxx << " if (HasOptionalField(e_" << fields[i].GetIdentifier() << "))\n"
2320 " ";
2321 cxx << " m_" << fields[i].GetIdentifier() << ".Encode(strm);\n";
2324 for (; i < fields.GetSize(); i++)
2325 cxx << " KnownExtensionEncode(strm, e_"
2326 << fields[i].GetIdentifier()
2327 << ", m_" << fields[i].GetIdentifier() << ");\n";
2329 cxx << "\n"
2330 " UnknownExtensionsEncode(strm);\n";
2332 EndGenerateCplusplus(hdr, cxx);
2336 const char * SequenceType::GetAncestorClass() const
2338 return "PASN_Sequence";
2342 BOOL SequenceType::CanReferenceType() const
2344 return TRUE;
2348 BOOL SequenceType::ReferencesType(const TypeBase & type)
2350 for (PINDEX i = 0; i < fields.GetSize(); i++)
2351 if (fields[i].ReferencesType(type))
2352 return TRUE;
2353 return FALSE;
2357 /////////////////////////////////////////////////////////
2359 SequenceOfType::SequenceOfType(TypeBase * base, Constraint * constraint, unsigned tag)
2360 : TypeBase(tag)
2362 baseType = base;
2363 if (constraint != NULL)
2364 AddConstraint(constraint);
2368 SequenceOfType::~SequenceOfType()
2370 delete baseType;
2374 void SequenceOfType::PrintOn(ostream & strm) const
2376 PrintStart(strm);
2377 if (baseType == NULL)
2378 strm << "!!Null Type!!\n";
2379 else
2380 strm << *baseType << '\n';
2381 PrintFinish(strm);
2385 void SequenceOfType::FlattenUsedTypes()
2387 baseType = baseType->FlattenThisType(*this);
2391 TypeBase * SequenceOfType::FlattenThisType(const TypeBase & parent)
2393 if (!baseType->IsPrimitiveType() || baseType->HasConstraints())
2394 return new DefinedType(this, parent);
2396 // Search for an existing sequence of type
2397 PString seqName = "ArrayOf_" + baseType->GetTypeName();
2399 TypeBase * existingType = Module->FindType(seqName);
2400 if (existingType != NULL)
2401 return new DefinedType(this, existingType);
2403 return new DefinedType(this, seqName);
2407 BOOL SequenceOfType::IsPrimitiveType() const
2409 return FALSE;
2413 void SequenceOfType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2415 BeginGenerateCplusplus(hdr, cxx);
2416 cxx << ")\n"
2417 "{\n";
2418 GenerateCplusplusConstraints(PString(), hdr, cxx);
2419 cxx << "}\n"
2420 "\n"
2421 "\n";
2423 PString baseTypeName = baseType->GetTypeName();
2425 // Generate declarations for generated functions
2426 hdr << " PASN_Object * CreateObject() const;\n"
2427 " " << baseTypeName << " & operator[](PINDEX i) const";
2428 if (Module->UsingInlines())
2429 hdr << " { return (" << baseTypeName << " &)array[i]; }\n";
2430 else
2431 hdr << ";\n";
2433 // Generate implementation for functions
2434 cxx << GetTemplatePrefix()
2435 << "PASN_Object * " << GetClassNameString() << "::CreateObject() const\n"
2436 "{\n";
2438 if (baseType->HasConstraints()) {
2439 cxx << " " << baseTypeName << " * obj = new " << baseTypeName << ";\n";
2440 baseType->GenerateCplusplusConstraints("obj->", hdr, cxx);
2441 cxx << " return obj;\n";
2443 else
2444 cxx << " return new " << baseTypeName << ";\n";
2446 if (!Module->UsingInlines())
2447 cxx << "}\n"
2448 "\n"
2449 "\n"
2450 << GetTemplatePrefix()
2451 << baseTypeName << " & " << GetClassNameString() << "::operator[](PINDEX i) const\n"
2452 "{\n"
2453 " return (" << baseTypeName << " &)array[i];\n";
2455 EndGenerateCplusplus(hdr, cxx);
2459 void SequenceOfType::GenerateForwardDecls(ostream & hdr)
2461 if (baseType->IsParameterizedType())
2462 return;
2464 PString baseTypeName = baseType->GetTypeName();
2466 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2467 typesOutput += GetIdentifier();
2469 if (!typesOutput.Contains(baseTypeName))
2470 hdr << "class " << baseTypeName << ";\n\n";
2474 const char * SequenceOfType::GetAncestorClass() const
2476 return "PASN_Array";
2480 BOOL SequenceOfType::CanReferenceType() const
2482 return TRUE;
2486 BOOL SequenceOfType::ReferencesType(const TypeBase & type)
2488 return baseType->ReferencesType(type) && baseType->IsParameterizedType();
2492 /////////////////////////////////////////////////////////
2494 SetType::SetType()
2495 : SequenceType(NULL, FALSE, NULL, Tag::UniversalSet)
2500 SetType::SetType(SequenceType * seq)
2501 : SequenceType(*seq)
2503 tag.number = Tag::UniversalSet;
2507 const char * SetType::GetAncestorClass() const
2509 return "PASN_Set";
2513 /////////////////////////////////////////////////////////
2515 SetOfType::SetOfType(TypeBase * base, Constraint * constraint)
2516 : SequenceOfType(base, constraint, Tag::UniversalSet)
2521 /////////////////////////////////////////////////////////
2523 ChoiceType::ChoiceType(TypesList * stnd,
2524 BOOL extendable,
2525 TypesList * extensions)
2526 : SequenceType(stnd, extendable, extensions, Tag::IllegalUniversalTag)
2531 void ChoiceType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2533 PINDEX i;
2536 BeginGenerateCplusplus(hdr, cxx);
2538 // Complete the ancestor constructor parameters
2539 cxx << ", " << numFields << ", " << (extendable ? "TRUE" : "FALSE");
2541 // Generate the enum's for each choice discriminator, and include strings for
2542 // PrintOn() debug output into acncestor constructor
2543 BOOL outputEnum = FALSE;
2544 int prevNum = -1;
2545 for (i = 0; i < fields.GetSize(); i++) {
2546 const Tag & fieldTag = fields[i].GetTag();
2547 if (fieldTag.mode == Tag::Automatic || !fields[i].IsChoice()) {
2548 if (outputEnum) {
2549 hdr << ",\n";
2550 cxx << " \"";
2552 else {
2553 hdr << " enum Choices {\n";
2554 cxx << "\n"
2555 "#ifndef PASN_NOPRINTON\n"
2556 " , \"";
2557 outputEnum = TRUE;
2560 hdr << " e_" << fields[i].GetIdentifier();
2561 cxx << fields[i].GetIdentifier();
2563 if (fieldTag.mode != Tag::Automatic && fieldTag.number != (unsigned)(prevNum+1)) {
2564 hdr << " = " << fieldTag.number;
2565 cxx << '=' << fieldTag.number;
2567 prevNum = fieldTag.number;
2568 cxx << " \"\n";
2572 if (outputEnum) {
2573 hdr << "\n"
2574 " };\n"
2575 "\n";
2576 cxx << "#endif\n"
2577 " ";
2580 cxx << ")\n"
2581 "{\n";
2582 GenerateCplusplusConstraints(PString(), hdr, cxx);
2583 cxx << "}\n"
2584 "\n"
2585 "\n";
2587 // Generate code for type safe cast operators of selected choice object
2588 BOOL needExtraLine = FALSE;
2590 if (Module->UsingOperators()) {
2591 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2592 typesOutput += GetIdentifier();
2594 for (i = 0; i < fields.GetSize(); i++) {
2595 PString type = fields[i].GetTypeName();
2596 if (!typesOutput.Contains(type)) {
2597 if (Module->UsingInlines()) {
2598 hdr << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2599 " operator " << type << " &() const { return *(" << type << " *)choice; }\n"
2600 "#else\n"
2601 " operator " << type << " &() { return *(" << type << " *)choice; }\n"
2602 " operator const " << type << " &() const { return *(const " << type << " *)choice; }\n"
2603 "#endif\n";
2605 else {
2606 hdr << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2607 " operator " << type << " &() const;\n"
2608 "#else\n"
2609 " operator " << type << " &();\n"
2610 " operator const " << type << " &() const;\n"
2611 "#endif\n";
2612 cxx << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2613 << GetTemplatePrefix()
2614 << GetClassNameString() << "::operator " << type << " &() const\n"
2615 "#else\n"
2616 << GetTemplatePrefix()
2617 << GetClassNameString() << "::operator " << type << " &()\n"
2618 "{\n"
2619 "#ifndef PASN_LEANANDMEAN\n"
2620 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2621 "#endif\n"
2622 " return *(" << type << " *)choice;\n"
2623 "}\n"
2624 "\n"
2625 "\n"
2626 << GetTemplatePrefix()
2627 << GetClassNameString() << "::operator const " << type << " &() const\n"
2628 "#endif\n"
2629 "{\n"
2630 "#ifndef PASN_LEANANDMEAN\n"
2631 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2632 "#endif\n"
2633 " return *(" << type << " *)choice;\n"
2634 "}\n"
2635 "\n"
2636 "\n";
2638 typesOutput += type;
2639 needExtraLine = TRUE;
2643 else {
2644 for (i = 0; i < fields.GetSize(); i++) {
2645 PString type = fields[i].GetTypeName();
2646 PString fieldName = fields[i].GetIdentifier();
2647 if (Module->UsingInlines()) {
2648 hdr << " " << type << " & m_" << fieldName << "() { return *(" << type << " *)choice; }\n"
2649 " const " << type << " & m_" << fieldName << "() const { return *(const " << type << " *)choice; }\n";
2651 else {
2652 hdr << " " << type << " & m_" << fieldName << "();\n"
2653 " const " << type << " & m_" << fieldName << "() const;\n";
2654 cxx << GetTemplatePrefix() << type << " & "
2655 << GetClassNameString() << "::m_" << fieldName << "()\n"
2656 "{\n"
2657 "#ifndef PASN_LEANANDMEAN\n"
2658 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2659 "#endif\n"
2660 " return *(" << type << " *)choice;\n"
2661 "}\n"
2662 "\n"
2663 "\n"
2664 << GetTemplatePrefix() << type << " const & "
2665 << GetClassNameString() << "::m_" << fieldName << "() const\n"
2666 "{\n"
2667 "#ifndef PASN_LEANANDMEAN\n"
2668 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2669 "#endif\n"
2670 " return *(" << type << " *)choice;\n"
2671 "}\n"
2672 "\n"
2673 "\n";
2676 needExtraLine = TRUE;
2679 if (needExtraLine)
2680 hdr << '\n';
2683 // Generate virtual function to create chosen object based on discriminator
2684 hdr << " BOOL CreateObject();\n";
2685 cxx << GetTemplatePrefix()
2686 << "BOOL " << GetClassNameString() << "::CreateObject()\n"
2687 "{\n";
2689 // special case: if choice is all NULLs then simply output code
2690 BOOL allNull = TRUE;
2691 for (i = 0; allNull && i < fields.GetSize(); i++)
2692 allNull = allNull && strcmp(fields[i].GetAncestorClass(), "PASN_Null") == 0;
2694 if (allNull) {
2695 cxx << " choice = (tag <= e_" << fields[fields.GetSize()-1].GetIdentifier() << ") ? new PASN_Null() : NULL;\n"
2696 << " return choice != NULL;\n";
2699 else {
2700 // declare an array of flags indicating whether the tag has been output or not
2701 PBYTEArray flags(fields.GetSize());
2702 for (i = 0; i < fields.GetSize(); i++)
2703 flags[i] = 0;
2705 // keep
2706 outputEnum = FALSE;
2707 for (i = 0; i < fields.GetSize(); i++) {
2709 if (fields[i].GetTag().mode == Tag::Automatic || !fields[i].IsChoice()) {
2711 // ignore this tag if output previously
2712 if (flags[i] != 0)
2713 continue;
2715 if (!outputEnum) {
2716 cxx << " switch (tag) {\n";
2717 outputEnum = TRUE;
2720 // if the field has constraints, then output it alone
2721 // otherwise, look for all fields with the same type
2722 PString name = fields[i].GetTypeName();
2723 if (fields[i].HasConstraints()) {
2724 cxx << " case e_" << fields[i].GetIdentifier() << " :\n";
2725 flags[i] = 1;
2726 } else {
2727 PINDEX j;
2728 for (j = i; j < fields.GetSize(); j++) {
2729 if (fields[j].GetTypeName() == name) {
2730 cxx << " case e_" << fields[j].GetIdentifier() << " :\n";
2731 flags[j] = 1;
2736 cxx << " choice = new " << name;
2737 fields[i].GenerateCplusplusConstructor(hdr, cxx);
2738 cxx << ";\n";
2739 fields[i].GenerateCplusplusConstraints(" choice->", hdr, cxx);
2740 cxx << " return TRUE;\n";
2744 if (outputEnum)
2745 cxx << " }\n"
2746 "\n";
2748 for (i = 0; i < fields.GetSize(); i++) {
2749 if (fields[i].GetTag().mode != Tag::Automatic && fields[i].IsChoice())
2750 cxx << " choice = new " << fields[i].GetTypeName() << "(tag, tagClass);\n"
2751 " if (((PASN_Choice*)choice)->CreateObject())\n"
2752 " return TRUE;\n"
2753 " delete choice;\n"
2754 "\n";
2757 cxx << " choice = NULL;\n"
2758 " return FALSE;\n";
2761 EndGenerateCplusplus(hdr, cxx);
2765 void ChoiceType::GenerateForwardDecls(ostream & hdr)
2767 // Output forward declarations for choice pointers, but not standard classes
2768 BOOL needExtraLine = FALSE;
2770 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2771 typesOutput += GetIdentifier();
2773 PStringSet forwards;
2775 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2776 PString type = fields[i].GetTypeName();
2777 if (!fields[i].IsParameterizedType() &&
2778 !typesOutput.Contains(type) &&
2779 !forwards.Contains(type)) {
2780 hdr << "class " << type << ";\n";
2781 needExtraLine = TRUE;
2782 forwards.Include(type);
2786 if (needExtraLine)
2787 hdr << '\n';
2791 BOOL ChoiceType::IsPrimitiveType() const
2793 return FALSE;
2797 BOOL ChoiceType::IsChoice() const
2799 return TRUE;
2803 const char * ChoiceType::GetAncestorClass() const
2805 return "PASN_Choice";
2809 BOOL ChoiceType::ReferencesType(const TypeBase & type)
2811 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2812 if (fields[i].ReferencesType(type) && fields[i].IsParameterizedType())
2813 return TRUE;
2815 return FALSE;
2819 /////////////////////////////////////////////////////////
2821 EmbeddedPDVType::EmbeddedPDVType()
2822 : TypeBase(Tag::UniversalEmbeddedPDV)
2827 const char * EmbeddedPDVType::GetAncestorClass() const
2829 return "PASN_OctetString";
2833 /////////////////////////////////////////////////////////
2835 ExternalType::ExternalType()
2836 : TypeBase(Tag::UniversalExternalType)
2841 const char * ExternalType::GetAncestorClass() const
2843 return "PASN_OctetString";
2847 /////////////////////////////////////////////////////////
2849 AnyType::AnyType(PString * ident)
2850 : TypeBase(Tag::UniversalExternalType)
2852 if (ident != NULL) {
2853 identifier = *ident;
2854 delete ident;
2859 void AnyType::PrintOn(ostream & strm) const
2861 PrintStart(strm);
2862 if (!identifier)
2863 strm << "Defined by " << identifier;
2864 PrintFinish(strm);
2868 const char * AnyType::GetAncestorClass() const
2870 return "PASN_OctetString";
2874 /////////////////////////////////////////////////////////
2876 StringTypeBase::StringTypeBase(int tag)
2877 : TypeBase(tag)
2882 int StringTypeBase::GetBraceTokenContext() const
2884 return STRING_BRACE;
2888 static void GenerateOperator(const char * rhsType, ostream & hdr, ostream & cxx, const TypeBase & actualType)
2890 hdr << " " << actualType.GetIdentifier() << " & operator=(const " << rhsType << " v)";
2891 if (Module->UsingInlines())
2892 hdr << " { SetValue(v); return *this; }\n";
2893 else {
2894 hdr << ";\n";
2895 cxx << actualType.GetTemplatePrefix()
2896 << actualType.GetIdentifier() << " & "
2897 << actualType.GetClassNameString() << "::operator=(const " << rhsType << " v)\n"
2898 "{\n"
2899 " SetValue(v);\n"
2900 " return *this;\n"
2901 "}\n"
2902 "\n"
2903 "\n";
2908 void StringTypeBase::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
2910 GenerateOperator("char *", hdr, cxx, actualType);
2911 GenerateOperator("PString &", hdr, cxx, actualType);
2915 /////////////////////////////////////////////////////////
2917 BMPStringType::BMPStringType()
2918 : StringTypeBase(Tag::UniversalBMPString)
2923 const char * BMPStringType::GetAncestorClass() const
2925 return "PASN_BMPString";
2929 void BMPStringType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
2931 StringTypeBase::GenerateOperators(hdr, cxx, actualType);
2932 GenerateOperator("PWORDArray &", hdr, cxx, actualType);
2933 GenerateOperator("PASN_BMPString &", hdr, cxx, actualType);
2937 /////////////////////////////////////////////////////////
2939 GeneralStringType::GeneralStringType()
2940 : StringTypeBase(Tag::UniversalGeneralString)
2945 const char * GeneralStringType::GetAncestorClass() const
2947 return "PASN_GeneralString";
2951 /////////////////////////////////////////////////////////
2953 GraphicStringType::GraphicStringType()
2954 : StringTypeBase(Tag::UniversalGraphicString)
2959 const char * GraphicStringType::GetAncestorClass() const
2961 return "PASN_GraphicString";
2965 /////////////////////////////////////////////////////////
2967 IA5StringType::IA5StringType()
2968 : StringTypeBase(Tag::UniversalIA5String)
2973 const char * IA5StringType::GetAncestorClass() const
2975 return "PASN_IA5String";
2979 /////////////////////////////////////////////////////////
2981 ISO646StringType::ISO646StringType()
2982 : StringTypeBase(Tag::UniversalVisibleString)
2987 const char * ISO646StringType::GetAncestorClass() const
2989 return "PASN_ISO646String";
2993 /////////////////////////////////////////////////////////
2995 NumericStringType::NumericStringType()
2996 : StringTypeBase(Tag::UniversalNumericString)
3001 const char * NumericStringType::GetAncestorClass() const
3003 return "PASN_NumericString";
3007 /////////////////////////////////////////////////////////
3009 PrintableStringType::PrintableStringType()
3010 : StringTypeBase(Tag::UniversalPrintableString)
3015 const char * PrintableStringType::GetAncestorClass() const
3017 return "PASN_PrintableString";
3021 /////////////////////////////////////////////////////////
3023 TeletexStringType::TeletexStringType()
3024 : StringTypeBase(Tag::UniversalTeletexString)
3029 const char * TeletexStringType::GetAncestorClass() const
3031 return "PASN_TeletexString";
3035 /////////////////////////////////////////////////////////
3037 T61StringType::T61StringType()
3038 : StringTypeBase(Tag::UniversalTeletexString)
3043 const char * T61StringType::GetAncestorClass() const
3045 return "PASN_T61String";
3049 /////////////////////////////////////////////////////////
3051 UniversalStringType::UniversalStringType()
3052 : StringTypeBase(Tag::UniversalUniversalString)
3057 const char * UniversalStringType::GetAncestorClass() const
3059 return "PASN_UniversalString";
3063 /////////////////////////////////////////////////////////
3065 VideotexStringType::VideotexStringType()
3066 : StringTypeBase(Tag::UniversalVideotexString)
3071 const char * VideotexStringType::GetAncestorClass() const
3073 return "PASN_VideotexString";
3077 /////////////////////////////////////////////////////////
3079 VisibleStringType::VisibleStringType()
3080 : StringTypeBase(Tag::UniversalVisibleString)
3085 const char * VisibleStringType::GetAncestorClass() const
3087 return "PASN_VisibleString";
3091 /////////////////////////////////////////////////////////
3093 UnrestrictedCharacterStringType::UnrestrictedCharacterStringType()
3094 : StringTypeBase(Tag::UniversalUniversalString)
3099 const char * UnrestrictedCharacterStringType::GetAncestorClass() const
3101 return "PASN_UnrestrictedString";
3105 /////////////////////////////////////////////////////////
3107 GeneralizedTimeType::GeneralizedTimeType()
3108 : TypeBase(Tag::UniversalGeneralisedTime)
3113 const char * GeneralizedTimeType::GetAncestorClass() const
3115 return "PASN_GeneralisedTime";
3119 /////////////////////////////////////////////////////////
3121 UTCTimeType::UTCTimeType()
3122 : TypeBase(Tag::UniversalUTCTime)
3127 const char * UTCTimeType::GetAncestorClass() const
3129 return "PASN_UniversalTime";
3133 /////////////////////////////////////////////////////////
3135 ObjectDescriptorType::ObjectDescriptorType()
3136 : TypeBase(Tag::UniversalObjectDescriptor)
3141 const char * ObjectDescriptorType::GetAncestorClass() const
3143 return "PASN_ObectDescriptor";
3147 /////////////////////////////////////////////////////////
3149 ObjectIdentifierType::ObjectIdentifierType()
3150 : TypeBase(Tag::UniversalObjectId)
3155 int ObjectIdentifierType::GetIdentifierTokenContext() const
3157 return OID_IDENTIFIER;
3161 int ObjectIdentifierType::GetBraceTokenContext() const
3163 return OID_BRACE;
3167 const char * ObjectIdentifierType::GetAncestorClass() const
3169 return "PASN_ObjectId";
3173 /////////////////////////////////////////////////////////
3175 ObjectClassFieldType::ObjectClassFieldType(PString * objclass, PString * field)
3176 : TypeBase(Tag::IllegalUniversalTag),
3177 asnObjectClassName(*objclass),
3178 asnObjectClassField(*field)
3180 delete objclass;
3181 delete field;
3185 const char * ObjectClassFieldType::GetAncestorClass() const
3187 return "PASN_OctetString";
3191 void ObjectClassFieldType::PrintOn(ostream & strm) const
3193 PrintStart(strm);
3194 strm << asnObjectClassName << '.' << asnObjectClassField;
3195 PrintFinish(strm);
3199 TypeBase * ObjectClassFieldType::FlattenThisType(const TypeBase & parent)
3201 return new DefinedType(this, parent);
3205 BOOL ObjectClassFieldType::IsPrimitiveType() const
3207 return FALSE;
3211 void ObjectClassFieldType::GenerateCplusplus(ostream & hdr, ostream & cxx)
3213 BeginGenerateCplusplus(hdr, cxx);
3215 hdr << " BOOL DecodeSubType(";
3216 GenerateCplusplusConstraints(PString(), hdr, cxx);
3217 hdr << " & obj) { return PASN_OctetString::DecodeSubType(obj); }\n"
3218 " void EncodeSubType(const ";
3219 GenerateCplusplusConstraints(PString(), hdr, cxx);
3220 hdr << " & obj) { PASN_OctetString::EncodeSubType(obj); } \n"
3221 "\n";
3223 cxx << ")\n"
3224 "{\n";
3226 EndGenerateCplusplus(hdr, cxx);
3230 BOOL ObjectClassFieldType::CanReferenceType() const
3232 return TRUE;
3236 BOOL ObjectClassFieldType::ReferencesType(const TypeBase & type)
3238 for (PINDEX i = 0; i < constraints.GetSize(); i++) {
3239 if (constraints[i].ReferencesType(type))
3240 return TRUE;
3242 return FALSE;
3246 /////////////////////////////////////////////////////////
3248 ImportedType::ImportedType(PString * theName, BOOL param)
3249 : TypeBase(Tag::IllegalUniversalTag)
3251 identifier = name = *theName;
3252 delete theName;
3254 parameterised = param;
3258 const char * ImportedType::GetAncestorClass() const
3260 return identifier;
3264 void ImportedType::AdjustIdentifier()
3266 identifier = modulePrefix + '_' + MakeIdentifierC(name);
3270 void ImportedType::GenerateCplusplus(ostream &, ostream &)
3275 void ImportedType::SetImportPrefix(const PString & prefix)
3277 modulePrefix = prefix;
3281 BOOL ImportedType::IsParameterisedImport() const
3283 return parameterised;
3287 /////////////////////////////////////////////////////////
3289 SearchType::SearchType(const PString & theName)
3290 : TypeBase(Tag::IllegalUniversalTag)
3292 identifier = name = theName;
3296 const char * SearchType::GetAncestorClass() const
3298 return identifier;
3302 /////////////////////////////////////////////////////////
3304 void ValueBase::SetValueName(PString * name)
3306 valueName = *name;
3307 delete name;
3311 void ValueBase::PrintBase(ostream & strm) const
3313 if (!valueName)
3314 strm << '\n' << indent() << valueName << '=';
3318 void ValueBase::GenerateCplusplus(ostream &, ostream &)
3320 PError << StdError(Warning) << "unsupported value type." << endl;
3324 /////////////////////////////////////////////////////////
3326 DefinedValue::DefinedValue(PString * name)
3327 : referenceName(*name)
3329 delete name;
3330 actualValue = NULL;
3331 unresolved = TRUE;
3335 void DefinedValue::PrintOn(ostream & strm) const
3337 PrintBase(strm);
3338 strm << referenceName;
3342 void DefinedValue::GenerateCplusplus(ostream & hdr, ostream & cxx)
3344 if (unresolved) {
3345 unresolved = FALSE;
3347 const ValuesList & values = Module->GetValues();
3348 for (PINDEX i = 0; i < values.GetSize(); i++) {
3349 if (values[i].GetName() == referenceName) {
3350 actualValue = &values[i];
3351 break;
3356 if (actualValue != NULL)
3357 actualValue->GenerateCplusplus(hdr, cxx);
3358 else
3359 cxx << "e_" << referenceName;
3363 /////////////////////////////////////////////////////////
3365 BooleanValue::BooleanValue(BOOL newVal)
3367 value = newVal;
3371 void BooleanValue::PrintOn(ostream & strm) const
3373 PrintBase(strm);
3374 strm << (value ? "TRUE" : "FALSE");
3378 void BooleanValue::GenerateCplusplus(ostream &, ostream & cxx)
3380 cxx << (value ? "TRUE" : "FALSE");
3384 /////////////////////////////////////////////////////////
3386 IntegerValue::IntegerValue(PInt64 newVal)
3388 value = newVal;
3392 void IntegerValue::PrintOn(ostream & strm) const
3394 PrintBase(strm);
3396 strm << value;
3400 void IntegerValue::GenerateCplusplus(ostream &, ostream & cxx)
3402 cxx << value;
3403 if (value > INT_MAX)
3404 cxx << 'U';
3408 /////////////////////////////////////////////////////////
3410 RealValue::RealValue(double newVal)
3412 value = newVal;
3416 /////////////////////////////////////////////////////////
3418 OctetStringValue::OctetStringValue(PString * newVal)
3420 // value = *newVal;
3421 delete newVal;
3425 /////////////////////////////////////////////////////////
3427 BitStringValue::BitStringValue(PString * newVal)
3429 // value = *newVal;
3430 delete newVal;
3434 BitStringValue::BitStringValue(PStringList * newVal)
3436 // value = *newVal;
3437 delete newVal;
3441 /////////////////////////////////////////////////////////
3443 CharacterValue::CharacterValue(BYTE c)
3445 value = c;
3449 CharacterValue::CharacterValue(BYTE t1, BYTE t2)
3451 value = (t1<<8) + t2;
3455 CharacterValue::CharacterValue(BYTE q1, BYTE q2, BYTE q3, BYTE q4)
3457 value = (q1<<24) + (q2<<16) + (q3<<8) + q4;
3461 void CharacterValue::PrintOn(ostream & strm) const
3463 strm << "'\\x" << hex << value << '\'';
3467 void CharacterValue::GenerateCplusplus(ostream &, ostream & cxx)
3469 cxx << value;
3473 /////////////////////////////////////////////////////////
3475 CharacterStringValue::CharacterStringValue(PString * newVal)
3477 value = *newVal;
3478 delete newVal;
3482 CharacterStringValue::CharacterStringValue(PStringList * newVal)
3484 for (PINDEX i = 0; i < newVal->GetSize(); i++)
3485 value += (*newVal)[i];
3486 delete newVal;
3490 void CharacterStringValue::PrintOn(ostream & strm) const
3492 strm << value;
3496 void CharacterStringValue::GenerateCplusplus(ostream &, ostream & cxx)
3498 cxx << value;
3502 /////////////////////////////////////////////////////////
3504 ObjectIdentifierValue::ObjectIdentifierValue(PString * newVal)
3506 value.Append(newVal);
3510 ObjectIdentifierValue::ObjectIdentifierValue(PStringList * newVal)
3512 value = *newVal;
3513 delete newVal;
3517 void ObjectIdentifierValue::PrintOn(ostream & strm) const
3519 PrintBase(strm);
3520 if (value.IsEmpty())
3521 strm << "empty object identifier";
3522 else {
3523 strm << value[0];
3524 for (PINDEX i = 1; i < value.GetSize(); i++)
3525 strm << '.' << value[i];
3527 strm << '\n';
3531 /////////////////////////////////////////////////////////
3533 void MinValue::PrintOn(ostream & strm) const
3535 strm << "MIN";
3539 void MinValue::GenerateCplusplus(ostream &, ostream & cxx)
3541 cxx << "MinimumValue";
3545 /////////////////////////////////////////////////////////
3547 void MaxValue::PrintOn(ostream & strm) const
3549 strm << "MAX";
3553 void MaxValue::GenerateCplusplus(ostream &, ostream & cxx)
3555 cxx << "MaximumValue";
3559 /////////////////////////////////////////////////////////
3561 SequenceValue::SequenceValue(ValuesList * list)
3563 if (list != NULL) {
3564 values = *list;
3565 delete list;
3570 void SequenceValue::PrintOn(ostream & strm) const
3572 strm << "{ ";
3573 for (PINDEX i = 0; i < values.GetSize(); i++) {
3574 if (i > 0)
3575 strm << ", ";
3576 strm << values[i];
3578 strm << " }";
3582 /////////////////////////////////////////////////////////
3584 MibBase::MibBase(PString * nam,
3585 PString * descr,
3586 PString * refer,
3587 ValueBase * val)
3588 : name(*nam)
3590 delete nam;
3591 if (descr != NULL) {
3592 description = *descr;
3593 delete descr;
3595 if (refer != NULL) {
3596 reference = *refer;
3597 delete refer;
3599 value = val;
3603 MibBase::~MibBase()
3605 delete value;
3609 /////////////////////////////////////////////////////////
3611 MibObject::MibObject(PString * nam,
3612 TypeBase * typ,
3613 Access acc,
3614 Status stat,
3615 PString * descr,
3616 PString * refer,
3617 PStringList * idx,
3618 ValueBase * defVal,
3619 ValueBase * setVal)
3620 : MibBase(nam, descr, refer, setVal)
3622 type = typ;
3623 access = acc;
3624 status = stat;
3625 if (idx != NULL) {
3626 index = *idx;
3627 delete idx;
3629 defaultValue = defVal;
3633 MibObject::~MibObject()
3635 delete type;
3636 delete defaultValue;
3640 void MibObject::PrintOn(ostream & strm) const
3642 strm << " Object: " << name << "\n " << *type
3643 << " " << description << "\n"
3644 " " << *value << '\n';
3648 /////////////////////////////////////////////////////////
3650 MibTrap::MibTrap(PString * nam, ValueBase * ent, ValuesList * var,
3651 PString * descr, PString * refer, ValueBase * val)
3652 : MibBase(nam, descr, refer, val)
3654 enterprise = ent;
3655 if (var != NULL) {
3656 variables = *var;
3657 delete var;
3662 MibTrap::~MibTrap()
3664 delete enterprise;
3668 void MibTrap::PrintOn(ostream & strm) const
3670 strm << " Trap: " << name << "\n " << *enterprise
3671 << " " << description << "\n"
3672 " " << *value << '\n';
3676 /////////////////////////////////////////////////////////
3678 ImportModule::ImportModule(PString * name, TypesList * syms)
3679 : fullModuleName(*name),
3680 shortModuleName(Module->GetImportModuleName(*name)),
3681 filename(shortModuleName.ToLower())
3683 delete name;
3684 symbols = *syms;
3685 delete syms;
3687 PStringArray renameArgs = shortModuleName.Tokenise(',');
3688 switch (renameArgs.GetSize())
3690 case 3 :
3691 filename = renameArgs[2];
3692 case 2 :
3693 directoryPrefix = renameArgs[1];
3694 shortModuleName = renameArgs[0];
3697 for (PINDEX i = 0; i < symbols.GetSize(); i++) {
3698 symbols[i].SetImportPrefix(shortModuleName);
3699 Module->AppendType(&symbols[i]);
3704 void ImportModule::PrintOn(ostream & strm) const
3706 strm << " " << fullModuleName << " (" << shortModuleName << "):\n";
3707 for (PINDEX i = 0; i < symbols.GetSize(); i++)
3708 strm << " " << symbols[i];
3709 strm << '\n';
3713 void ImportModule::GenerateCplusplus(ostream & hdr, ostream & cxx)
3715 hdr << "#include \"" << directoryPrefix << filename << ".h\"\n";
3717 for (PINDEX i = 0; i < symbols.GetSize(); i++) {
3718 if (symbols[i].IsParameterisedImport()) {
3719 cxx << "#include \"" << filename << "_t.cxx\"\n";
3720 break;
3726 /////////////////////////////////////////////////////////
3728 ModuleDefinition::ModuleDefinition(PString * name, PStringList * id, Tag::Mode defTagMode)
3729 : moduleName(*name),
3730 definitiveId(*id)
3732 delete name;
3733 delete id;
3734 defaultTagMode = defTagMode;
3735 exportAll = FALSE;
3736 indentLevel = 1;
3738 PArgList & args = PProcess::Current().GetArguments();
3739 if (args.HasOption('r')) {
3740 PStringArray renames = args.GetOptionString('r').Lines();
3741 for (PINDEX i = 0; i < renames.GetSize(); i++) {
3742 PINDEX equal = renames[i].Find('=');
3743 if (equal > 0 && equal != P_MAX_INDEX)
3744 importNames.SetAt(renames[i].Left(equal).Trim(), renames[i].Mid(equal+1).Trim());
3750 void ModuleDefinition::SetExportAll()
3752 exportAll = TRUE;
3756 void ModuleDefinition::SetExports(TypesList * syms)
3758 exports = *syms;
3759 delete syms;
3763 void ModuleDefinition::PrintOn(ostream & strm) const
3765 strm << moduleName << "\n"
3766 "Default Tags: " << Tag::modeNames[defaultTagMode] << "\n"
3767 "Exports:";
3768 if (exportAll)
3769 strm << " ALL";
3770 else {
3771 strm << "\n ";
3772 for (PINDEX i = 0; i < exports.GetSize(); i++)
3773 strm << exports[i] << ' ';
3774 strm << '\n';
3776 strm << "Imports:\n" << imports << "\n"
3777 "Types:\n" << types << "\n"
3778 "Values:\n" << values << "\n"
3779 "MIBs:\n" << mibs << endl;
3783 void ModuleDefinition::AppendType(TypeBase * type)
3785 types.Append(type);
3786 sortedTypes.Append(type);
3790 TypeBase * ModuleDefinition::FindType(const PString & name)
3792 PINDEX pos = sortedTypes.GetValuesIndex(SearchType(name));
3793 if (pos != P_MAX_INDEX)
3794 return &sortedTypes[pos];
3795 return NULL;
3799 PString ModuleDefinition::GetImportModuleName(const PString & moduleName)
3801 if (importNames.Contains(moduleName))
3802 return importNames[moduleName];
3804 PINDEX pos = moduleName.Find('-');
3805 if (pos > 32)
3806 pos = 32;
3807 return moduleName.Left(pos);
3811 void ModuleDefinition::GenerateCplusplus(const PFilePath & path,
3812 const PString & modName,
3813 const PString & headerPrefix,
3814 unsigned numFiles,
3815 BOOL useNamespaces,
3816 BOOL useInlines,
3817 BOOL useOperators,
3818 BOOL verbose)
3820 PArgList & args = PProcess::Current().GetArguments();
3821 BOOL xml_output = args.HasOption('x');
3822 PINDEX i;
3824 usingInlines = useInlines;
3825 usingOperators = useOperators;
3827 // Adjust the module name to what is specified to a default
3828 if (!modName)
3829 moduleName = modName;
3830 else
3831 moduleName = MakeIdentifierC(moduleName);
3833 // Set the prefix on all external class names
3834 if (!useNamespaces)
3835 classNamePrefix = moduleName + '_';
3838 if (verbose)
3839 cout << "Sorting " << types.GetSize() << " types..." << endl;
3842 // Create sorted list for faster searching.
3843 sortedTypes.DisallowDeleteObjects();
3844 for (i = 0; i < types.GetSize(); i++)
3845 sortedTypes.Append(&types[i]);
3847 // Flatten types by generating types for "inline" definitions
3848 for (i = 0; i < types.GetSize(); i++)
3849 types[i].FlattenUsedTypes();
3851 // Reorder types
3852 // Determine if we need a separate file for template closure
3853 BOOL hasTemplates = FALSE;
3854 types.DisallowDeleteObjects();
3855 PINDEX loopDetect = 0;
3856 PINDEX bubble = 0;
3857 while (bubble < types.GetSize()) {
3858 BOOL makesReference = FALSE;
3860 TypeBase & bubbleType = types[bubble];
3861 if (bubbleType.CanReferenceType()) {
3862 for (i = bubble; i < types.GetSize(); i++) {
3863 if (bubbleType.ReferencesType(types[i])) {
3864 makesReference = TRUE;
3865 break;
3870 if (makesReference) {
3871 types.Append(types.RemoveAt(bubble));
3872 if (loopDetect > types.GetSize()) {
3873 PError << StdError(Fatal)
3874 << "Recursive type definition: " << bubbleType.GetName() << endl;
3875 break;
3877 loopDetect++;
3879 else {
3880 loopDetect = bubble;
3881 bubble++;
3884 if (bubbleType.HasParameters())
3885 hasTemplates = TRUE;
3887 types.AllowDeleteObjects();
3889 // Adjust all of the C++ identifiers prepending module name
3890 for (i = 0; i < types.GetSize(); i++)
3891 types[i].AdjustIdentifier();
3894 // Generate the code
3895 if (verbose)
3896 cout << "Generating code (" << types.GetSize() << " classes) ..." << endl;
3899 // Output the special template closure file, if necessary
3900 PString templateFilename;
3901 if (hasTemplates) {
3902 OutputFile templateFile;
3903 if (!templateFile.Open(path, "_t", ".cxx"))
3904 return;
3906 for (i = 0; i < types.GetSize(); i++) {
3907 if (types[i].HasParameters()) {
3908 PStringStream dummy;
3909 types[i].GenerateCplusplus(dummy, templateFile);
3913 if (verbose)
3914 cout << "Completed " << templateFile.GetFilePath() << endl;
3916 templateFilename = templateFile.GetFilePath().GetFileName();
3919 // Start the header file
3920 OutputFile hdrFile;
3921 if (!hdrFile.Open(path, "", ".h"))
3922 return;
3924 hdrFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3926 hdrFile << "#ifndef __" << moduleName.ToUpper() << "_H\n"
3927 "#define __" << moduleName.ToUpper() << "_H\n"
3928 "\n"
3929 "#ifdef P_USE_PRAGMA\n"
3930 "#pragma interface\n"
3931 "#endif\n"
3932 "\n";
3934 if (xml_output)
3935 hdrFile << "#define P_EXPAT 1\n"
3936 "#include <ptclib/pxml.h>\n";
3938 hdrFile << "#include <ptclib/asner.h>\n"
3939 "\n";
3941 // Start the first (and maybe only) cxx file
3942 OutputFile cxxFile;
3943 if (!cxxFile.Open(path, numFiles > 1 ? "_1" : "", ".cxx"))
3944 return;
3946 PString headerName = hdrFile.GetFilePath().GetFileName();
3948 cxxFile << "#ifdef P_USE_PRAGMA\n"
3949 "#pragma implementation \"" << headerName << "\"\n"
3950 "#endif\n"
3951 "\n"
3952 "#include <ptlib.h>\n"
3953 "#include \"" << headerPrefix << headerName << "\"\n"
3954 "\n"
3955 "#define new PNEW\n"
3956 "\n"
3957 "\n";
3959 cxxFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3961 // Include the template closure file.
3962 if (hasTemplates)
3963 cxxFile << "#include \"" << templateFilename << "\"\n\n";
3966 for (i = 0; i < imports.GetSize(); i++)
3967 imports[i].GenerateCplusplus(hdrFile, cxxFile);
3968 if (!imports.IsEmpty()) {
3969 hdrFile << "\n\n";
3970 cxxFile << "\n\n";
3974 if (useNamespaces) {
3975 hdrFile << "namespace " << moduleName << " {\n"
3976 "\n";
3977 cxxFile << "using namespace " << moduleName << ";\n"
3978 "\n";
3982 PINDEX classesPerFile = (types.GetSize()+numFiles-1)/numFiles;
3983 for (i = 0; i < types.GetSize(); i++) {
3984 if (i > 0 && i%classesPerFile == 0) {
3986 cxxFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
3987 "\n";
3989 cxxFile.Close();
3991 if (verbose)
3992 cout << "Completed " << cxxFile.GetFilePath() << endl;
3994 if (!cxxFile.Open(path, psprintf("_%u", i/classesPerFile+1), ".cxx"))
3995 return;
3997 cxxFile << "#include <ptlib.h>\n"
3998 "#include \"" << headerPrefix << headerName << "\"\n"
3999 "\n";
4001 if (useNamespaces)
4002 cxxFile << "using namespace " << moduleName << ";\n"
4003 "\n";
4004 cxxFile << "#define new PNEW\n"
4005 "\n"
4006 "\n";
4008 cxxFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
4012 if (types[i].HasParameters()) {
4013 PStringStream dummy;
4014 types[i].GenerateCplusplus(hdrFile, dummy);
4016 else
4017 types[i].GenerateCplusplus(hdrFile, cxxFile);
4021 // Close off the files
4022 if (useNamespaces)
4023 hdrFile << "};\n"
4024 "\n";
4026 hdrFile << "#endif // __" << moduleName.ToUpper() << "_H\n"
4027 "\n";
4029 hdrFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
4030 "\n";
4032 cxxFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
4033 "\n";
4035 if (verbose)
4036 cout << "Completed " << cxxFile.GetFilePath() << endl;
4040 //////////////////////////////////////////////////////////////////////////////