Added a parameter to semaphore constructor to avoid ambiguity
[pwlib.git] / tools / asnparser / main.cxx
blob2dfb44846a2abdf99a05c715ae0a253417a8cde9
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.47 2004/02/17 10:24:04 rjongbloed
34 * Updated version number so will rebuild ASN files.
36 * Revision 1.46 2004/02/17 09:38:24 csoutheren
37 * Added change to remove duplicate forward declarations
38 * See SourceForge bug 832245
39 * Thanks to Vyacheslav E. Andrejev
41 * Revision 1.45 2003/10/03 00:13:04 rjongbloed
42 * Added ability to specify CHOICE field selection by function rather than operator as the operator technique does not work with some dumb compilers.
43 * Added ability to specify that the header file name be different from the module name and module prefix string.
45 * Revision 1.44 2003/02/27 04:05:30 robertj
46 * Added ability to have alternate directories for header file
47 * includes in generated C++ code.
48 * Added constructors to PASN_OctetString descendant classes to help
49 * with doing simple assignments.
51 * Revision 1.43 2003/02/26 01:57:44 robertj
52 * Added XML encoding rules to ASN system, thanks Federico Pinna
54 * Revision 1.42 2003/02/19 14:18:55 craigs
55 * Fixed ifdef problem with multipart cxx files
57 * Revision 1.41 2003/02/18 10:50:41 craigs
58 * Added minor optimisation of outputted ASN code
59 * Added automatic insertion of defines to allow disabling of generated code
61 * Revision 1.40 2002/11/27 11:42:52 robertj
62 * Rearranged code to avoid GNU compiler problem.
63 * Changed new classheader parameters to be full C literal like string for
64 * improved backslash conversion.
65 * Incremented version number.
67 * Revision 1.39 2002/11/26 11:39:10 craigs
68 * Added option to allow adding functions to generated header files
70 * Revision 1.38 2002/09/16 01:08:59 robertj
71 * Added #define so can select if #pragma interface/implementation is used on
72 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
74 * Revision 1.37 2001/10/02 00:56:14 robertj
75 * Fixed problem with autonumering enumerated types.
77 * Revision 1.36 2001/08/06 01:39:02 robertj
78 * Added assignement operator with RHS of PASN_BMPString to classes
79 * descended from PASN_BMPString.
81 * Revision 1.35 2001/08/03 09:01:02 robertj
82 * Added assignement operator with RHS of PWORDArray to classes
83 * descended from PASN_BMPString.
85 * Revision 1.34 2001/06/14 02:09:20 robertj
86 * Corrected support for ASN object class type reference constructs
87 * ie TYPE-IDENTIFIER.&Type encoded as octet string.
89 * Revision 1.33 2001/04/26 08:15:58 robertj
90 * Fixed problem with ASN compile of single constraints on enumerations.
92 * Revision 1.32 2001/04/23 04:40:14 robertj
93 * Added ASN standard types GeneralizedTime and UTCTime
95 * Revision 1.31 2001/02/22 23:31:42 robertj
96 * Fixed display of version number just added.
98 * Revision 1.30 2001/02/22 22:31:01 robertj
99 * Added command line flag to display version number only.
101 * Revision 1.29 2000/10/12 23:11:48 robertj
102 * Fixed problem with BER encoding of ASN with optional fields.
104 * Revision 1.28 2000/06/26 13:14:46 robertj
105 * Nucleus++ port.
107 * Revision 1.27 2000/03/21 21:23:23 robertj
108 * Added option to rename imported module names, allows include filename matching.
110 * Revision 1.26 2000/01/19 12:33:07 robertj
111 * Fixed parsing of OID's in IMPORTS section.
113 * Revision 1.25 2000/01/19 03:38:12 robertj
114 * Fixed support for parsing multiple IMPORTS
116 * Revision 1.24 1999/09/18 04:17:40 robertj
117 * Added generation of C++ inlines for some functions.
118 * Optimised CreateObject() switch statements, collapsing common cases.
120 * Revision 1.23 1999/09/18 02:42:27 craigs
121 * Added optimisation to collapse switch arms in CreateObject functions
123 * Revision 1.22 1999/09/07 09:56:04 robertj
124 * Fixed failure to put "using anmespace" in every generated .cxx file.
126 * Revision 1.21 1999/08/28 01:48:55 robertj
127 * Fixed anomaly to always include non-optional extensions in encodings.
129 * Revision 1.20 1999/08/09 13:02:36 robertj
130 * Added ASN compiler #defines for backward support of pre GCC 2.9 compilers.
131 * Added ASN compiler #defines to reduce its memory footprint.
132 * Added ASN compiler code generation of assignment operators for string classes.
134 * Revision 1.19 1999/07/22 06:48:55 robertj
135 * Added comparison operation to base ASN classes and compiled ASN code.
136 * Added support for ANY type in ASN parser.
138 * Revision 1.18 1999/07/06 05:00:26 robertj
139 * Incremented release number
141 * Revision 1.17 1999/07/01 12:21:46 robertj
142 * Changed PASN_Choice cast operators so no longer "break" const-ness of object.
144 * Revision 1.16 1999/06/30 08:57:19 robertj
145 * Fixed bug in encodeing sequence of constrained primitive type. Constraint not set.
146 * Fixed bug in not emitting namespace use clause.
147 * Added "normalisation" of separate sequence of <base type> to be single class.
149 * Revision 1.15 1999/06/14 13:00:15 robertj
150 * Fixed bug in code generation for string constraints.
152 * Revision 1.14 1999/06/09 06:58:09 robertj
153 * Adjusted heading comments.
155 * Revision 1.13 1999/06/09 02:07:49 robertj
156 * Fixed backward compatibility of generated template code with G++ 2.7.x
158 * Revision 1.12 1999/06/07 01:56:25 robertj
159 * Added header comment on license.
163 #include <ptlib.h>
165 #include "main.h"
166 #include "asn_grammar.h"
169 #define MAJOR_VERSION 1
170 #define MINOR_VERSION 8
171 #define BUILD_TYPE ReleaseCode
172 #define BUILD_NUMBER 1
175 unsigned lineNumber;
176 PString fileName;
178 unsigned fatals, warnings;
180 extern FILE * yyin;
181 extern int yydebug;
182 extern int LexEcho;
184 ModuleDefinition * Module;
187 static const char * UniversalTagClassNames[] = {
188 "UniversalTagClass",
189 "ApplicationTagClass",
190 "ContextSpecificTagClass",
191 "PrivateTagClass"
194 static const char * UniversalTagNames[] = {
195 NULL,
196 "UniversalBoolean",
197 "UniversalInteger",
198 "UniversalBitString",
199 "UniversalOctetString",
200 "UniversalNull",
201 "UniversalObjectId",
202 "UniversalObjectDescriptor",
203 "UniversalExternalType",
204 "UniversalReal",
205 "UniversalEnumeration",
206 "UniversalEmbeddedPDV",
207 NULL,
208 NULL,
209 NULL,
210 NULL,
211 "UniversalSequence",
212 "UniversalSet",
213 "UniversalNumericString",
214 "UniversalPrintableString",
215 "UniversalTeletexString",
216 "UniversalVideotexString",
217 "UniversalIA5String",
218 "UniversalUTCTime",
219 "UniversalGeneralisedTime",
220 "UniversalGraphicString",
221 "UniversalVisibleString",
222 "UniversalGeneralString",
223 "UniversalUniversalString",
224 NULL,
225 "UniversalBMPString"
229 static const char * const StandardClasses[] = {
230 "PASN_Null",
231 "PASN_Boolean",
232 "PASN_Integer",
233 "PASN_Enumeration",
234 "PASN_Real",
235 "PASN_ObjectId",
236 "PASN_BitString",
237 "PASN_OctetString",
238 "PASN_NumericString",
239 "PASN_PrintableString",
240 "PASN_VisibleString",
241 "PASN_IA5String",
242 "PASN_GeneralString",
243 "PASN_BMPString",
244 "PASN_Sequence"
248 /////////////////////////////////////////
250 // yyerror
251 // required function for flex
254 void yyerror(char * str)
256 extern char * yytext;
257 PError << StdError(Fatal) << str << " near token \"" << yytext <<"\"\n";
260 ostream & operator<<(ostream & out, const StdError & e)
262 out << fileName << '(' << lineNumber << ") : ";
263 if (e.e == Fatal) {
264 fatals++;
265 out << "error";
267 else {
268 warnings++;
269 out << "warning";
271 return out << ": ";
275 /////////////////////////////////////////////////////////
277 // Utility
280 static PString MakeIdentifierC(const PString & identifier)
282 PString s = identifier;
283 s.Replace("-", "_", TRUE);
284 return s;
288 class OutputFile : public PTextFile
290 PCLASSINFO(OutputFile, PTextFile);
291 public:
292 ~OutputFile() { Close(); }
294 BOOL Open(const PFilePath & path, const PString & suffix, const char * extension);
295 BOOL Close();
299 BOOL OutputFile::Open(const PFilePath & path,
300 const PString & suffix,
301 const char * extension)
303 PFilePath fn = path.GetDirectory() + path.GetTitle() + suffix;
304 fn.SetType(extension);
306 if (PTextFile::Open(fn, WriteOnly))
307 *this << "//\n"
308 "// " << GetFilePath().GetFileName() << "\n"
309 "//\n"
310 "// Code automatically generated by asnparse.\n"
311 "//\n"
312 "\n";
313 else
314 PError << PProcess::Current().GetName() << ": cannot create \""
315 << GetFilePath() << "\" :" << GetErrorText() << endl;
317 return IsOpen();
321 BOOL OutputFile::Close()
323 if (IsOpen())
324 *this << "\n"
325 "// End of " << GetFilePath().GetFileName() << '\n';
327 return PTextFile::Close();
331 /////////////////////////////////////////////////////////
333 // Application
336 class App : public PProcess
338 PCLASSINFO(App, PProcess);
339 public:
340 App();
341 void Main();
342 BOOL SetClassHeaderFile(PArgList & args);
343 BOOL SetClassHeader(PArgList & args);
344 void OutputAdditionalHeaders(ostream & hdr, const PString & className);
345 protected:
346 PStringToString classToHeader;
349 PCREATE_PROCESS(App);
351 App::App()
352 : PProcess("Equivalence", "ASNParse", MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
356 void App::Main()
358 cout << GetName() << " version " << GetVersion(TRUE)
359 << " for " << GetOSClass() << ' ' << GetOSName()
360 << " by " << GetManufacturer() << endl;
362 PArgList & args = GetArguments();
363 args.Parse("c-c++."
364 "d-debug."
365 "e-echo."
366 "h-hdr-prefix:"
367 "i-inlines."
368 "m-module:"
369 "n-namespace."
370 "o-output:"
371 "r-rename:"
372 "s-split;"
373 "V-version."
374 "v-verbose."
375 "x-xml."
376 "-no-operators."
377 "-classheader:"
378 "-classheaderfile:");
380 if (args.HasOption('V'))
381 return;
383 unsigned numFiles = 1;
384 if (args.HasOption('s')) {
385 PString numFilesStr = args.GetOptionString('s');
386 if (numFilesStr.IsEmpty())
387 numFiles = 2;
388 else
389 numFiles = numFilesStr.AsUnsigned();
392 if (args.GetCount() < 1 || args.GetCount() > 1 || numFiles == 0) {
393 PError << "usage: asnparse [options] asnfile\n"
394 " -V --version Display version and exit\n"
395 " -v --verbose Verbose output (multiple times for more verbose)\n"
396 " -e --echo Echo input file\n"
397 " -d --debug Debug output (copious!)\n"
398 " -c --c++ Generate C++ files\n"
399 " -n --namespace Use C++ namespace\n"
400 " -h --hdr-prefix str Prefix for C++ include of header (eg directory)\n"
401 " -i --inlines Use C++ inlines\n"
402 " -s[n] --split[n] Split output into n (default 2) files\n"
403 " -m --module name Module name prefix/namespace\n"
404 " -r --rename args Rename import module where arg is:\n"
405 " from=name[,prefix[,fname]]\n"
406 " from is module name in ASN file\n"
407 " name is target header file name\n"
408 " prefix is optional prefix for include\n"
409 " (eg header directory)\n"
410 " fname is optional base name for header files\n"
411 " --no-operators Generate functions instead of operators for choice\n"
412 " sub-object extraction.\n"
413 " -x --xml X.693 support (XER)\n"
414 " -o --output file Output filename/directory\n"
415 << endl;
416 return;
419 PTextFile prcFile;
420 if (!prcFile.Open(args[0], PFile::ReadOnly)) {
421 PError << GetName() << ": cannot open \""
422 << prcFile.GetFilePath() << "\" :" << prcFile.GetErrorText() << endl;
423 return;
426 if (args.HasOption('d'))
427 yydebug = 1;
428 if (args.HasOption('e'))
429 LexEcho = TRUE;
431 fileName = prcFile.GetFilePath();
432 lineNumber = 1;
433 fatals = 0;
434 warnings = 0;
436 if (args.HasOption("classheaderfile")) {
437 if (!SetClassHeaderFile(args))
438 return;
441 if (args.HasOption("classheader")) {
442 if (!SetClassHeader(args))
443 return;
446 if (args.HasOption('v'))
447 cout << "Parsing..." << endl;
449 yyin = _fdopen(prcFile.GetHandle(), "r");
450 PAssertNULL(yyin);
451 yyparse();
453 if (Module != NULL) {
454 if (args.GetOptionCount('v') > 1)
455 PError << "Module " << *Module << endl;
457 if (args.HasOption('c'))
458 Module->GenerateCplusplus(args.GetOptionString('o', args[0]),
459 args.GetOptionString('m'),
460 args.GetOptionString('h'),
461 numFiles,
462 args.HasOption('n'),
463 args.HasOption('i'),
464 !args.HasOption("no-operators"),
465 args.HasOption('v'));
470 BOOL App::SetClassHeaderFile(PArgList & args)
472 PStringArray lines = args.GetOptionString("classheaderfile").Lines();
473 if (lines.IsEmpty()) {
474 PError << GetName() << ": malformed --classheaderfile option\n";
475 return FALSE;
478 for (PINDEX i = 0; i < lines.GetSize(); i++) {
479 PString str = lines[i];
480 PINDEX pos = str.Find("=");
481 if (pos == P_MAX_INDEX) {
482 PError << GetName() << ": malformed --classheaderfile option\n";
483 return FALSE;
486 PFilePath fn = str.Right(pos+1);
487 PTextFile file(fn, PFile::ReadOnly);
488 if (!file.IsOpen()) {
489 PError << GetName() << ": cannot open file required for --classheaderfile option \"" << fn
490 << "\" :" << file.GetErrorText() << '\n';
491 return FALSE;
494 PString text;
495 PString line;
496 while (file.ReadLine(line))
497 text += PString(PString::Literal, (const char *)line) + '\n';
498 classToHeader.SetAt(str.Left(pos), text);
501 return TRUE;
505 BOOL App::SetClassHeader(PArgList & args)
507 PStringArray lines = args.GetOptionString("classheader").Lines();
508 if (lines.IsEmpty()) {
509 PError << GetName() << ": malformed --classheader option\n";
510 return FALSE;
513 for (PINDEX i = 0; i < lines.GetSize(); i++) {
514 PString str = lines[i];
515 PINDEX pos = str.Find("=");
516 if (pos == P_MAX_INDEX) {
517 PError << GetName() << ": malformed --classheader option\n";
518 return FALSE;
521 PString text(PString::Literal, (const char *)str.Mid(pos+1));
522 classToHeader.SetAt(str.Left(pos), text);
525 return TRUE;
529 void App::OutputAdditionalHeaders(ostream & hdr, const PString & className)
531 if (classToHeader.Contains(className)) {
532 hdr << "// following code added by command line option\n"
533 "\n"
534 << classToHeader[className] << "\n"
535 "\n"
536 "// end of added code\n"
537 "\n";
541 /////////////////////////////////////////
543 // miscellaneous
546 class indent
548 public:
549 indent() { }
550 friend ostream & operator<<(ostream & s, const indent &)
551 { return s << setw(Module->GetIndentLevel()*3) << ' '; }
555 /////////////////////////////////////////
557 // intermediate structures from parser
560 NamedNumber::NamedNumber(PString * nam)
561 : name(*nam)
563 delete nam;
564 number = 0;
565 autonumber = TRUE;
569 NamedNumber::NamedNumber(PString * nam, int num)
570 : name(*nam)
572 delete nam;
573 number = num;
574 autonumber = FALSE;
578 NamedNumber::NamedNumber(PString * nam, const PString & ref)
579 : name(*nam), reference(ref)
581 delete nam;
582 number = 0;
583 autonumber = FALSE;
587 void NamedNumber::PrintOn(ostream & strm) const
589 strm << name << " (";
590 if (reference.IsEmpty())
591 strm << number;
592 else
593 strm << reference;
594 strm << ')';
598 void NamedNumber::SetAutoNumber(const NamedNumber & prev)
600 if (autonumber) {
601 number = prev.number + 1;
602 autonumber = FALSE;
607 /////////////////////////////////////////////////////////
609 Tag::Tag(unsigned tagNum)
611 type = Universal;
612 number = tagNum;
613 mode = Module->GetDefaultTagMode();
617 const char * Tag::classNames[] = {
618 "UNIVERSAL", "APPLICATION", "CONTEXTSPECIFIC", "PRIVATE"
622 const char * Tag::modeNames[] = {
623 "IMPLICIT", "EXPLICIT", "AUTOMATIC"
627 void Tag::PrintOn(ostream & strm) const
629 if (type != Universal || number != IllegalUniversalTag) {
630 strm << '[';
631 if (type != ContextSpecific)
632 strm << classNames[type] << ' ';
633 strm << number << "] " << modeNames[mode] << ' ';
638 /////////////////////////////////////////////////////////
640 Constraint::Constraint(ConstraintElementBase * elmt)
642 standard.Append(elmt);
643 extendable = FALSE;
647 Constraint::Constraint(ConstraintElementList * stnd, BOOL extend, ConstraintElementList * ext)
649 if (stnd != NULL) {
650 standard = *stnd;
651 delete stnd;
653 extendable = extend;
654 if (ext != NULL) {
655 extensions = *ext;
656 delete ext;
661 void Constraint::PrintOn(ostream & strm) const
663 strm << '(';
664 for (PINDEX i = 0; i < standard.GetSize(); i++)
665 strm << standard[i];
666 if (extendable) {
667 strm << indent();
668 if (standard.GetSize() > 0)
669 strm << ", ";
670 strm << "..., ";
671 for (PINDEX i = 0; i < extensions.GetSize(); i++)
672 strm << extensions[i];
674 strm << ')';
678 void Constraint::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
680 switch (standard.GetSize()) {
681 case 0 :
682 return;
683 case 1 :
684 break;
685 default :
686 PError << StdError(Warning) << "unsupported UNION constraints, ignored." << endl;
689 if (extensions.GetSize() > 0)
690 PError << StdError(Warning) << "unsupported extension constraints, ignored." << endl;
692 PString fn2 = fn;
693 if (fn.Find("PASN_Object::") == P_MAX_INDEX) {
694 if (extendable)
695 fn2 += "PASN_Object::ExtendableConstraint";
696 else
697 fn2 += "PASN_Object::FixedConstraint";
700 standard[0].GenerateCplusplus(fn2, hdr, cxx);
704 BOOL Constraint::ReferencesType(const TypeBase & type)
706 PINDEX i;
708 for (i = 0; i < standard.GetSize(); i++) {
709 if (standard[i].ReferencesType(type))
710 return TRUE;
713 for (i = 0; i < extensions.GetSize(); i++) {
714 if (extensions[i].ReferencesType(type))
715 return TRUE;
718 return FALSE;
722 /////////////////////////////////////////////////////////
724 ConstraintElementBase::ConstraintElementBase()
726 exclusions = NULL;
730 void ConstraintElementBase::GenerateCplusplus(const PString &, ostream &, ostream &)
732 PError << StdError(Warning) << "unsupported constraint, ignored." << endl;
736 BOOL ConstraintElementBase::ReferencesType(const TypeBase &)
738 return FALSE;
742 /////////////////////////////////////////////////////////
744 ConstrainAllConstraintElement::ConstrainAllConstraintElement(ConstraintElementBase * excl)
746 SetExclusions(excl);
750 /////////////////////////////////////////////////////////
752 ElementListConstraintElement::ElementListConstraintElement(ConstraintElementList * list)
753 : elements(*list)
755 delete list;
759 void ElementListConstraintElement::PrintOn(ostream & strm) const
761 elements.PrintOn(strm);
765 void ElementListConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
767 for (PINDEX i = 0; i < elements.GetSize(); i++)
768 elements[i].GenerateCplusplus(fn, hdr, cxx);
772 BOOL ElementListConstraintElement::ReferencesType(const TypeBase & type)
774 for (PINDEX i = 0; i < elements.GetSize(); i++) {
775 if (elements[i].ReferencesType(type))
776 return TRUE;
778 return FALSE;
782 /////////////////////////////////////////////////////////
784 SingleValueConstraintElement::SingleValueConstraintElement(ValueBase * val)
786 value = val;
790 SingleValueConstraintElement::~SingleValueConstraintElement()
792 delete value;
796 void SingleValueConstraintElement::PrintOn(ostream & strm) const
798 strm << *value;
802 void SingleValueConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
804 cxx << fn << ", ";
805 value->GenerateCplusplus(hdr, cxx);
806 cxx << ");\n";
810 /////////////////////////////////////////////////////////
812 ValueRangeConstraintElement::ValueRangeConstraintElement(ValueBase * lowerBound, ValueBase * upperBound)
814 lower = lowerBound;
815 upper = upperBound;
819 ValueRangeConstraintElement::~ValueRangeConstraintElement()
821 delete lower;
822 delete upper;
826 void ValueRangeConstraintElement::PrintOn(ostream & strm) const
828 strm << *lower << ".." << *upper;
832 void ValueRangeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
834 cxx << fn << ", ";
835 lower->GenerateCplusplus(hdr, cxx);
836 cxx << ", ";
837 upper->GenerateCplusplus(hdr, cxx);
838 cxx << ");\n";
842 /////////////////////////////////////////////////////////
844 SubTypeConstraintElement::SubTypeConstraintElement(TypeBase * typ)
846 subtype = typ;
850 SubTypeConstraintElement::~SubTypeConstraintElement()
852 delete subtype;
856 void SubTypeConstraintElement::PrintOn(ostream & strm) const
858 strm << subtype->GetTypeName();
862 void SubTypeConstraintElement::GenerateCplusplus(const PString &, ostream & hdr, ostream &)
864 hdr << subtype->GetTypeName();
868 BOOL SubTypeConstraintElement::ReferencesType(const TypeBase & type)
870 return subtype->ReferencesType(type);
874 /////////////////////////////////////////////////////////
876 NestedConstraintConstraintElement::NestedConstraintConstraintElement(Constraint * con)
878 constraint = con;
882 NestedConstraintConstraintElement::~NestedConstraintConstraintElement()
884 delete constraint;
888 BOOL NestedConstraintConstraintElement::ReferencesType(const TypeBase & type)
890 if (constraint == NULL)
891 return FALSE;
893 return constraint->ReferencesType(type);
897 /////////////////////////////////////////////////////////
899 SizeConstraintElement::SizeConstraintElement(Constraint * constraint)
900 : NestedConstraintConstraintElement(constraint)
905 void SizeConstraintElement::PrintOn(ostream & strm) const
907 strm << "SIZE" << *constraint;
911 void SizeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
913 constraint->GenerateCplusplus(fn, hdr, cxx);
917 /////////////////////////////////////////////////////////
919 FromConstraintElement::FromConstraintElement(Constraint * constraint)
920 : NestedConstraintConstraintElement(constraint)
925 void FromConstraintElement::PrintOn(ostream & strm) const
927 strm << "FROM" << *constraint;
931 void FromConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
933 PString newfn = fn;
934 newfn.Replace("SetConstraints(", "SetCharacterSet(");
935 constraint->GenerateCplusplus(newfn, hdr, cxx);
939 /////////////////////////////////////////////////////////
941 WithComponentConstraintElement::WithComponentConstraintElement(PString * newName,
942 Constraint * constraint,
943 int pres)
944 : NestedConstraintConstraintElement(constraint)
946 if (newName != NULL) {
947 name = *newName;
948 delete newName;
951 presence = pres;
955 void WithComponentConstraintElement::PrintOn(ostream & strm) const
957 if (name.IsEmpty())
958 strm << "WITH COMPONENT";
959 else
960 strm << name;
962 if (constraint != NULL)
963 strm << *constraint;
965 switch (presence) {
966 case Present :
967 strm << " PRESENT";
968 break;
969 case Absent :
970 strm << " ABSENT";
971 break;
972 case Optional :
973 strm << " OPTIONAL";
974 break;
979 void WithComponentConstraintElement::GenerateCplusplus(const PString &, ostream &, ostream & cxx)
981 if (presence == Present)
982 cxx << " IncludeOptionalField(e_" << name << ");\n";
986 /////////////////////////////////////////////////////////
988 InnerTypeConstraintElement::InnerTypeConstraintElement(ConstraintElementList * list,
989 BOOL part)
990 : ElementListConstraintElement(list)
992 partial = part;
996 void InnerTypeConstraintElement::PrintOn(ostream & strm) const
998 strm << "WITH COMPONENTS { ";
1000 if (partial)
1001 strm << "..., ";
1003 for (PINDEX i = 0; i < elements.GetSize(); i++) {
1004 if (i > 0)
1005 strm << ", ";
1006 elements[i].PrintOn(strm);
1009 strm << " }";
1013 void InnerTypeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
1015 for (PINDEX i = 0; i < elements.GetSize(); i++)
1016 elements[i].GenerateCplusplus(fn, hdr, cxx);
1020 /////////////////////////////////////////////////////////
1022 UserDefinedConstraintElement::UserDefinedConstraintElement(TypesList * t)
1024 if (t != NULL) {
1025 types = *t;
1026 delete t;
1031 void UserDefinedConstraintElement::PrintOn(ostream & strm) const
1033 strm << "CONSTRAINED BY { ";
1034 for (PINDEX i = 0; i < types.GetSize(); i++) {
1035 if (i > 0)
1036 strm << ", ";
1037 strm << types[i].GetTypeName();
1039 strm << " }";
1043 void UserDefinedConstraintElement::GenerateCplusplus(const PString &, ostream &, ostream &)
1048 /////////////////////////////////////////////////////////
1050 TypeBase::TypeBase(unsigned tagNum)
1051 : tag(tagNum), defaultTag(tagNum)
1053 isOptional = FALSE;
1054 defaultValue = NULL;
1055 isGenerated = FALSE;
1059 TypeBase::TypeBase(TypeBase * copy)
1060 : name(copy->name),
1061 identifier(MakeIdentifierC(name)),
1062 tag(copy->tag),
1063 defaultTag(copy->tag)
1065 isOptional = copy->isOptional;
1066 defaultValue = NULL;
1067 isGenerated = FALSE;
1071 PObject::Comparison TypeBase::Compare(const PObject & obj) const
1073 return name.Compare(((const TypeBase &)obj).name);
1077 void TypeBase::PrintOn(ostream & strm) const
1079 PrintStart(strm);
1080 PrintFinish(strm);
1084 void TypeBase::PrintStart(ostream & strm) const
1086 strm << indent();
1087 if (!name) {
1088 strm << name;
1089 if (!parameters.IsEmpty()) {
1090 strm << " { ";
1091 for (PINDEX i = 0; i < parameters.GetSize(); i++) {
1092 if (i > 0)
1093 strm << ", ";
1094 strm << parameters[i];
1096 strm << " } ";
1098 strm << ": ";
1100 strm << tag << GetClass() << ' ';
1101 Module->SetIndentLevel(1);
1105 void TypeBase::PrintFinish(ostream & strm) const
1107 Module->SetIndentLevel(-1);
1108 strm << ' ' << constraints;
1109 if (isOptional)
1110 strm << " OPTIONAL";
1111 if (defaultValue != NULL)
1112 strm << " DEFAULT " << *defaultValue;
1113 strm << '\n';
1117 int TypeBase::GetIdentifierTokenContext() const
1119 return IDENTIFIER;
1123 int TypeBase::GetBraceTokenContext() const
1125 return '{';
1129 void TypeBase::SetName(PString * newName)
1131 name = *newName;
1132 delete newName;
1133 identifier = MakeIdentifierC(name);
1137 void TypeBase::AdjustIdentifier()
1139 identifier = Module->GetPrefix() + MakeIdentifierC(name);
1143 void TypeBase::SetTag(Tag::Type type, unsigned num, Tag::Mode mode)
1145 tag.type = type;
1146 tag.number = num;
1147 tag.mode = mode;
1151 void TypeBase::SetParameters(PStringList * list)
1153 parameters = *list;
1154 delete list;
1158 void TypeBase::MoveConstraints(TypeBase * from)
1160 from->constraints.DisallowDeleteObjects();
1162 while (!from->constraints.IsEmpty())
1163 constraints.Append(from->constraints.RemoveAt(0));
1165 from->constraints.AllowDeleteObjects();
1169 void TypeBase::FlattenUsedTypes()
1174 TypeBase * TypeBase::FlattenThisType(const TypeBase &)
1176 return this;
1180 BOOL TypeBase::IsChoice() const
1182 return FALSE;
1186 BOOL TypeBase::IsParameterizedType() const
1188 return FALSE;
1192 BOOL TypeBase::IsPrimitiveType() const
1194 return TRUE;
1198 void TypeBase::GenerateCplusplus(ostream & hdr, ostream & cxx)
1200 BeginGenerateCplusplus(hdr, cxx);
1202 // Close off the constructor implementation
1203 cxx << ")\n"
1204 "{\n";
1205 GenerateCplusplusConstraints(PString(), hdr, cxx);
1207 EndGenerateCplusplus(hdr, cxx);
1211 void TypeBase::GenerateForwardDecls(ostream &)
1216 void TypeBase::GenerateOperators(ostream &, ostream &, const TypeBase &)
1221 PString TypeBase::GetTypeName() const
1223 return GetAncestorClass();
1227 BOOL TypeBase::CanReferenceType() const
1229 return FALSE;
1233 BOOL TypeBase::ReferencesType(const TypeBase &)
1235 return FALSE;
1239 void TypeBase::SetImportPrefix(const PString &)
1244 BOOL TypeBase::IsParameterisedImport() const
1246 return FALSE;
1250 void TypeBase::BeginGenerateCplusplus(ostream & hdr, ostream & cxx)
1252 classNameString = GetIdentifier();
1254 if (!parameters.IsEmpty()) {
1255 templatePrefix = "template <";
1256 classNameString += '<';
1257 for (PINDEX i = 0; i < parameters.GetSize(); i++) {
1258 if (i > 0) {
1259 templatePrefix += ", ";
1260 classNameString += ", ";
1262 PString ident = MakeIdentifierC(parameters[i]);
1263 templatePrefix += "class " + ident;
1264 classNameString += ident;
1266 templatePrefix += ">\n";
1267 classNameString += '>';
1270 // Output header file declaration of class
1271 hdr << "//\n"
1272 "// " << GetName() << "\n"
1273 "//\n"
1274 "\n";
1275 GenerateForwardDecls(hdr);
1276 hdr << templatePrefix
1277 << "class " << GetIdentifier() << " : public " << GetTypeName() << "\n"
1278 "{\n"
1279 "#ifndef PASN_LEANANDMEAN\n"
1280 " PCLASSINFO(" << GetIdentifier() << ", " << GetTypeName() << ");\n"
1281 "#endif\n"
1282 " public:\n"
1283 " " << GetIdentifier() << "(unsigned tag = ";
1284 if (tag.type == Tag::Universal &&
1285 tag.number < PARRAYSIZE(UniversalTagNames) &&
1286 UniversalTagNames[tag.number] != NULL)
1287 hdr << UniversalTagNames[tag.number];
1288 else
1289 hdr << tag.number;
1290 hdr << ", TagClass tagClass = " << UniversalTagClassNames[tag.type] << ");\n\n";
1292 App & app = (App &)PProcess::Current();
1293 app.OutputAdditionalHeaders(hdr, GetIdentifier());
1295 // Output cxx file implementation of class
1296 cxx << "//\n"
1297 "// " << GetName() << "\n"
1298 "//\n"
1299 "\n"
1300 << GetTemplatePrefix()
1301 << GetClassNameString() << "::" << GetIdentifier() << "(unsigned tag, PASN_Object::TagClass tagClass)\n"
1302 " : " << GetTypeName() << "(tag, tagClass";
1306 void TypeBase::EndGenerateCplusplus(ostream & hdr, ostream & cxx)
1308 cxx << "}\n"
1309 "\n"
1310 "\n";
1312 GenerateOperators(hdr, cxx, *this);
1314 // Output header file declaration of class
1315 hdr << " PObject * Clone() const;\n"
1316 "};\n"
1317 "\n"
1318 "\n";
1320 // Output cxx file implementation of class
1321 cxx << GetTemplatePrefix()
1322 << "PObject * " << GetClassNameString() << "::Clone() const\n"
1323 "{\n"
1324 "#ifndef PASN_LEANANDMEAN\n"
1325 " PAssert(IsClass(" << GetClassNameString() << "::Class()), PInvalidCast);\n"
1326 "#endif\n"
1327 " return new " << GetClassNameString() << "(*this);\n"
1328 "}\n"
1329 "\n"
1330 "\n";
1332 isGenerated = TRUE;
1336 void TypeBase::GenerateCplusplusConstructor(ostream &, ostream & cxx)
1338 cxx << '(';
1339 if (HasNonStandardTag()) {
1340 if (tag.type == Tag::Universal &&
1341 tag.number < PARRAYSIZE(UniversalTagNames) &&
1342 UniversalTagNames[tag.number] != NULL)
1343 cxx << UniversalTagNames[tag.number];
1344 else
1345 cxx << tag.number;
1346 cxx << ", " << UniversalTagClassNames[tag.type];
1348 cxx << ')';
1352 void TypeBase::GenerateCplusplusConstraints(const PString & prefix, ostream & hdr, ostream & cxx)
1354 for (PINDEX i = 0; i < constraints.GetSize(); i++)
1355 constraints[i].GenerateCplusplus(" " + prefix + "SetConstraints(", hdr, cxx);
1359 /////////////////////////////////////////////////////////
1361 DefinedType::DefinedType(PString * name, BOOL parameter)
1362 : TypeBase(Tag::IllegalUniversalTag),
1363 referenceName(*name)
1365 delete name;
1366 baseType = NULL;
1367 unresolved = !parameter;
1371 DefinedType::DefinedType(TypeBase * refType, TypeBase * bType)
1372 : TypeBase(refType),
1373 referenceName(bType->GetName())
1375 MoveConstraints(refType);
1377 baseType = bType;
1378 unresolved = FALSE;
1382 DefinedType::DefinedType(TypeBase * refType, const PString & refName)
1383 : TypeBase(refType)
1385 MoveConstraints(refType);
1386 ConstructFromType(refType, refName);
1390 DefinedType::DefinedType(TypeBase * refType, const TypeBase & parent)
1391 : TypeBase(refType)
1393 if (!name)
1394 ConstructFromType(refType, parent.GetName() + '_' + name);
1395 else
1396 ConstructFromType(refType, parent.GetName() + "_subtype");
1400 void DefinedType::ConstructFromType(TypeBase * refType, const PString & name)
1402 referenceName = name;
1403 refType->SetName(new PString(name));
1405 Module->AppendType(refType);
1407 baseType = refType;
1408 unresolved = FALSE;
1412 void DefinedType::PrintOn(ostream & strm) const
1414 PrintStart(strm);
1415 strm << referenceName << ' ';
1416 PrintFinish(strm);
1420 BOOL DefinedType::CanReferenceType() const
1422 return TRUE;
1426 BOOL DefinedType::IsChoice() const
1428 if (baseType != NULL)
1429 return baseType->IsChoice();
1430 return FALSE;
1434 BOOL DefinedType::IsParameterizedType() const
1436 if (baseType != NULL)
1437 return baseType->IsParameterizedType();
1438 return FALSE;
1442 BOOL DefinedType::ReferencesType(const TypeBase & type)
1444 if (unresolved) {
1445 unresolved = FALSE;
1447 if ((baseType = Module->FindType(referenceName)) == NULL)
1448 PError << StdError(Warning) << "unresolved symbol: " << referenceName << endl;
1449 else {
1450 if (!HasNonStandardTag())
1451 defaultTag = tag = baseType->GetTag();
1455 return type.GetName() == referenceName;
1459 void DefinedType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1461 if (baseType != NULL)
1462 baseType->GenerateOperators(hdr, cxx, actualType);
1466 const char * DefinedType::GetAncestorClass() const
1468 if (baseType != NULL)
1469 return baseType->GetAncestorClass();
1470 return NULL;
1474 PString DefinedType::GetTypeName() const
1476 if (baseType == NULL)
1477 return referenceName;
1479 if (HasConstraints() && baseType->IsPrimitiveType())
1480 return baseType->GetTypeName();
1482 return baseType->GetIdentifier();
1486 /////////////////////////////////////////////////////////
1488 ParameterizedType::ParameterizedType(PString * name, TypesList * args)
1489 : DefinedType(name, FALSE),
1490 arguments(*args)
1492 delete args;
1496 void ParameterizedType::PrintOn(ostream & strm) const
1498 PrintStart(strm);
1499 strm << referenceName << " { ";
1500 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1501 if (i > 0)
1502 strm << ", ";
1503 strm << arguments[i].GetTypeName();
1505 strm << " }";
1506 PrintFinish(strm);
1510 BOOL ParameterizedType::IsParameterizedType() const
1512 return TRUE;
1516 BOOL ParameterizedType::ReferencesType(const TypeBase & type)
1518 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1519 if (arguments[i].ReferencesType(type))
1520 return TRUE;
1523 return DefinedType::ReferencesType(type);
1527 PString ParameterizedType::GetTypeName() const
1529 PString typeName = DefinedType::GetTypeName();
1530 if (!arguments.IsEmpty()) {
1531 typeName += '<';
1532 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1533 if (i > 0)
1534 typeName += ", ";
1535 typeName += arguments[i].GetTypeName();
1537 typeName += '>';
1539 return typeName;
1543 /////////////////////////////////////////////////////////
1545 SelectionType::SelectionType(PString * name, TypeBase * base)
1546 : TypeBase(Tag::IllegalUniversalTag),
1547 selection(*name)
1549 delete name;
1550 baseType = PAssertNULL(base);
1554 SelectionType::~SelectionType()
1556 delete baseType;
1560 void SelectionType::PrintOn(ostream & strm) const
1562 PrintStart(strm);
1563 strm << selection << '<' << *baseType;
1564 PrintFinish(strm);
1568 void SelectionType::FlattenUsedTypes()
1570 baseType = baseType->FlattenThisType(*this);
1574 TypeBase * SelectionType::FlattenThisType(const TypeBase & parent)
1576 return new DefinedType(this, parent);
1580 void SelectionType::GenerateCplusplus(ostream &, ostream &)
1582 PError << StdError(Fatal) << "Cannot generate code for Selection type" << endl;
1583 isGenerated = TRUE;
1587 const char * SelectionType::GetAncestorClass() const
1589 return "";
1593 BOOL SelectionType::CanReferenceType() const
1595 return TRUE;
1599 BOOL SelectionType::ReferencesType(const TypeBase & type)
1601 return baseType->ReferencesType(type);
1605 /////////////////////////////////////////////////////////
1607 BooleanType::BooleanType()
1608 : TypeBase(Tag::UniversalBoolean)
1613 void BooleanType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1615 hdr << " " << actualType.GetIdentifier() << " & operator=(BOOL v)";
1616 if (Module->UsingInlines())
1617 hdr << " { SetValue(v); return *this; }\n";
1618 else {
1619 hdr << ";\n";
1620 cxx << actualType.GetTemplatePrefix()
1621 << actualType.GetIdentifier() << " & "
1622 << actualType.GetClassNameString() << "::operator=(BOOL v)\n"
1623 "{\n"
1624 " SetValue(v);\n"
1625 " return *this;\n"
1626 "}\n"
1627 "\n"
1628 "\n";
1633 const char * BooleanType::GetAncestorClass() const
1635 return "PASN_Boolean";
1639 /////////////////////////////////////////////////////////
1641 IntegerType::IntegerType()
1642 : TypeBase(Tag::UniversalInteger)
1647 IntegerType::IntegerType(NamedNumberList * lst)
1648 : TypeBase(Tag::UniversalInteger),
1649 allowedValues(*lst)
1651 delete lst;
1655 void IntegerType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1657 hdr << " " << actualType.GetIdentifier() << " & operator=(int v)";
1658 if (Module->UsingInlines())
1659 hdr << " { SetValue(v); return *this; }\n";
1660 else {
1661 hdr << ";\n";
1662 cxx << actualType.GetTemplatePrefix()
1663 << actualType.GetIdentifier() << " & "
1664 << actualType.GetClassNameString() << "::operator=(int v)\n"
1665 "{\n"
1666 " SetValue(v);\n"
1667 " return *this;\n"
1668 "}\n"
1669 "\n"
1670 "\n";
1673 hdr << " " << actualType.GetIdentifier() << " & operator=(unsigned v)";
1674 if (Module->UsingInlines())
1675 hdr << " { SetValue(v); return *this; }\n";
1676 else {
1677 hdr << ";\n";
1678 cxx << actualType.GetTemplatePrefix()
1679 << actualType.GetIdentifier() << " & "
1680 << actualType.GetClassNameString() << "::operator=(unsigned v)\n"
1681 "{\n"
1682 " SetValue(v);\n"
1683 " return *this;\n"
1684 "}\n"
1685 "\n"
1686 "\n";
1691 const char * IntegerType::GetAncestorClass() const
1693 return "PASN_Integer";
1697 /////////////////////////////////////////////////////////
1699 EnumeratedType::EnumeratedType(NamedNumberList * enums, BOOL extend, NamedNumberList * ext)
1700 : TypeBase(Tag::UniversalEnumeration),
1701 enumerations(*enums)
1703 numEnums = enums->GetSize();
1704 delete enums;
1705 extendable = extend;
1706 if (ext != NULL) {
1707 ext->DisallowDeleteObjects();
1708 for (PINDEX i = 0; i < ext->GetSize(); i++)
1709 enumerations.Append(ext->GetAt(i));
1710 delete ext;
1715 void EnumeratedType::PrintOn(ostream & strm) const
1717 PrintStart(strm);
1718 strm << '\n';
1719 PINDEX i;
1720 for (i = 0; i < numEnums; i++)
1721 strm << indent() << enumerations[i] << '\n';
1722 if (extendable) {
1723 strm << "...\n";
1724 for (; i < enumerations.GetSize(); i++)
1725 strm << indent() << enumerations[i] << '\n';
1727 PrintFinish(strm);
1731 TypeBase * EnumeratedType::FlattenThisType(const TypeBase & parent)
1733 return new DefinedType(this, parent);
1737 void EnumeratedType::GenerateCplusplus(ostream & hdr, ostream & cxx)
1739 PINDEX i;
1740 PArgList & args = PProcess::Current().GetArguments();
1741 BOOL xml_output = args.HasOption('x');
1743 BeginGenerateCplusplus(hdr, cxx);
1745 int maxEnumValue = 0;
1746 for (i = 0; i < enumerations.GetSize(); i++) {
1747 int num = enumerations[i].GetNumber();
1748 if (maxEnumValue < num)
1749 maxEnumValue = num;
1752 // Generate enumerations and complete the constructor implementation
1753 hdr << " enum Enumerations {\n";
1754 cxx << ", " << maxEnumValue << ", " << (extendable ? "TRUE" : "FALSE") << "\n"
1755 "#ifndef PASN_NOPRINTON\n"
1756 " , \"";
1758 int prevNum = -1;
1759 for (i = 0; i < enumerations.GetSize(); i++) {
1760 if (i > 0) {
1761 hdr << ",\n";
1762 cxx << " \"";
1765 hdr << " e_" << MakeIdentifierC(enumerations[i].GetName());
1766 cxx << enumerations[i].GetName();
1768 int num = enumerations[i].GetNumber();
1769 if (num != prevNum+1) {
1770 hdr << " = " << num;
1771 cxx << '=' << num;
1773 prevNum = num;
1775 cxx << " \"\n";
1778 hdr << "\n"
1779 " };\n"
1780 "\n";
1781 cxx << "#endif\n"
1782 " )\n"
1783 "{\n";
1784 GenerateCplusplusConstraints(PString(), hdr, cxx);
1786 if (xml_output)
1788 hdr << " BOOL DecodeXER(PXER_Stream & strm);\n"
1789 " void EncodeXER(PXER_Stream & strm) const;\n";
1791 cxx << "}\n"
1792 "\n"
1793 << GetTemplatePrefix()
1794 << "BOOL " << GetClassNameString() << "::DecodeXER(PXER_Stream & strm)\n"
1795 "{\n"
1796 " PXMLElement * elem = strm.GetCurrentElement();\n"
1797 " PXMLObject * sub_elem = elem->GetElement();\n"
1798 "\n"
1799 " if (!elem || !elem->IsElement())\n"
1800 " return FALSE;\n"
1801 "\n"
1802 " PCaselessString id = ((PXMLElement *)sub_elem)->GetName();\n"
1803 "\n"
1804 " ";
1806 for (i = 0 ; i < enumerations.GetSize() ; i++) {
1807 cxx << " if (id == \"" << enumerations[i].GetName() << "\") {\n"
1808 " value = " << enumerations[i].GetNumber() << ";\n"
1809 " return TRUE;\n"
1810 " }\n"
1811 " else";
1814 cxx << "\n"
1815 " return FALSE;\n"
1816 "}\n"
1817 "\n";
1819 cxx << GetTemplatePrefix()
1820 << "void " << GetClassNameString() << "::EncodeXER(PXER_Stream & strm) const\n"
1821 "{\n"
1822 " PXMLElement * elem = strm.GetCurrentElement();\n"
1823 " PString id;\n"
1824 "\n"
1825 " switch(value)\n"
1826 " {\n";
1828 for (i = 0 ; i < enumerations.GetSize() ; i++) {
1829 cxx << " case " << enumerations[i].GetNumber() << ":\n"
1830 " elem->AddChild(new PXMLElement(elem, \"" << enumerations[i].GetName() << "\"));\n"
1831 " break;\n";
1834 cxx << " default:\n"
1835 " break;\n"
1836 " }\n";
1839 EndGenerateCplusplus(hdr, cxx);
1843 void EnumeratedType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1845 hdr << " " << actualType.GetIdentifier() << " & operator=(unsigned v)";
1846 if (Module->UsingInlines())
1847 hdr << " { SetValue(v); return *this; }\n";
1848 else {
1849 hdr << ";\n";
1850 cxx << actualType.GetTemplatePrefix()
1851 << actualType.GetIdentifier() << " & "
1852 << actualType.GetClassNameString() << "::operator=(unsigned v)\n"
1853 "{\n"
1854 " SetValue(v);\n"
1855 " return *this;\n"
1856 "}\n"
1857 "\n"
1858 "\n";
1863 const char * EnumeratedType::GetAncestorClass() const
1865 return "PASN_Enumeration";
1869 /////////////////////////////////////////////////////////
1871 RealType::RealType()
1872 : TypeBase(Tag::UniversalReal)
1877 const char * RealType::GetAncestorClass() const
1879 return "PASN_Real";
1883 /////////////////////////////////////////////////////////
1885 BitStringType::BitStringType()
1886 : TypeBase(Tag::UniversalBitString)
1891 BitStringType::BitStringType(NamedNumberList * lst)
1892 : TypeBase(Tag::UniversalBitString),
1893 allowedBits(*lst)
1895 delete lst;
1898 int BitStringType::GetIdentifierTokenContext() const
1900 return OID_IDENTIFIER;
1904 int BitStringType::GetBraceTokenContext() const
1906 return BITSTRING_BRACE;
1910 const char * BitStringType::GetAncestorClass() const
1912 return "PASN_BitString";
1916 /////////////////////////////////////////////////////////
1918 OctetStringType::OctetStringType()
1919 : TypeBase(Tag::UniversalOctetString)
1924 void OctetStringType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1926 static const char * const types[] = {
1927 "char *", "PString &", "PBYTEArray &"
1930 PINDEX i;
1931 for (i = 0; i < PARRAYSIZE(types); i++) {
1932 hdr << " " << actualType.GetIdentifier() << "(const " << types[i] << " v)";
1933 if (Module->UsingInlines())
1934 hdr << " { SetValue(v); }\n";
1935 else {
1936 hdr << ";\n";
1937 cxx << actualType.GetTemplatePrefix()
1938 << actualType.GetIdentifier() << "::" << actualType.GetIdentifier() << "(const " << types[i] << " v)\n"
1939 "{\n"
1940 " SetValue(v);\n"
1941 "}\n"
1942 "\n"
1943 "\n";
1947 hdr << '\n';
1949 for (i = 0; i < PARRAYSIZE(types); i++) {
1950 hdr << " " << actualType.GetIdentifier() << " & operator=(const " << types[i] << " v)";
1951 if (Module->UsingInlines())
1952 hdr << " { SetValue(v); return *this; }\n";
1953 else {
1954 hdr << ";\n";
1955 cxx << actualType.GetTemplatePrefix()
1956 << actualType.GetIdentifier() << " & "
1957 << actualType.GetClassNameString() << "::operator=(const " << types[i] << " v)\n"
1958 "{\n"
1959 " SetValue(v);\n"
1960 " return *this;\n"
1961 "}\n"
1962 "\n"
1963 "\n";
1969 const char * OctetStringType::GetAncestorClass() const
1971 return "PASN_OctetString";
1975 /////////////////////////////////////////////////////////
1977 NullType::NullType()
1978 : TypeBase(Tag::UniversalNull)
1983 const char * NullType::GetAncestorClass() const
1985 return "PASN_Null";
1989 /////////////////////////////////////////////////////////
1991 SequenceType::SequenceType(TypesList * stnd,
1992 BOOL extend,
1993 TypesList * ext,
1994 unsigned tagNum)
1995 : TypeBase(tagNum)
1997 if (stnd != NULL) {
1998 numFields = stnd->GetSize();
1999 fields = *stnd;
2000 delete stnd;
2002 else
2003 numFields = 0;
2004 extendable = extend;
2005 if (ext != NULL) {
2006 ext->DisallowDeleteObjects();
2007 for (PINDEX i = 0; i < ext->GetSize(); i++)
2008 fields.Append(ext->GetAt(i));
2009 delete ext;
2014 void SequenceType::PrintOn(ostream & strm) const
2016 PrintStart(strm);
2017 strm << '\n';
2018 PINDEX i;
2019 for (i = 0; i < numFields; i++)
2020 strm << fields[i];
2021 if (extendable) {
2022 strm << indent() << "...\n";
2023 for (; i < fields.GetSize(); i++)
2024 strm << fields[i];
2026 PrintFinish(strm);
2030 void SequenceType::FlattenUsedTypes()
2032 for (PINDEX i = 0; i < fields.GetSize(); i++)
2033 fields.SetAt(i, fields[i].FlattenThisType(*this));
2037 TypeBase * SequenceType::FlattenThisType(const TypeBase & parent)
2039 return new DefinedType(this, parent);
2043 BOOL SequenceType::IsPrimitiveType() const
2045 return FALSE;
2049 void SequenceType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2051 PArgList & args = PProcess::Current().GetArguments();
2052 BOOL xml_output = args.HasOption('x');
2054 PINDEX i;
2056 BeginGenerateCplusplus(hdr, cxx);
2058 PINDEX baseOptions = 0;
2059 for (i = 0; i < fields.GetSize(); i++) {
2060 if (i < numFields && fields[i].IsOptional())
2061 baseOptions++;
2064 // Complete ancestor constructor parameters
2065 cxx << ", " << baseOptions << ", "
2066 << (extendable ? "TRUE" : "FALSE") << ", "
2067 << fields.GetSize() - numFields
2068 << ')';
2070 // Output enum for optional parameters
2071 BOOL outputEnum = FALSE;
2072 for (i = 0; i < fields.GetSize(); i++) {
2073 if (i >= numFields || fields[i].IsOptional()) {
2074 if (outputEnum)
2075 hdr << ",\n";
2076 else {
2077 hdr << " enum OptionalFields {\n";
2078 outputEnum = TRUE;
2080 hdr << " e_" << fields[i].GetIdentifier();
2084 if (outputEnum)
2085 hdr << "\n"
2086 " };\n"
2087 "\n";
2089 // Output the declarations and constructors for member variables
2090 for (i = 0; i < fields.GetSize(); i++) {
2091 PString varname = "m_" + fields[i].GetIdentifier();
2092 hdr << " " << fields[i].GetTypeName() << ' ' << varname << ";\n";
2093 if (fields[i].HasNonStandardTag()) {
2094 cxx << ",\n"
2095 " " << varname;
2096 fields[i].GenerateCplusplusConstructor(hdr, cxx);
2100 // Output declarations for generated functions
2101 hdr << "\n"
2102 " PINDEX GetDataLength() const;\n"
2103 " BOOL Decode(PASN_Stream & strm);\n"
2104 " void Encode(PASN_Stream & strm) const;\n"
2105 "#ifndef PASN_NOPRINTON\n"
2106 " void PrintOn(ostream & strm) const;\n"
2107 "#endif\n";
2109 if (xml_output)
2111 hdr << " BOOL PreambleDecodeXER(PXER_Stream & strm);\n";
2113 if (fields.GetSize())
2114 hdr << " void PreambleEncodeXER(PXER_Stream &) const;\n";
2118 if (numFields > 0)
2119 hdr << " Comparison Compare(const PObject & obj) const;\n";
2121 cxx << "\n"
2122 "{\n";
2123 GenerateCplusplusConstraints(PString(), hdr, cxx);
2124 for (i = 0; i < fields.GetSize(); i++) {
2125 PString ident = fields[i].GetIdentifier();
2126 fields[i].GenerateCplusplusConstraints("m_" + ident + ".", hdr, cxx);
2127 if (i >= numFields && !fields[i].IsOptional())
2128 cxx << " IncludeOptionalField(e_" << ident << ");\n";
2130 cxx << "}\n"
2131 "\n"
2132 "\n"
2133 "#ifndef PASN_NOPRINTON\n"
2134 << GetTemplatePrefix()
2135 << "void " << GetClassNameString() << "::PrintOn(ostream & strm) const\n"
2136 "{\n"
2137 " int indent = strm.precision() + 2;\n"
2138 " strm << \"{\\n\";\n";
2140 for (i = 0; i < fields.GetSize(); i++) {
2141 PString id = fields[i].GetIdentifier();
2142 if (i >= numFields || fields[i].IsOptional())
2143 cxx << " if (HasOptionalField(e_" << id << "))\n"
2144 " ";
2145 cxx << " strm << setw(indent+" << id.GetLength()+3 << ") << \""
2146 << id << " = \" << setprecision(indent) << m_" << id << " << '\\n';\n";
2149 cxx << " strm << setw(indent-1) << \"}\";\n"
2150 "}\n"
2151 "#endif\n"
2152 "\n"
2153 "\n";
2155 if (xml_output)
2157 cxx << GetTemplatePrefix()
2158 << "BOOL " << GetClassNameString() << "::PreambleDecodeXER(PXER_Stream & strm)\n"
2159 "{\n";
2161 if (fields.GetSize())
2163 cxx << " PXMLElement * elem = strm.GetCurrentElement();\n"
2164 " PXMLElement * sub_elem;\n"
2165 " BOOL result;\n"
2166 "\n";
2168 for (i = 0; i < fields.GetSize(); i++)
2170 PString id = fields[i].GetIdentifier();
2171 cxx << " if ((sub_elem = (PXMLElement *)elem->GetElement(\"" << id << "\")) && sub_elem->IsElement())\n"
2172 " {\n";
2174 if (i >= numFields || fields[i].IsOptional())
2175 cxx << " IncludeOptionalField(e_" << id << ");\n";
2177 cxx << " strm.SetCurrentElement(sub_elem);\n"
2178 " result = m_" << id << ".Decode(strm);\n"
2179 " strm.SetCurrentElement(sub_elem);\n"
2180 " if (!result)\n"
2181 " return FALSE;\n"
2182 " }\n"
2183 "\n";
2187 cxx << " return TRUE;\n"
2188 "}\n"
2189 "\n";
2191 if (fields.GetSize())
2193 cxx << GetTemplatePrefix()
2194 << "void " << GetClassNameString() << "::PreambleEncodeXER(PXER_Stream & strm) const\n"
2195 "{\n";
2197 cxx << " PXMLElement * elem = strm.GetCurrentElement();\n"
2198 " PXMLElement * sub_elem;\n"
2199 "\n";
2201 for (i = 0; i < fields.GetSize(); i++)
2203 PString id = fields[i].GetIdentifier();
2205 if (i >= numFields || fields[i].IsOptional())
2206 cxx << " if (HasOptionalField(e_" << id << "))\n"
2207 " {\n";
2209 cxx << " sub_elem = elem->AddChild(new PXMLElement(elem, \"" << id << "\"));\n"
2210 " strm.SetCurrentElement(sub_elem);\n"
2211 " m_" << id << ".Encode(strm);\n";
2213 if (i >= numFields || fields[i].IsOptional())
2214 cxx << " }\n";
2216 cxx << "\n";
2219 cxx << " strm.SetCurrentElement(elem);\n"
2220 "}\n"
2221 "\n";
2225 if (numFields > 0) {
2226 cxx << GetTemplatePrefix()
2227 << "PObject::Comparison " << GetClassNameString() << "::Compare(const PObject & obj) const\n"
2228 "{\n"
2229 "#ifndef PASN_LEANANDMEAN\n"
2230 " PAssert(IsDescendant(" << GetClassNameString() << "::Class()), PInvalidCast);\n"
2231 "#endif\n"
2232 " const " << GetClassNameString() << " & other = (const " << GetClassNameString() << " &)obj;\n"
2233 "\n"
2234 " Comparison result;\n"
2235 "\n";
2237 for (i = 0; i < numFields; i++) {
2238 PString identifier = fields[i].GetIdentifier();
2239 cxx << " if ((result = m_" << identifier << ".Compare(other.m_" << identifier << ")) != EqualTo)\n"
2240 " return result;\n";
2243 cxx << "\n"
2244 " return PASN_Sequence::Compare(other);\n"
2245 "}\n"
2246 "\n"
2247 "\n";
2250 cxx << GetTemplatePrefix()
2251 << "PINDEX " << GetClassNameString() << "::GetDataLength() const\n"
2252 "{\n"
2253 " PINDEX length = 0;\n";
2255 for (i = 0; i < numFields; i++) {
2256 if (fields[i].IsOptional())
2257 cxx << " if (HasOptionalField(e_" << fields[i].GetIdentifier() << "))\n ";
2258 cxx << " length += m_" << fields[i].GetIdentifier() << ".GetObjectLength();\n";
2261 cxx << " return length;\n"
2262 "}\n"
2263 "\n"
2264 "\n"
2265 << GetTemplatePrefix()
2266 << "BOOL " << GetClassNameString() << "::Decode(PASN_Stream & strm)\n"
2267 "{\n"
2268 " if (!PreambleDecode(strm))\n"
2269 " return FALSE;\n\n";
2271 if (xml_output)
2273 cxx << " if (strm.IsDescendant(\"PXER_Stream\"))\n"
2274 " return TRUE;\n\n";
2277 for (i = 0; i < numFields; i++) {
2278 cxx << " if (";
2279 if (fields[i].IsOptional())
2280 cxx << "HasOptionalField(e_" << fields[i].GetIdentifier() << ") && ";
2281 cxx << "!m_" << fields[i].GetIdentifier() << ".Decode(strm))\n"
2282 " return FALSE;\n";
2285 for (; i < fields.GetSize(); i++)
2286 cxx << " if (!KnownExtensionDecode(strm, e_"
2287 << fields[i].GetIdentifier()
2288 << ", m_" << fields[i].GetIdentifier() << "))\n"
2289 " return FALSE;\n";
2291 cxx << "\n"
2292 " return UnknownExtensionsDecode(strm);\n"
2293 "}\n"
2294 "\n"
2295 "\n"
2296 << GetTemplatePrefix()
2297 << "void " << GetClassNameString() << "::Encode(PASN_Stream & strm) const\n"
2298 "{\n"
2299 " PreambleEncode(strm);\n\n";
2301 if (xml_output)
2303 cxx << " if (strm.IsDescendant(\"PXER_Stream\"))\n"
2304 " return;\n\n";
2307 for (i = 0; i < numFields; i++) {
2308 if (fields[i].IsOptional())
2309 cxx << " if (HasOptionalField(e_" << fields[i].GetIdentifier() << "))\n"
2310 " ";
2311 cxx << " m_" << fields[i].GetIdentifier() << ".Encode(strm);\n";
2314 for (; i < fields.GetSize(); i++)
2315 cxx << " KnownExtensionEncode(strm, e_"
2316 << fields[i].GetIdentifier()
2317 << ", m_" << fields[i].GetIdentifier() << ");\n";
2319 cxx << "\n"
2320 " UnknownExtensionsEncode(strm);\n";
2322 EndGenerateCplusplus(hdr, cxx);
2326 const char * SequenceType::GetAncestorClass() const
2328 return "PASN_Sequence";
2332 BOOL SequenceType::CanReferenceType() const
2334 return TRUE;
2338 BOOL SequenceType::ReferencesType(const TypeBase & type)
2340 for (PINDEX i = 0; i < fields.GetSize(); i++)
2341 if (fields[i].ReferencesType(type))
2342 return TRUE;
2343 return FALSE;
2347 /////////////////////////////////////////////////////////
2349 SequenceOfType::SequenceOfType(TypeBase * base, Constraint * constraint, unsigned tag)
2350 : TypeBase(tag)
2352 baseType = base;
2353 if (constraint != NULL)
2354 AddConstraint(constraint);
2358 SequenceOfType::~SequenceOfType()
2360 delete baseType;
2364 void SequenceOfType::PrintOn(ostream & strm) const
2366 PrintStart(strm);
2367 if (baseType == NULL)
2368 strm << "!!Null Type!!\n";
2369 else
2370 strm << *baseType << '\n';
2371 PrintFinish(strm);
2375 void SequenceOfType::FlattenUsedTypes()
2377 baseType = baseType->FlattenThisType(*this);
2381 TypeBase * SequenceOfType::FlattenThisType(const TypeBase & parent)
2383 if (!baseType->IsPrimitiveType() || baseType->HasConstraints())
2384 return new DefinedType(this, parent);
2386 // Search for an existing sequence of type
2387 PString seqName = "ArrayOf_" + baseType->GetTypeName();
2389 TypeBase * existingType = Module->FindType(seqName);
2390 if (existingType != NULL)
2391 return new DefinedType(this, existingType);
2393 return new DefinedType(this, seqName);
2397 BOOL SequenceOfType::IsPrimitiveType() const
2399 return FALSE;
2403 void SequenceOfType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2405 BeginGenerateCplusplus(hdr, cxx);
2406 cxx << ")\n"
2407 "{\n";
2408 GenerateCplusplusConstraints(PString(), hdr, cxx);
2409 cxx << "}\n"
2410 "\n"
2411 "\n";
2413 PString baseTypeName = baseType->GetTypeName();
2415 // Generate declarations for generated functions
2416 hdr << " PASN_Object * CreateObject() const;\n"
2417 " " << baseTypeName << " & operator[](PINDEX i) const";
2418 if (Module->UsingInlines())
2419 hdr << " { return (" << baseTypeName << " &)array[i]; }\n";
2420 else
2421 hdr << ";\n";
2423 // Generate implementation for functions
2424 cxx << GetTemplatePrefix()
2425 << "PASN_Object * " << GetClassNameString() << "::CreateObject() const\n"
2426 "{\n";
2428 if (baseType->HasConstraints()) {
2429 cxx << " " << baseTypeName << " * obj = new " << baseTypeName << ";\n";
2430 baseType->GenerateCplusplusConstraints("obj->", hdr, cxx);
2431 cxx << " return obj;\n";
2433 else
2434 cxx << " return new " << baseTypeName << ";\n";
2436 if (!Module->UsingInlines())
2437 cxx << "}\n"
2438 "\n"
2439 "\n"
2440 << GetTemplatePrefix()
2441 << baseTypeName << " & " << GetClassNameString() << "::operator[](PINDEX i) const\n"
2442 "{\n"
2443 " return (" << baseTypeName << " &)array[i];\n";
2445 EndGenerateCplusplus(hdr, cxx);
2449 void SequenceOfType::GenerateForwardDecls(ostream & hdr)
2451 if (baseType->IsParameterizedType())
2452 return;
2454 PString baseTypeName = baseType->GetTypeName();
2456 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2457 typesOutput += GetIdentifier();
2459 if (!typesOutput.Contains(baseTypeName))
2460 hdr << "class " << baseTypeName << ";\n\n";
2464 const char * SequenceOfType::GetAncestorClass() const
2466 return "PASN_Array";
2470 BOOL SequenceOfType::CanReferenceType() const
2472 return TRUE;
2476 BOOL SequenceOfType::ReferencesType(const TypeBase & type)
2478 return baseType->ReferencesType(type) && baseType->IsParameterizedType();
2482 /////////////////////////////////////////////////////////
2484 SetType::SetType()
2485 : SequenceType(NULL, FALSE, NULL, Tag::UniversalSet)
2490 SetType::SetType(SequenceType * seq)
2491 : SequenceType(*seq)
2493 tag.number = Tag::UniversalSet;
2497 const char * SetType::GetAncestorClass() const
2499 return "PASN_Set";
2503 /////////////////////////////////////////////////////////
2505 SetOfType::SetOfType(TypeBase * base, Constraint * constraint)
2506 : SequenceOfType(base, constraint, Tag::UniversalSet)
2511 /////////////////////////////////////////////////////////
2513 ChoiceType::ChoiceType(TypesList * stnd,
2514 BOOL extendable,
2515 TypesList * extensions)
2516 : SequenceType(stnd, extendable, extensions, Tag::IllegalUniversalTag)
2521 void ChoiceType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2523 PINDEX i;
2526 BeginGenerateCplusplus(hdr, cxx);
2528 // Complete the ancestor constructor parameters
2529 cxx << ", " << numFields << ", " << (extendable ? "TRUE" : "FALSE");
2531 // Generate the enum's for each choice discriminator, and include strings for
2532 // PrintOn() debug output into acncestor constructor
2533 BOOL outputEnum = FALSE;
2534 int prevNum = -1;
2535 for (i = 0; i < fields.GetSize(); i++) {
2536 const Tag & fieldTag = fields[i].GetTag();
2537 if (fieldTag.mode == Tag::Automatic || !fields[i].IsChoice()) {
2538 if (outputEnum) {
2539 hdr << ",\n";
2540 cxx << " \"";
2542 else {
2543 hdr << " enum Choices {\n";
2544 cxx << "\n"
2545 "#ifndef PASN_NOPRINTON\n"
2546 " , \"";
2547 outputEnum = TRUE;
2550 hdr << " e_" << fields[i].GetIdentifier();
2551 cxx << fields[i].GetIdentifier();
2553 if (fieldTag.mode != Tag::Automatic && fieldTag.number != (unsigned)(prevNum+1)) {
2554 hdr << " = " << fieldTag.number;
2555 cxx << '=' << fieldTag.number;
2557 prevNum = fieldTag.number;
2558 cxx << " \"\n";
2562 if (outputEnum) {
2563 hdr << "\n"
2564 " };\n"
2565 "\n";
2566 cxx << "#endif\n"
2567 " ";
2570 cxx << ")\n"
2571 "{\n";
2572 GenerateCplusplusConstraints(PString(), hdr, cxx);
2573 cxx << "}\n"
2574 "\n"
2575 "\n";
2577 // Generate code for type safe cast operators of selected choice object
2578 BOOL needExtraLine = FALSE;
2580 if (Module->UsingOperators()) {
2581 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2582 typesOutput += GetIdentifier();
2584 for (i = 0; i < fields.GetSize(); i++) {
2585 PString type = fields[i].GetTypeName();
2586 if (!typesOutput.Contains(type)) {
2587 if (Module->UsingInlines()) {
2588 hdr << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2589 " operator " << type << " &() const { return *(" << type << " *)choice; }\n"
2590 "#else\n"
2591 " operator " << type << " &() { return *(" << type << " *)choice; }\n"
2592 " operator const " << type << " &() const { return *(const " << type << " *)choice; }\n"
2593 "#endif\n";
2595 else {
2596 hdr << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2597 " operator " << type << " &() const;\n"
2598 "#else\n"
2599 " operator " << type << " &();\n"
2600 " operator const " << type << " &() const;\n"
2601 "#endif\n";
2602 cxx << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2603 << GetTemplatePrefix()
2604 << GetClassNameString() << "::operator " << type << " &() const\n"
2605 "#else\n"
2606 << GetTemplatePrefix()
2607 << GetClassNameString() << "::operator " << type << " &()\n"
2608 "{\n"
2609 "#ifndef PASN_LEANANDMEAN\n"
2610 " PAssert(PAssertNULL(choice)->IsDescendant(" << type << "::Class()), PInvalidCast);\n"
2611 "#endif\n"
2612 " return *(" << type << " *)choice;\n"
2613 "}\n"
2614 "\n"
2615 "\n"
2616 << GetTemplatePrefix()
2617 << GetClassNameString() << "::operator const " << type << " &() const\n"
2618 "#endif\n"
2619 "{\n"
2620 "#ifndef PASN_LEANANDMEAN\n"
2621 " PAssert(PAssertNULL(choice)->IsDescendant(" << type << "::Class()), PInvalidCast);\n"
2622 "#endif\n"
2623 " return *(" << type << " *)choice;\n"
2624 "}\n"
2625 "\n"
2626 "\n";
2628 typesOutput += type;
2629 needExtraLine = TRUE;
2633 else {
2634 for (i = 0; i < fields.GetSize(); i++) {
2635 PString type = fields[i].GetTypeName();
2636 PString fieldName = fields[i].GetIdentifier();
2637 if (Module->UsingInlines()) {
2638 hdr << " " << type << " & m_" << fieldName << "() { return *(" << type << " *)choice; }\n"
2639 " const " << type << " & m_" << fieldName << "() const { return *(const " << type << " *)choice; }\n";
2641 else {
2642 hdr << " " << type << " & m_" << fieldName << "();\n"
2643 " const " << type << " & m_" << fieldName << "() const;\n";
2644 cxx << GetTemplatePrefix() << type << " & "
2645 << GetClassNameString() << "::m_" << fieldName << "()\n"
2646 "{\n"
2647 "#ifndef PASN_LEANANDMEAN\n"
2648 " PAssert(PAssertNULL(choice)->IsDescendant(" << type << "::Class()), PInvalidCast);\n"
2649 "#endif\n"
2650 " return *(" << type << " *)choice;\n"
2651 "}\n"
2652 "\n"
2653 "\n"
2654 << GetTemplatePrefix() << type << " const & "
2655 << GetClassNameString() << "::m_" << fieldName << "() const\n"
2656 "{\n"
2657 "#ifndef PASN_LEANANDMEAN\n"
2658 " PAssert(PAssertNULL(choice)->IsDescendant(" << type << "::Class()), PInvalidCast);\n"
2659 "#endif\n"
2660 " return *(" << type << " *)choice;\n"
2661 "}\n"
2662 "\n"
2663 "\n";
2666 needExtraLine = TRUE;
2669 if (needExtraLine)
2670 hdr << '\n';
2673 // Generate virtual function to create chosen object based on discriminator
2674 hdr << " BOOL CreateObject();\n";
2675 cxx << GetTemplatePrefix()
2676 << "BOOL " << GetClassNameString() << "::CreateObject()\n"
2677 "{\n";
2679 // special case: if choice is all NULLs then simply output code
2680 BOOL allNull = TRUE;
2681 for (i = 0; allNull && i < fields.GetSize(); i++)
2682 allNull = allNull && strcmp(fields[i].GetAncestorClass(), "PASN_Null") == 0;
2684 if (allNull) {
2685 cxx << " choice = (tag <= e_" << fields[fields.GetSize()-1].GetIdentifier() << ") ? new PASN_Null() : NULL;\n"
2686 << " return choice != NULL;\n";
2689 else {
2690 // declare an array of flags indicating whether the tag has been output or not
2691 PBYTEArray flags(fields.GetSize());
2692 for (i = 0; i < fields.GetSize(); i++)
2693 flags[i] = 0;
2695 // keep
2696 outputEnum = FALSE;
2697 for (i = 0; i < fields.GetSize(); i++) {
2699 if (fields[i].GetTag().mode == Tag::Automatic || !fields[i].IsChoice()) {
2701 // ignore this tag if output previously
2702 if (flags[i] != 0)
2703 continue;
2705 if (!outputEnum) {
2706 cxx << " switch (tag) {\n";
2707 outputEnum = TRUE;
2710 // if the field has constraints, then output it alone
2711 // otherwise, look for all fields with the same type
2712 PString name = fields[i].GetTypeName();
2713 if (fields[i].HasConstraints()) {
2714 cxx << " case e_" << fields[i].GetIdentifier() << " :\n";
2715 flags[i] = 1;
2716 } else {
2717 PINDEX j;
2718 for (j = i; j < fields.GetSize(); j++) {
2719 if (fields[j].GetTypeName() == name) {
2720 cxx << " case e_" << fields[j].GetIdentifier() << " :\n";
2721 flags[j] = 1;
2726 cxx << " choice = new " << name;
2727 fields[i].GenerateCplusplusConstructor(hdr, cxx);
2728 cxx << ";\n";
2729 fields[i].GenerateCplusplusConstraints(" choice->", hdr, cxx);
2730 cxx << " return TRUE;\n";
2734 if (outputEnum)
2735 cxx << " }\n"
2736 "\n";
2738 for (i = 0; i < fields.GetSize(); i++) {
2739 if (fields[i].GetTag().mode != Tag::Automatic && fields[i].IsChoice())
2740 cxx << " choice = new " << fields[i].GetTypeName() << "(tag, tagClass);\n"
2741 " if (((PASN_Choice*)choice)->CreateObject())\n"
2742 " return TRUE;\n"
2743 " delete choice;\n"
2744 "\n";
2747 cxx << " choice = NULL;\n"
2748 " return FALSE;\n";
2751 EndGenerateCplusplus(hdr, cxx);
2755 void ChoiceType::GenerateForwardDecls(ostream & hdr)
2757 // Output forward declarations for choice pointers, but not standard classes
2758 BOOL needExtraLine = FALSE;
2760 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2761 typesOutput += GetIdentifier();
2763 PStringSet forwards;
2765 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2766 PString type = fields[i].GetTypeName();
2767 if (!fields[i].IsParameterizedType() &&
2768 !typesOutput.Contains(type) &&
2769 !forwards.Contains(type)) {
2770 hdr << "class " << type << ";\n";
2771 needExtraLine = TRUE;
2772 forwards.Include(type);
2776 if (needExtraLine)
2777 hdr << '\n';
2781 BOOL ChoiceType::IsPrimitiveType() const
2783 return FALSE;
2787 BOOL ChoiceType::IsChoice() const
2789 return TRUE;
2793 const char * ChoiceType::GetAncestorClass() const
2795 return "PASN_Choice";
2799 BOOL ChoiceType::ReferencesType(const TypeBase & type)
2801 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2802 if (fields[i].ReferencesType(type) && fields[i].IsParameterizedType())
2803 return TRUE;
2805 return FALSE;
2809 /////////////////////////////////////////////////////////
2811 EmbeddedPDVType::EmbeddedPDVType()
2812 : TypeBase(Tag::UniversalEmbeddedPDV)
2817 const char * EmbeddedPDVType::GetAncestorClass() const
2819 return "PASN_OctetString";
2823 /////////////////////////////////////////////////////////
2825 ExternalType::ExternalType()
2826 : TypeBase(Tag::UniversalExternalType)
2831 const char * ExternalType::GetAncestorClass() const
2833 return "PASN_OctetString";
2837 /////////////////////////////////////////////////////////
2839 AnyType::AnyType(PString * ident)
2840 : TypeBase(Tag::UniversalExternalType)
2842 if (ident != NULL) {
2843 identifier = *ident;
2844 delete ident;
2849 void AnyType::PrintOn(ostream & strm) const
2851 PrintStart(strm);
2852 if (!identifier)
2853 strm << "Defined by " << identifier;
2854 PrintFinish(strm);
2858 const char * AnyType::GetAncestorClass() const
2860 return "PASN_OctetString";
2864 /////////////////////////////////////////////////////////
2866 StringTypeBase::StringTypeBase(int tag)
2867 : TypeBase(tag)
2872 int StringTypeBase::GetBraceTokenContext() const
2874 return STRING_BRACE;
2878 static void GenerateOperator(const char * rhsType, ostream & hdr, ostream & cxx, const TypeBase & actualType)
2880 hdr << " " << actualType.GetIdentifier() << " & operator=(const " << rhsType << " v)";
2881 if (Module->UsingInlines())
2882 hdr << " { SetValue(v); return *this; }\n";
2883 else {
2884 hdr << ";\n";
2885 cxx << actualType.GetTemplatePrefix()
2886 << actualType.GetIdentifier() << " & "
2887 << actualType.GetClassNameString() << "::operator=(const " << rhsType << " v)\n"
2888 "{\n"
2889 " SetValue(v);\n"
2890 " return *this;\n"
2891 "}\n"
2892 "\n"
2893 "\n";
2898 void StringTypeBase::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
2900 GenerateOperator("char *", hdr, cxx, actualType);
2901 GenerateOperator("PString &", hdr, cxx, actualType);
2905 /////////////////////////////////////////////////////////
2907 BMPStringType::BMPStringType()
2908 : StringTypeBase(Tag::UniversalBMPString)
2913 const char * BMPStringType::GetAncestorClass() const
2915 return "PASN_BMPString";
2919 void BMPStringType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
2921 StringTypeBase::GenerateOperators(hdr, cxx, actualType);
2922 GenerateOperator("PWORDArray &", hdr, cxx, actualType);
2923 GenerateOperator("PASN_BMPString &", hdr, cxx, actualType);
2927 /////////////////////////////////////////////////////////
2929 GeneralStringType::GeneralStringType()
2930 : StringTypeBase(Tag::UniversalGeneralString)
2935 const char * GeneralStringType::GetAncestorClass() const
2937 return "PASN_GeneralString";
2941 /////////////////////////////////////////////////////////
2943 GraphicStringType::GraphicStringType()
2944 : StringTypeBase(Tag::UniversalGraphicString)
2949 const char * GraphicStringType::GetAncestorClass() const
2951 return "PASN_GraphicString";
2955 /////////////////////////////////////////////////////////
2957 IA5StringType::IA5StringType()
2958 : StringTypeBase(Tag::UniversalIA5String)
2963 const char * IA5StringType::GetAncestorClass() const
2965 return "PASN_IA5String";
2969 /////////////////////////////////////////////////////////
2971 ISO646StringType::ISO646StringType()
2972 : StringTypeBase(Tag::UniversalVisibleString)
2977 const char * ISO646StringType::GetAncestorClass() const
2979 return "PASN_ISO646String";
2983 /////////////////////////////////////////////////////////
2985 NumericStringType::NumericStringType()
2986 : StringTypeBase(Tag::UniversalNumericString)
2991 const char * NumericStringType::GetAncestorClass() const
2993 return "PASN_NumericString";
2997 /////////////////////////////////////////////////////////
2999 PrintableStringType::PrintableStringType()
3000 : StringTypeBase(Tag::UniversalPrintableString)
3005 const char * PrintableStringType::GetAncestorClass() const
3007 return "PASN_PrintableString";
3011 /////////////////////////////////////////////////////////
3013 TeletexStringType::TeletexStringType()
3014 : StringTypeBase(Tag::UniversalTeletexString)
3019 const char * TeletexStringType::GetAncestorClass() const
3021 return "PASN_TeletexString";
3025 /////////////////////////////////////////////////////////
3027 T61StringType::T61StringType()
3028 : StringTypeBase(Tag::UniversalTeletexString)
3033 const char * T61StringType::GetAncestorClass() const
3035 return "PASN_T61String";
3039 /////////////////////////////////////////////////////////
3041 UniversalStringType::UniversalStringType()
3042 : StringTypeBase(Tag::UniversalUniversalString)
3047 const char * UniversalStringType::GetAncestorClass() const
3049 return "PASN_UniversalString";
3053 /////////////////////////////////////////////////////////
3055 VideotexStringType::VideotexStringType()
3056 : StringTypeBase(Tag::UniversalVideotexString)
3061 const char * VideotexStringType::GetAncestorClass() const
3063 return "PASN_VideotexString";
3067 /////////////////////////////////////////////////////////
3069 VisibleStringType::VisibleStringType()
3070 : StringTypeBase(Tag::UniversalVisibleString)
3075 const char * VisibleStringType::GetAncestorClass() const
3077 return "PASN_VisibleString";
3081 /////////////////////////////////////////////////////////
3083 UnrestrictedCharacterStringType::UnrestrictedCharacterStringType()
3084 : StringTypeBase(Tag::UniversalUniversalString)
3089 const char * UnrestrictedCharacterStringType::GetAncestorClass() const
3091 return "PASN_UnrestrictedString";
3095 /////////////////////////////////////////////////////////
3097 GeneralizedTimeType::GeneralizedTimeType()
3098 : TypeBase(Tag::UniversalGeneralisedTime)
3103 const char * GeneralizedTimeType::GetAncestorClass() const
3105 return "PASN_GeneralisedTime";
3109 /////////////////////////////////////////////////////////
3111 UTCTimeType::UTCTimeType()
3112 : TypeBase(Tag::UniversalUTCTime)
3117 const char * UTCTimeType::GetAncestorClass() const
3119 return "PASN_UniversalTime";
3123 /////////////////////////////////////////////////////////
3125 ObjectDescriptorType::ObjectDescriptorType()
3126 : TypeBase(Tag::UniversalObjectDescriptor)
3131 const char * ObjectDescriptorType::GetAncestorClass() const
3133 return "PASN_ObectDescriptor";
3137 /////////////////////////////////////////////////////////
3139 ObjectIdentifierType::ObjectIdentifierType()
3140 : TypeBase(Tag::UniversalObjectId)
3145 int ObjectIdentifierType::GetIdentifierTokenContext() const
3147 return OID_IDENTIFIER;
3151 int ObjectIdentifierType::GetBraceTokenContext() const
3153 return OID_BRACE;
3157 const char * ObjectIdentifierType::GetAncestorClass() const
3159 return "PASN_ObjectId";
3163 /////////////////////////////////////////////////////////
3165 ObjectClassFieldType::ObjectClassFieldType(PString * objclass, PString * field)
3166 : TypeBase(Tag::IllegalUniversalTag),
3167 asnObjectClassName(*objclass),
3168 asnObjectClassField(*field)
3170 delete objclass;
3171 delete field;
3175 const char * ObjectClassFieldType::GetAncestorClass() const
3177 return "PASN_OctetString";
3181 void ObjectClassFieldType::PrintOn(ostream & strm) const
3183 PrintStart(strm);
3184 strm << asnObjectClassName << '.' << asnObjectClassField;
3185 PrintFinish(strm);
3189 TypeBase * ObjectClassFieldType::FlattenThisType(const TypeBase & parent)
3191 return new DefinedType(this, parent);
3195 BOOL ObjectClassFieldType::IsPrimitiveType() const
3197 return FALSE;
3201 void ObjectClassFieldType::GenerateCplusplus(ostream & hdr, ostream & cxx)
3203 BeginGenerateCplusplus(hdr, cxx);
3205 hdr << " BOOL DecodeSubType(";
3206 GenerateCplusplusConstraints(PString(), hdr, cxx);
3207 hdr << " & obj) { return PASN_OctetString::DecodeSubType(obj); }\n"
3208 " void EncodeSubType(const ";
3209 GenerateCplusplusConstraints(PString(), hdr, cxx);
3210 hdr << " & obj) { PASN_OctetString::EncodeSubType(obj); } \n"
3211 "\n";
3213 cxx << ")\n"
3214 "{\n";
3216 EndGenerateCplusplus(hdr, cxx);
3220 BOOL ObjectClassFieldType::CanReferenceType() const
3222 return TRUE;
3226 BOOL ObjectClassFieldType::ReferencesType(const TypeBase & type)
3228 for (PINDEX i = 0; i < constraints.GetSize(); i++) {
3229 if (constraints[i].ReferencesType(type))
3230 return TRUE;
3232 return FALSE;
3236 /////////////////////////////////////////////////////////
3238 ImportedType::ImportedType(PString * theName, BOOL param)
3239 : TypeBase(Tag::IllegalUniversalTag)
3241 identifier = name = *theName;
3242 delete theName;
3244 parameterised = param;
3248 const char * ImportedType::GetAncestorClass() const
3250 return identifier;
3254 void ImportedType::AdjustIdentifier()
3256 identifier = modulePrefix + '_' + MakeIdentifierC(name);
3260 void ImportedType::GenerateCplusplus(ostream &, ostream &)
3265 void ImportedType::SetImportPrefix(const PString & prefix)
3267 modulePrefix = prefix;
3271 BOOL ImportedType::IsParameterisedImport() const
3273 return parameterised;
3277 /////////////////////////////////////////////////////////
3279 SearchType::SearchType(const PString & theName)
3280 : TypeBase(Tag::IllegalUniversalTag)
3282 identifier = name = theName;
3286 const char * SearchType::GetAncestorClass() const
3288 return identifier;
3292 /////////////////////////////////////////////////////////
3294 void ValueBase::SetValueName(PString * name)
3296 valueName = *name;
3297 delete name;
3301 void ValueBase::PrintBase(ostream & strm) const
3303 if (!valueName)
3304 strm << '\n' << indent() << valueName << '=';
3308 void ValueBase::GenerateCplusplus(ostream &, ostream &)
3310 PError << StdError(Warning) << "unsupported value type." << endl;
3314 /////////////////////////////////////////////////////////
3316 DefinedValue::DefinedValue(PString * name)
3317 : referenceName(*name)
3319 delete name;
3320 actualValue = NULL;
3321 unresolved = TRUE;
3325 void DefinedValue::PrintOn(ostream & strm) const
3327 PrintBase(strm);
3328 strm << referenceName;
3332 void DefinedValue::GenerateCplusplus(ostream & hdr, ostream & cxx)
3334 if (unresolved) {
3335 unresolved = FALSE;
3337 const ValuesList & values = Module->GetValues();
3338 for (PINDEX i = 0; i < values.GetSize(); i++) {
3339 if (values[i].GetName() == referenceName) {
3340 actualValue = &values[i];
3341 break;
3346 if (actualValue != NULL)
3347 actualValue->GenerateCplusplus(hdr, cxx);
3348 else
3349 cxx << "e_" << referenceName;
3353 /////////////////////////////////////////////////////////
3355 BooleanValue::BooleanValue(BOOL newVal)
3357 value = newVal;
3361 void BooleanValue::PrintOn(ostream & strm) const
3363 PrintBase(strm);
3364 strm << (value ? "TRUE" : "FALSE");
3368 void BooleanValue::GenerateCplusplus(ostream &, ostream & cxx)
3370 cxx << (value ? "TRUE" : "FALSE");
3374 /////////////////////////////////////////////////////////
3376 IntegerValue::IntegerValue(PInt64 newVal)
3378 value = newVal;
3382 void IntegerValue::PrintOn(ostream & strm) const
3384 PrintBase(strm);
3386 strm << value;
3390 void IntegerValue::GenerateCplusplus(ostream &, ostream & cxx)
3392 cxx << value;
3393 if (value > INT_MAX)
3394 cxx << 'U';
3398 /////////////////////////////////////////////////////////
3400 RealValue::RealValue(double newVal)
3402 value = newVal;
3406 /////////////////////////////////////////////////////////
3408 OctetStringValue::OctetStringValue(PString * newVal)
3410 // value = *newVal;
3411 delete newVal;
3415 /////////////////////////////////////////////////////////
3417 BitStringValue::BitStringValue(PString * newVal)
3419 // value = *newVal;
3420 delete newVal;
3424 BitStringValue::BitStringValue(PStringList * newVal)
3426 // value = *newVal;
3427 delete newVal;
3431 /////////////////////////////////////////////////////////
3433 CharacterValue::CharacterValue(BYTE c)
3435 value = c;
3439 CharacterValue::CharacterValue(BYTE t1, BYTE t2)
3441 value = (t1<<8) + t2;
3445 CharacterValue::CharacterValue(BYTE q1, BYTE q2, BYTE q3, BYTE q4)
3447 value = (q1<<24) + (q2<<16) + (q3<<8) + q4;
3451 void CharacterValue::PrintOn(ostream & strm) const
3453 strm << "'\\x" << hex << value << '\'';
3457 void CharacterValue::GenerateCplusplus(ostream &, ostream & cxx)
3459 cxx << value;
3463 /////////////////////////////////////////////////////////
3465 CharacterStringValue::CharacterStringValue(PString * newVal)
3467 value = *newVal;
3468 delete newVal;
3472 CharacterStringValue::CharacterStringValue(PStringList * newVal)
3474 for (PINDEX i = 0; i < newVal->GetSize(); i++)
3475 value += (*newVal)[i];
3476 delete newVal;
3480 void CharacterStringValue::PrintOn(ostream & strm) const
3482 strm << value;
3486 void CharacterStringValue::GenerateCplusplus(ostream &, ostream & cxx)
3488 cxx << value;
3492 /////////////////////////////////////////////////////////
3494 ObjectIdentifierValue::ObjectIdentifierValue(PString * newVal)
3496 value.Append(newVal);
3500 ObjectIdentifierValue::ObjectIdentifierValue(PStringList * newVal)
3502 value = *newVal;
3503 delete newVal;
3507 void ObjectIdentifierValue::PrintOn(ostream & strm) const
3509 PrintBase(strm);
3510 if (value.IsEmpty())
3511 strm << "empty object identifier";
3512 else {
3513 strm << value[0];
3514 for (PINDEX i = 1; i < value.GetSize(); i++)
3515 strm << '.' << value[i];
3517 strm << '\n';
3521 /////////////////////////////////////////////////////////
3523 void MinValue::PrintOn(ostream & strm) const
3525 strm << "MIN";
3529 void MinValue::GenerateCplusplus(ostream &, ostream & cxx)
3531 cxx << "MinimumValue";
3535 /////////////////////////////////////////////////////////
3537 void MaxValue::PrintOn(ostream & strm) const
3539 strm << "MAX";
3543 void MaxValue::GenerateCplusplus(ostream &, ostream & cxx)
3545 cxx << "MaximumValue";
3549 /////////////////////////////////////////////////////////
3551 SequenceValue::SequenceValue(ValuesList * list)
3553 if (list != NULL) {
3554 values = *list;
3555 delete list;
3560 void SequenceValue::PrintOn(ostream & strm) const
3562 strm << "{ ";
3563 for (PINDEX i = 0; i < values.GetSize(); i++) {
3564 if (i > 0)
3565 strm << ", ";
3566 strm << values[i];
3568 strm << " }";
3572 /////////////////////////////////////////////////////////
3574 MibBase::MibBase(PString * nam,
3575 PString * descr,
3576 PString * refer,
3577 ValueBase * val)
3578 : name(*nam)
3580 delete nam;
3581 if (descr != NULL) {
3582 description = *descr;
3583 delete descr;
3585 if (refer != NULL) {
3586 reference = *refer;
3587 delete refer;
3589 value = val;
3593 MibBase::~MibBase()
3595 delete value;
3599 /////////////////////////////////////////////////////////
3601 MibObject::MibObject(PString * nam,
3602 TypeBase * typ,
3603 Access acc,
3604 Status stat,
3605 PString * descr,
3606 PString * refer,
3607 PStringList * idx,
3608 ValueBase * defVal,
3609 ValueBase * setVal)
3610 : MibBase(nam, descr, refer, setVal)
3612 type = typ;
3613 access = acc;
3614 status = stat;
3615 if (idx != NULL) {
3616 index = *idx;
3617 delete idx;
3619 defaultValue = defVal;
3623 MibObject::~MibObject()
3625 delete type;
3626 delete defaultValue;
3630 void MibObject::PrintOn(ostream & strm) const
3632 strm << " Object: " << name << "\n " << *type
3633 << " " << description << "\n"
3634 " " << *value << '\n';
3638 /////////////////////////////////////////////////////////
3640 MibTrap::MibTrap(PString * nam, ValueBase * ent, ValuesList * var,
3641 PString * descr, PString * refer, ValueBase * val)
3642 : MibBase(nam, descr, refer, val)
3644 enterprise = ent;
3645 if (var != NULL) {
3646 variables = *var;
3647 delete var;
3652 MibTrap::~MibTrap()
3654 delete enterprise;
3658 void MibTrap::PrintOn(ostream & strm) const
3660 strm << " Trap: " << name << "\n " << *enterprise
3661 << " " << description << "\n"
3662 " " << *value << '\n';
3666 /////////////////////////////////////////////////////////
3668 ImportModule::ImportModule(PString * name, TypesList * syms)
3669 : fullModuleName(*name),
3670 shortModuleName(Module->GetImportModuleName(*name)),
3671 filename(shortModuleName.ToLower())
3673 delete name;
3674 symbols = *syms;
3675 delete syms;
3677 PStringArray renameArgs = shortModuleName.Tokenise(',');
3678 switch (renameArgs.GetSize())
3680 case 3 :
3681 filename = renameArgs[2];
3682 case 2 :
3683 directoryPrefix = renameArgs[1];
3684 shortModuleName = renameArgs[0];
3687 for (PINDEX i = 0; i < symbols.GetSize(); i++) {
3688 symbols[i].SetImportPrefix(shortModuleName);
3689 Module->AppendType(&symbols[i]);
3694 void ImportModule::PrintOn(ostream & strm) const
3696 strm << " " << fullModuleName << " (" << shortModuleName << "):\n";
3697 for (PINDEX i = 0; i < symbols.GetSize(); i++)
3698 strm << " " << symbols[i];
3699 strm << '\n';
3703 void ImportModule::GenerateCplusplus(ostream & hdr, ostream & cxx)
3705 hdr << "#include \"" << directoryPrefix << filename << ".h\"\n";
3707 for (PINDEX i = 0; i < symbols.GetSize(); i++) {
3708 if (symbols[i].IsParameterisedImport()) {
3709 cxx << "#include \"" << filename << "_t.cxx\"\n";
3710 break;
3716 /////////////////////////////////////////////////////////
3718 ModuleDefinition::ModuleDefinition(PString * name, PStringList * id, Tag::Mode defTagMode)
3719 : moduleName(*name),
3720 definitiveId(*id)
3722 delete name;
3723 delete id;
3724 defaultTagMode = defTagMode;
3725 exportAll = FALSE;
3726 indentLevel = 1;
3728 PArgList & args = PProcess::Current().GetArguments();
3729 if (args.HasOption('r')) {
3730 PStringArray renames = args.GetOptionString('r').Lines();
3731 for (PINDEX i = 0; i < renames.GetSize(); i++) {
3732 PINDEX equal = renames[i].Find('=');
3733 if (equal > 0 && equal != P_MAX_INDEX)
3734 importNames.SetAt(renames[i].Left(equal).Trim(), renames[i].Mid(equal+1).Trim());
3740 void ModuleDefinition::SetExportAll()
3742 exportAll = TRUE;
3746 void ModuleDefinition::SetExports(TypesList * syms)
3748 exports = *syms;
3749 delete syms;
3753 void ModuleDefinition::PrintOn(ostream & strm) const
3755 strm << moduleName << "\n"
3756 "Default Tags: " << Tag::modeNames[defaultTagMode] << "\n"
3757 "Exports:";
3758 if (exportAll)
3759 strm << " ALL";
3760 else {
3761 strm << "\n ";
3762 for (PINDEX i = 0; i < exports.GetSize(); i++)
3763 strm << exports[i] << ' ';
3764 strm << '\n';
3766 strm << "Imports:\n" << imports << "\n"
3767 "Types:\n" << types << "\n"
3768 "Values:\n" << values << "\n"
3769 "MIBs:\n" << mibs << endl;
3773 void ModuleDefinition::AppendType(TypeBase * type)
3775 types.Append(type);
3776 sortedTypes.Append(type);
3780 TypeBase * ModuleDefinition::FindType(const PString & name)
3782 PINDEX pos = sortedTypes.GetValuesIndex(SearchType(name));
3783 if (pos != P_MAX_INDEX)
3784 return &sortedTypes[pos];
3785 return NULL;
3789 PString ModuleDefinition::GetImportModuleName(const PString & moduleName)
3791 if (importNames.Contains(moduleName))
3792 return importNames[moduleName];
3794 PINDEX pos = moduleName.Find('-');
3795 if (pos > 32)
3796 pos = 32;
3797 return moduleName.Left(pos);
3801 void ModuleDefinition::GenerateCplusplus(const PFilePath & path,
3802 const PString & modName,
3803 const PString & headerPrefix,
3804 unsigned numFiles,
3805 BOOL useNamespaces,
3806 BOOL useInlines,
3807 BOOL useOperators,
3808 BOOL verbose)
3810 PArgList & args = PProcess::Current().GetArguments();
3811 BOOL xml_output = args.HasOption('x');
3812 PINDEX i;
3814 usingInlines = useInlines;
3815 usingOperators = useOperators;
3817 // Adjust the module name to what is specified to a default
3818 if (!modName)
3819 moduleName = modName;
3820 else
3821 moduleName = MakeIdentifierC(moduleName);
3823 // Set the prefix on all external class names
3824 if (!useNamespaces)
3825 classNamePrefix = moduleName + '_';
3828 if (verbose)
3829 cout << "Sorting " << types.GetSize() << " types..." << endl;
3832 // Create sorted list for faster searching.
3833 sortedTypes.DisallowDeleteObjects();
3834 for (i = 0; i < types.GetSize(); i++)
3835 sortedTypes.Append(&types[i]);
3837 // Flatten types by generating types for "inline" definitions
3838 for (i = 0; i < types.GetSize(); i++)
3839 types[i].FlattenUsedTypes();
3841 // Reorder types
3842 // Determine if we need a separate file for template closure
3843 BOOL hasTemplates = FALSE;
3844 types.DisallowDeleteObjects();
3845 PINDEX loopDetect = 0;
3846 PINDEX bubble = 0;
3847 while (bubble < types.GetSize()) {
3848 BOOL makesReference = FALSE;
3850 TypeBase & bubbleType = types[bubble];
3851 if (bubbleType.CanReferenceType()) {
3852 for (i = bubble; i < types.GetSize(); i++) {
3853 if (bubbleType.ReferencesType(types[i])) {
3854 makesReference = TRUE;
3855 break;
3860 if (makesReference) {
3861 types.Append(types.RemoveAt(bubble));
3862 if (loopDetect > types.GetSize()) {
3863 PError << StdError(Fatal)
3864 << "Recursive type definition: " << bubbleType.GetName() << endl;
3865 break;
3867 loopDetect++;
3869 else {
3870 loopDetect = bubble;
3871 bubble++;
3874 if (bubbleType.HasParameters())
3875 hasTemplates = TRUE;
3877 types.AllowDeleteObjects();
3879 // Adjust all of the C++ identifiers prepending module name
3880 for (i = 0; i < types.GetSize(); i++)
3881 types[i].AdjustIdentifier();
3884 // Generate the code
3885 if (verbose)
3886 cout << "Generating code (" << types.GetSize() << " classes) ..." << endl;
3889 // Output the special template closure file, if necessary
3890 PString templateFilename;
3891 if (hasTemplates) {
3892 OutputFile templateFile;
3893 if (!templateFile.Open(path, "_t", ".cxx"))
3894 return;
3896 for (i = 0; i < types.GetSize(); i++) {
3897 if (types[i].HasParameters()) {
3898 PStringStream dummy;
3899 types[i].GenerateCplusplus(dummy, templateFile);
3903 if (verbose)
3904 cout << "Completed " << templateFile.GetFilePath() << endl;
3906 templateFilename = templateFile.GetFilePath().GetFileName();
3909 // Start the header file
3910 OutputFile hdrFile;
3911 if (!hdrFile.Open(path, "", ".h"))
3912 return;
3914 hdrFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3916 hdrFile << "#ifndef __" << moduleName.ToUpper() << "_H\n"
3917 "#define __" << moduleName.ToUpper() << "_H\n"
3918 "\n"
3919 "#ifdef P_USE_PRAGMA\n"
3920 "#pragma interface\n"
3921 "#endif\n"
3922 "\n";
3924 if (xml_output)
3925 hdrFile << "#define P_EXPAT 1\n"
3926 "#include <ptclib/pxml.h>\n";
3928 hdrFile << "#include <ptclib/asner.h>\n"
3929 "\n";
3931 // Start the first (and maybe only) cxx file
3932 OutputFile cxxFile;
3933 if (!cxxFile.Open(path, numFiles > 1 ? "_1" : "", ".cxx"))
3934 return;
3936 PString headerName = hdrFile.GetFilePath().GetFileName();
3938 cxxFile << "#ifdef P_USE_PRAGMA\n"
3939 "#pragma implementation \"" << headerName << "\"\n"
3940 "#endif\n"
3941 "\n"
3942 "#include <ptlib.h>\n"
3943 "#include \"" << headerPrefix << headerName << "\"\n"
3944 "\n"
3945 "#define new PNEW\n"
3946 "\n"
3947 "\n";
3949 cxxFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3951 // Include the template closure file.
3952 if (hasTemplates)
3953 cxxFile << "#include \"" << templateFilename << "\"\n\n";
3956 for (i = 0; i < imports.GetSize(); i++)
3957 imports[i].GenerateCplusplus(hdrFile, cxxFile);
3958 if (!imports.IsEmpty()) {
3959 hdrFile << "\n\n";
3960 cxxFile << "\n\n";
3964 if (useNamespaces) {
3965 hdrFile << "namespace " << moduleName << " {\n"
3966 "\n";
3967 cxxFile << "using namespace " << moduleName << ";\n"
3968 "\n";
3972 PINDEX classesPerFile = (types.GetSize()+numFiles-1)/numFiles;
3973 for (i = 0; i < types.GetSize(); i++) {
3974 if (i > 0 && i%classesPerFile == 0) {
3976 cxxFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
3977 "\n";
3979 cxxFile.Close();
3981 if (verbose)
3982 cout << "Completed " << cxxFile.GetFilePath() << endl;
3984 if (!cxxFile.Open(path, psprintf("_%u", i/classesPerFile+1), ".cxx"))
3985 return;
3987 cxxFile << "#include <ptlib.h>\n"
3988 "#include \"" << headerPrefix << headerName << "\"\n"
3989 "\n";
3991 if (useNamespaces)
3992 cxxFile << "using namespace " << moduleName << ";\n"
3993 "\n";
3994 cxxFile << "#define new PNEW\n"
3995 "\n"
3996 "\n";
3998 cxxFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
4002 if (types[i].HasParameters()) {
4003 PStringStream dummy;
4004 types[i].GenerateCplusplus(hdrFile, dummy);
4006 else
4007 types[i].GenerateCplusplus(hdrFile, cxxFile);
4011 // Close off the files
4012 if (useNamespaces)
4013 hdrFile << "};\n"
4014 "\n";
4016 hdrFile << "#endif // __" << moduleName.ToUpper() << "_H\n"
4017 "\n";
4019 hdrFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
4020 "\n";
4022 cxxFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
4023 "\n";
4025 if (verbose)
4026 cout << "Completed " << cxxFile.GetFilePath() << endl;
4030 //////////////////////////////////////////////////////////////////////////////