Added posix library to make files
[pwlib.git] / tools / asnparser / main.cxx
blob8949590ad58165fbe02facb7fb2e659768593406
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.51 2004/04/25 08:58:58 rjongbloed
34 * Fixed GCC 3.4 warning
36 * Revision 1.50 2004/04/21 00:32:02 csoutheren
37 * Fixed problem with XER and the new RTTI system
38 * Thanks to Federico Pinna and Reitek S.p.A.
40 * Revision 1.49 2004/04/13 11:33:55 csoutheren
41 * Fixed XER output, thanks to Federico Pinna
43 * Revision 1.48 2004/04/03 08:22:23 csoutheren
44 * Remove pseudo-RTTI and replaced with real RTTI
46 * Revision 1.47 2004/02/17 10:24:04 rjongbloed
47 * Updated version number so will rebuild ASN files.
49 * Revision 1.46 2004/02/17 09:38:24 csoutheren
50 * Added change to remove duplicate forward declarations
51 * See SourceForge bug 832245
52 * Thanks to Vyacheslav E. Andrejev
54 * Revision 1.45 2003/10/03 00:13:04 rjongbloed
55 * Added ability to specify CHOICE field selection by function rather than operator as the operator technique does not work with some dumb compilers.
56 * Added ability to specify that the header file name be different from the module name and module prefix string.
58 * Revision 1.44 2003/02/27 04:05:30 robertj
59 * Added ability to have alternate directories for header file
60 * includes in generated C++ code.
61 * Added constructors to PASN_OctetString descendant classes to help
62 * with doing simple assignments.
64 * Revision 1.43 2003/02/26 01:57:44 robertj
65 * Added XML encoding rules to ASN system, thanks Federico Pinna
67 * Revision 1.42 2003/02/19 14:18:55 craigs
68 * Fixed ifdef problem with multipart cxx files
70 * Revision 1.41 2003/02/18 10:50:41 craigs
71 * Added minor optimisation of outputted ASN code
72 * Added automatic insertion of defines to allow disabling of generated code
74 * Revision 1.40 2002/11/27 11:42:52 robertj
75 * Rearranged code to avoid GNU compiler problem.
76 * Changed new classheader parameters to be full C literal like string for
77 * improved backslash conversion.
78 * Incremented version number.
80 * Revision 1.39 2002/11/26 11:39:10 craigs
81 * Added option to allow adding functions to generated header files
83 * Revision 1.38 2002/09/16 01:08:59 robertj
84 * Added #define so can select if #pragma interface/implementation is used on
85 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
87 * Revision 1.37 2001/10/02 00:56:14 robertj
88 * Fixed problem with autonumering enumerated types.
90 * Revision 1.36 2001/08/06 01:39:02 robertj
91 * Added assignement operator with RHS of PASN_BMPString to classes
92 * descended from PASN_BMPString.
94 * Revision 1.35 2001/08/03 09:01:02 robertj
95 * Added assignement operator with RHS of PWORDArray to classes
96 * descended from PASN_BMPString.
98 * Revision 1.34 2001/06/14 02:09:20 robertj
99 * Corrected support for ASN object class type reference constructs
100 * ie TYPE-IDENTIFIER.&Type encoded as octet string.
102 * Revision 1.33 2001/04/26 08:15:58 robertj
103 * Fixed problem with ASN compile of single constraints on enumerations.
105 * Revision 1.32 2001/04/23 04:40:14 robertj
106 * Added ASN standard types GeneralizedTime and UTCTime
108 * Revision 1.31 2001/02/22 23:31:42 robertj
109 * Fixed display of version number just added.
111 * Revision 1.30 2001/02/22 22:31:01 robertj
112 * Added command line flag to display version number only.
114 * Revision 1.29 2000/10/12 23:11:48 robertj
115 * Fixed problem with BER encoding of ASN with optional fields.
117 * Revision 1.28 2000/06/26 13:14:46 robertj
118 * Nucleus++ port.
120 * Revision 1.27 2000/03/21 21:23:23 robertj
121 * Added option to rename imported module names, allows include filename matching.
123 * Revision 1.26 2000/01/19 12:33:07 robertj
124 * Fixed parsing of OID's in IMPORTS section.
126 * Revision 1.25 2000/01/19 03:38:12 robertj
127 * Fixed support for parsing multiple IMPORTS
129 * Revision 1.24 1999/09/18 04:17:40 robertj
130 * Added generation of C++ inlines for some functions.
131 * Optimised CreateObject() switch statements, collapsing common cases.
133 * Revision 1.23 1999/09/18 02:42:27 craigs
134 * Added optimisation to collapse switch arms in CreateObject functions
136 * Revision 1.22 1999/09/07 09:56:04 robertj
137 * Fixed failure to put "using anmespace" in every generated .cxx file.
139 * Revision 1.21 1999/08/28 01:48:55 robertj
140 * Fixed anomaly to always include non-optional extensions in encodings.
142 * Revision 1.20 1999/08/09 13:02:36 robertj
143 * Added ASN compiler #defines for backward support of pre GCC 2.9 compilers.
144 * Added ASN compiler #defines to reduce its memory footprint.
145 * Added ASN compiler code generation of assignment operators for string classes.
147 * Revision 1.19 1999/07/22 06:48:55 robertj
148 * Added comparison operation to base ASN classes and compiled ASN code.
149 * Added support for ANY type in ASN parser.
151 * Revision 1.18 1999/07/06 05:00:26 robertj
152 * Incremented release number
154 * Revision 1.17 1999/07/01 12:21:46 robertj
155 * Changed PASN_Choice cast operators so no longer "break" const-ness of object.
157 * Revision 1.16 1999/06/30 08:57:19 robertj
158 * Fixed bug in encodeing sequence of constrained primitive type. Constraint not set.
159 * Fixed bug in not emitting namespace use clause.
160 * Added "normalisation" of separate sequence of <base type> to be single class.
162 * Revision 1.15 1999/06/14 13:00:15 robertj
163 * Fixed bug in code generation for string constraints.
165 * Revision 1.14 1999/06/09 06:58:09 robertj
166 * Adjusted heading comments.
168 * Revision 1.13 1999/06/09 02:07:49 robertj
169 * Fixed backward compatibility of generated template code with G++ 2.7.x
171 * Revision 1.12 1999/06/07 01:56:25 robertj
172 * Added header comment on license.
176 #include <ptlib.h>
178 #include "main.h"
179 #include "asn_grammar.h"
182 #define MAJOR_VERSION 1
183 #define MINOR_VERSION 9
184 #define BUILD_TYPE ReleaseCode
185 #define BUILD_NUMBER 1
188 unsigned lineNumber;
189 PString fileName;
191 unsigned fatals, warnings;
193 extern FILE * yyin;
194 extern int yydebug;
195 extern int LexEcho;
197 ModuleDefinition * Module;
200 static const char * UniversalTagClassNames[] = {
201 "UniversalTagClass",
202 "ApplicationTagClass",
203 "ContextSpecificTagClass",
204 "PrivateTagClass"
207 static const char * UniversalTagNames[] = {
208 NULL,
209 "UniversalBoolean",
210 "UniversalInteger",
211 "UniversalBitString",
212 "UniversalOctetString",
213 "UniversalNull",
214 "UniversalObjectId",
215 "UniversalObjectDescriptor",
216 "UniversalExternalType",
217 "UniversalReal",
218 "UniversalEnumeration",
219 "UniversalEmbeddedPDV",
220 NULL,
221 NULL,
222 NULL,
223 NULL,
224 "UniversalSequence",
225 "UniversalSet",
226 "UniversalNumericString",
227 "UniversalPrintableString",
228 "UniversalTeletexString",
229 "UniversalVideotexString",
230 "UniversalIA5String",
231 "UniversalUTCTime",
232 "UniversalGeneralisedTime",
233 "UniversalGraphicString",
234 "UniversalVisibleString",
235 "UniversalGeneralString",
236 "UniversalUniversalString",
237 NULL,
238 "UniversalBMPString"
242 static const char * const StandardClasses[] = {
243 "PASN_Null",
244 "PASN_Boolean",
245 "PASN_Integer",
246 "PASN_Enumeration",
247 "PASN_Real",
248 "PASN_ObjectId",
249 "PASN_BitString",
250 "PASN_OctetString",
251 "PASN_NumericString",
252 "PASN_PrintableString",
253 "PASN_VisibleString",
254 "PASN_IA5String",
255 "PASN_GeneralString",
256 "PASN_BMPString",
257 "PASN_Sequence"
261 /////////////////////////////////////////
263 // yyerror
264 // required function for flex
267 void yyerror(char * str)
269 extern char * yytext;
270 PError << StdError(Fatal) << str << " near token \"" << yytext <<"\"\n";
273 ostream & operator<<(ostream & out, const StdError & e)
275 out << fileName << '(' << lineNumber << ") : ";
276 if (e.e == Fatal) {
277 fatals++;
278 out << "error";
280 else {
281 warnings++;
282 out << "warning";
284 return out << ": ";
288 /////////////////////////////////////////////////////////
290 // Utility
293 static PString MakeIdentifierC(const PString & identifier)
295 PString s = identifier;
296 s.Replace("-", "_", TRUE);
297 return s;
301 class OutputFile : public PTextFile
303 PCLASSINFO(OutputFile, PTextFile);
304 public:
305 ~OutputFile() { Close(); }
307 BOOL Open(const PFilePath & path, const PString & suffix, const char * extension);
308 BOOL Close();
312 BOOL OutputFile::Open(const PFilePath & path,
313 const PString & suffix,
314 const char * extension)
316 PFilePath fn = path.GetDirectory() + path.GetTitle() + suffix;
317 fn.SetType(extension);
319 if (PTextFile::Open(fn, WriteOnly))
320 *this << "//\n"
321 "// " << GetFilePath().GetFileName() << "\n"
322 "//\n"
323 "// Code automatically generated by asnparse.\n"
324 "//\n"
325 "\n";
326 else
327 PError << PProcess::Current().GetName() << ": cannot create \""
328 << GetFilePath() << "\" :" << GetErrorText() << endl;
330 return IsOpen();
334 BOOL OutputFile::Close()
336 if (IsOpen())
337 *this << "\n"
338 "// End of " << GetFilePath().GetFileName() << '\n';
340 return PTextFile::Close();
344 /////////////////////////////////////////////////////////
346 // Application
349 class App : public PProcess
351 PCLASSINFO(App, PProcess);
352 public:
353 App();
354 void Main();
355 BOOL SetClassHeaderFile(PArgList & args);
356 BOOL SetClassHeader(PArgList & args);
357 void OutputAdditionalHeaders(ostream & hdr, const PString & className);
358 protected:
359 PStringToString classToHeader;
362 PCREATE_PROCESS(App);
364 App::App()
365 : PProcess("Equivalence", "ASNParse", MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
369 void App::Main()
371 cout << GetName() << " version " << GetVersion(TRUE)
372 << " for " << GetOSClass() << ' ' << GetOSName()
373 << " by " << GetManufacturer() << endl;
375 PArgList & args = GetArguments();
376 args.Parse("c-c++."
377 "d-debug."
378 "e-echo."
379 "h-hdr-prefix:"
380 "i-inlines."
381 "m-module:"
382 "n-namespace."
383 "o-output:"
384 "r-rename:"
385 "s-split;"
386 "V-version."
387 "v-verbose."
388 "x-xml."
389 "-no-operators."
390 "-classheader:"
391 "-classheaderfile:");
393 if (args.HasOption('V'))
394 return;
396 unsigned numFiles = 1;
397 if (args.HasOption('s')) {
398 PString numFilesStr = args.GetOptionString('s');
399 if (numFilesStr.IsEmpty())
400 numFiles = 2;
401 else
402 numFiles = numFilesStr.AsUnsigned();
405 if (args.GetCount() < 1 || args.GetCount() > 1 || numFiles == 0) {
406 PError << "usage: asnparse [options] asnfile\n"
407 " -V --version Display version and exit\n"
408 " -v --verbose Verbose output (multiple times for more verbose)\n"
409 " -e --echo Echo input file\n"
410 " -d --debug Debug output (copious!)\n"
411 " -c --c++ Generate C++ files\n"
412 " -n --namespace Use C++ namespace\n"
413 " -h --hdr-prefix str Prefix for C++ include of header (eg directory)\n"
414 " -i --inlines Use C++ inlines\n"
415 " -s[n] --split[n] Split output into n (default 2) files\n"
416 " -m --module name Module name prefix/namespace\n"
417 " -r --rename args Rename import module where arg is:\n"
418 " from=name[,prefix[,fname]]\n"
419 " from is module name in ASN file\n"
420 " name is target header file name\n"
421 " prefix is optional prefix for include\n"
422 " (eg header directory)\n"
423 " fname is optional base name for header files\n"
424 " --no-operators Generate functions instead of operators for choice\n"
425 " sub-object extraction.\n"
426 " -x --xml X.693 support (XER)\n"
427 " -o --output file Output filename/directory\n"
428 << endl;
429 return;
432 PTextFile prcFile;
433 if (!prcFile.Open(args[0], PFile::ReadOnly)) {
434 PError << GetName() << ": cannot open \""
435 << prcFile.GetFilePath() << "\" :" << prcFile.GetErrorText() << endl;
436 return;
439 if (args.HasOption('d'))
440 yydebug = 1;
441 if (args.HasOption('e'))
442 LexEcho = TRUE;
444 fileName = prcFile.GetFilePath();
445 lineNumber = 1;
446 fatals = 0;
447 warnings = 0;
449 if (args.HasOption("classheaderfile")) {
450 if (!SetClassHeaderFile(args))
451 return;
454 if (args.HasOption("classheader")) {
455 if (!SetClassHeader(args))
456 return;
459 if (args.HasOption('v'))
460 cout << "Parsing..." << endl;
462 yyin = _fdopen(prcFile.GetHandle(), "r");
463 PAssert(yyin != NULL, "fdopen failed!");
464 yyparse();
466 if (Module != NULL) {
467 if (args.GetOptionCount('v') > 1)
468 PError << "Module " << *Module << endl;
470 if (args.HasOption('c'))
471 Module->GenerateCplusplus(args.GetOptionString('o', args[0]),
472 args.GetOptionString('m'),
473 args.GetOptionString('h'),
474 numFiles,
475 args.HasOption('n'),
476 args.HasOption('i'),
477 !args.HasOption("no-operators"),
478 args.HasOption('v'));
483 BOOL App::SetClassHeaderFile(PArgList & args)
485 PStringArray lines = args.GetOptionString("classheaderfile").Lines();
486 if (lines.IsEmpty()) {
487 PError << GetName() << ": malformed --classheaderfile option\n";
488 return FALSE;
491 for (PINDEX i = 0; i < lines.GetSize(); i++) {
492 PString str = lines[i];
493 PINDEX pos = str.Find("=");
494 if (pos == P_MAX_INDEX) {
495 PError << GetName() << ": malformed --classheaderfile option\n";
496 return FALSE;
499 PFilePath fn = str.Right(pos+1);
500 PTextFile file(fn, PFile::ReadOnly);
501 if (!file.IsOpen()) {
502 PError << GetName() << ": cannot open file required for --classheaderfile option \"" << fn
503 << "\" :" << file.GetErrorText() << '\n';
504 return FALSE;
507 PString text;
508 PString line;
509 while (file.ReadLine(line))
510 text += PString(PString::Literal, (const char *)line) + '\n';
511 classToHeader.SetAt(str.Left(pos), text);
514 return TRUE;
518 BOOL App::SetClassHeader(PArgList & args)
520 PStringArray lines = args.GetOptionString("classheader").Lines();
521 if (lines.IsEmpty()) {
522 PError << GetName() << ": malformed --classheader option\n";
523 return FALSE;
526 for (PINDEX i = 0; i < lines.GetSize(); i++) {
527 PString str = lines[i];
528 PINDEX pos = str.Find("=");
529 if (pos == P_MAX_INDEX) {
530 PError << GetName() << ": malformed --classheader option\n";
531 return FALSE;
534 PString text(PString::Literal, (const char *)str.Mid(pos+1));
535 classToHeader.SetAt(str.Left(pos), text);
538 return TRUE;
542 void App::OutputAdditionalHeaders(ostream & hdr, const PString & className)
544 if (classToHeader.Contains(className)) {
545 hdr << "// following code added by command line option\n"
546 "\n"
547 << classToHeader[className] << "\n"
548 "\n"
549 "// end of added code\n"
550 "\n";
554 /////////////////////////////////////////
556 // miscellaneous
559 class indent
561 public:
562 indent() { }
563 friend ostream & operator<<(ostream & s, const indent &)
564 { return s << setw(Module->GetIndentLevel()*3) << ' '; }
568 /////////////////////////////////////////
570 // intermediate structures from parser
573 NamedNumber::NamedNumber(PString * nam)
574 : name(*nam)
576 delete nam;
577 number = 0;
578 autonumber = TRUE;
582 NamedNumber::NamedNumber(PString * nam, int num)
583 : name(*nam)
585 delete nam;
586 number = num;
587 autonumber = FALSE;
591 NamedNumber::NamedNumber(PString * nam, const PString & ref)
592 : name(*nam), reference(ref)
594 delete nam;
595 number = 0;
596 autonumber = FALSE;
600 void NamedNumber::PrintOn(ostream & strm) const
602 strm << name << " (";
603 if (reference.IsEmpty())
604 strm << number;
605 else
606 strm << reference;
607 strm << ')';
611 void NamedNumber::SetAutoNumber(const NamedNumber & prev)
613 if (autonumber) {
614 number = prev.number + 1;
615 autonumber = FALSE;
620 /////////////////////////////////////////////////////////
622 Tag::Tag(unsigned tagNum)
624 type = Universal;
625 number = tagNum;
626 mode = Module->GetDefaultTagMode();
630 const char * Tag::classNames[] = {
631 "UNIVERSAL", "APPLICATION", "CONTEXTSPECIFIC", "PRIVATE"
635 const char * Tag::modeNames[] = {
636 "IMPLICIT", "EXPLICIT", "AUTOMATIC"
640 void Tag::PrintOn(ostream & strm) const
642 if (type != Universal || number != IllegalUniversalTag) {
643 strm << '[';
644 if (type != ContextSpecific)
645 strm << classNames[type] << ' ';
646 strm << number << "] " << modeNames[mode] << ' ';
651 /////////////////////////////////////////////////////////
653 Constraint::Constraint(ConstraintElementBase * elmt)
655 standard.Append(elmt);
656 extendable = FALSE;
660 Constraint::Constraint(ConstraintElementList * stnd, BOOL extend, ConstraintElementList * ext)
662 if (stnd != NULL) {
663 standard = *stnd;
664 delete stnd;
666 extendable = extend;
667 if (ext != NULL) {
668 extensions = *ext;
669 delete ext;
674 void Constraint::PrintOn(ostream & strm) const
676 strm << '(';
677 for (PINDEX i = 0; i < standard.GetSize(); i++)
678 strm << standard[i];
679 if (extendable) {
680 strm << indent();
681 if (standard.GetSize() > 0)
682 strm << ", ";
683 strm << "..., ";
684 for (PINDEX i = 0; i < extensions.GetSize(); i++)
685 strm << extensions[i];
687 strm << ')';
691 void Constraint::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
693 switch (standard.GetSize()) {
694 case 0 :
695 return;
696 case 1 :
697 break;
698 default :
699 PError << StdError(Warning) << "unsupported UNION constraints, ignored." << endl;
702 if (extensions.GetSize() > 0)
703 PError << StdError(Warning) << "unsupported extension constraints, ignored." << endl;
705 PString fn2 = fn;
706 if (fn.Find("PASN_Object::") == P_MAX_INDEX) {
707 if (extendable)
708 fn2 += "PASN_Object::ExtendableConstraint";
709 else
710 fn2 += "PASN_Object::FixedConstraint";
713 standard[0].GenerateCplusplus(fn2, hdr, cxx);
717 BOOL Constraint::ReferencesType(const TypeBase & type)
719 PINDEX i;
721 for (i = 0; i < standard.GetSize(); i++) {
722 if (standard[i].ReferencesType(type))
723 return TRUE;
726 for (i = 0; i < extensions.GetSize(); i++) {
727 if (extensions[i].ReferencesType(type))
728 return TRUE;
731 return FALSE;
735 /////////////////////////////////////////////////////////
737 ConstraintElementBase::ConstraintElementBase()
739 exclusions = NULL;
743 void ConstraintElementBase::GenerateCplusplus(const PString &, ostream &, ostream &)
745 PError << StdError(Warning) << "unsupported constraint, ignored." << endl;
749 BOOL ConstraintElementBase::ReferencesType(const TypeBase &)
751 return FALSE;
755 /////////////////////////////////////////////////////////
757 ConstrainAllConstraintElement::ConstrainAllConstraintElement(ConstraintElementBase * excl)
759 SetExclusions(excl);
763 /////////////////////////////////////////////////////////
765 ElementListConstraintElement::ElementListConstraintElement(ConstraintElementList * list)
766 : elements(*list)
768 delete list;
772 void ElementListConstraintElement::PrintOn(ostream & strm) const
774 elements.PrintOn(strm);
778 void ElementListConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
780 for (PINDEX i = 0; i < elements.GetSize(); i++)
781 elements[i].GenerateCplusplus(fn, hdr, cxx);
785 BOOL ElementListConstraintElement::ReferencesType(const TypeBase & type)
787 for (PINDEX i = 0; i < elements.GetSize(); i++) {
788 if (elements[i].ReferencesType(type))
789 return TRUE;
791 return FALSE;
795 /////////////////////////////////////////////////////////
797 SingleValueConstraintElement::SingleValueConstraintElement(ValueBase * val)
799 value = val;
803 SingleValueConstraintElement::~SingleValueConstraintElement()
805 delete value;
809 void SingleValueConstraintElement::PrintOn(ostream & strm) const
811 strm << *value;
815 void SingleValueConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
817 cxx << fn << ", ";
818 value->GenerateCplusplus(hdr, cxx);
819 cxx << ");\n";
823 /////////////////////////////////////////////////////////
825 ValueRangeConstraintElement::ValueRangeConstraintElement(ValueBase * lowerBound, ValueBase * upperBound)
827 lower = lowerBound;
828 upper = upperBound;
832 ValueRangeConstraintElement::~ValueRangeConstraintElement()
834 delete lower;
835 delete upper;
839 void ValueRangeConstraintElement::PrintOn(ostream & strm) const
841 strm << *lower << ".." << *upper;
845 void ValueRangeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
847 cxx << fn << ", ";
848 lower->GenerateCplusplus(hdr, cxx);
849 cxx << ", ";
850 upper->GenerateCplusplus(hdr, cxx);
851 cxx << ");\n";
855 /////////////////////////////////////////////////////////
857 SubTypeConstraintElement::SubTypeConstraintElement(TypeBase * typ)
859 subtype = typ;
863 SubTypeConstraintElement::~SubTypeConstraintElement()
865 delete subtype;
869 void SubTypeConstraintElement::PrintOn(ostream & strm) const
871 strm << subtype->GetTypeName();
875 void SubTypeConstraintElement::GenerateCplusplus(const PString &, ostream & hdr, ostream &)
877 hdr << subtype->GetTypeName();
881 BOOL SubTypeConstraintElement::ReferencesType(const TypeBase & type)
883 return subtype->ReferencesType(type);
887 /////////////////////////////////////////////////////////
889 NestedConstraintConstraintElement::NestedConstraintConstraintElement(Constraint * con)
891 constraint = con;
895 NestedConstraintConstraintElement::~NestedConstraintConstraintElement()
897 delete constraint;
901 BOOL NestedConstraintConstraintElement::ReferencesType(const TypeBase & type)
903 if (constraint == NULL)
904 return FALSE;
906 return constraint->ReferencesType(type);
910 /////////////////////////////////////////////////////////
912 SizeConstraintElement::SizeConstraintElement(Constraint * constraint)
913 : NestedConstraintConstraintElement(constraint)
918 void SizeConstraintElement::PrintOn(ostream & strm) const
920 strm << "SIZE" << *constraint;
924 void SizeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
926 constraint->GenerateCplusplus(fn, hdr, cxx);
930 /////////////////////////////////////////////////////////
932 FromConstraintElement::FromConstraintElement(Constraint * constraint)
933 : NestedConstraintConstraintElement(constraint)
938 void FromConstraintElement::PrintOn(ostream & strm) const
940 strm << "FROM" << *constraint;
944 void FromConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
946 PString newfn = fn;
947 newfn.Replace("SetConstraints(", "SetCharacterSet(");
948 constraint->GenerateCplusplus(newfn, hdr, cxx);
952 /////////////////////////////////////////////////////////
954 WithComponentConstraintElement::WithComponentConstraintElement(PString * newName,
955 Constraint * constraint,
956 int pres)
957 : NestedConstraintConstraintElement(constraint)
959 if (newName != NULL) {
960 name = *newName;
961 delete newName;
964 presence = pres;
968 void WithComponentConstraintElement::PrintOn(ostream & strm) const
970 if (name.IsEmpty())
971 strm << "WITH COMPONENT";
972 else
973 strm << name;
975 if (constraint != NULL)
976 strm << *constraint;
978 switch (presence) {
979 case Present :
980 strm << " PRESENT";
981 break;
982 case Absent :
983 strm << " ABSENT";
984 break;
985 case Optional :
986 strm << " OPTIONAL";
987 break;
992 void WithComponentConstraintElement::GenerateCplusplus(const PString &, ostream &, ostream & cxx)
994 if (presence == Present)
995 cxx << " IncludeOptionalField(e_" << name << ");\n";
999 /////////////////////////////////////////////////////////
1001 InnerTypeConstraintElement::InnerTypeConstraintElement(ConstraintElementList * list,
1002 BOOL part)
1003 : ElementListConstraintElement(list)
1005 partial = part;
1009 void InnerTypeConstraintElement::PrintOn(ostream & strm) const
1011 strm << "WITH COMPONENTS { ";
1013 if (partial)
1014 strm << "..., ";
1016 for (PINDEX i = 0; i < elements.GetSize(); i++) {
1017 if (i > 0)
1018 strm << ", ";
1019 elements[i].PrintOn(strm);
1022 strm << " }";
1026 void InnerTypeConstraintElement::GenerateCplusplus(const PString & fn, ostream & hdr, ostream & cxx)
1028 for (PINDEX i = 0; i < elements.GetSize(); i++)
1029 elements[i].GenerateCplusplus(fn, hdr, cxx);
1033 /////////////////////////////////////////////////////////
1035 UserDefinedConstraintElement::UserDefinedConstraintElement(TypesList * t)
1037 if (t != NULL) {
1038 types = *t;
1039 delete t;
1044 void UserDefinedConstraintElement::PrintOn(ostream & strm) const
1046 strm << "CONSTRAINED BY { ";
1047 for (PINDEX i = 0; i < types.GetSize(); i++) {
1048 if (i > 0)
1049 strm << ", ";
1050 strm << types[i].GetTypeName();
1052 strm << " }";
1056 void UserDefinedConstraintElement::GenerateCplusplus(const PString &, ostream &, ostream &)
1061 /////////////////////////////////////////////////////////
1063 TypeBase::TypeBase(unsigned tagNum)
1064 : tag(tagNum), defaultTag(tagNum)
1066 isOptional = FALSE;
1067 defaultValue = NULL;
1068 isGenerated = FALSE;
1072 TypeBase::TypeBase(TypeBase * copy)
1073 : name(copy->name),
1074 identifier(MakeIdentifierC(name)),
1075 tag(copy->tag),
1076 defaultTag(copy->tag)
1078 isOptional = copy->isOptional;
1079 defaultValue = NULL;
1080 isGenerated = FALSE;
1084 PObject::Comparison TypeBase::Compare(const PObject & obj) const
1086 return name.Compare(((const TypeBase &)obj).name);
1090 void TypeBase::PrintOn(ostream & strm) const
1092 PrintStart(strm);
1093 PrintFinish(strm);
1097 void TypeBase::PrintStart(ostream & strm) const
1099 strm << indent();
1100 if (!name) {
1101 strm << name;
1102 if (!parameters.IsEmpty()) {
1103 strm << " { ";
1104 for (PINDEX i = 0; i < parameters.GetSize(); i++) {
1105 if (i > 0)
1106 strm << ", ";
1107 strm << parameters[i];
1109 strm << " } ";
1111 strm << ": ";
1113 strm << tag << GetClass() << ' ';
1114 Module->SetIndentLevel(1);
1118 void TypeBase::PrintFinish(ostream & strm) const
1120 Module->SetIndentLevel(-1);
1121 strm << ' ' << constraints;
1122 if (isOptional)
1123 strm << " OPTIONAL";
1124 if (defaultValue != NULL)
1125 strm << " DEFAULT " << *defaultValue;
1126 strm << '\n';
1130 int TypeBase::GetIdentifierTokenContext() const
1132 return IDENTIFIER;
1136 int TypeBase::GetBraceTokenContext() const
1138 return '{';
1142 void TypeBase::SetName(PString * newName)
1144 name = *newName;
1145 delete newName;
1146 identifier = MakeIdentifierC(name);
1150 void TypeBase::AdjustIdentifier()
1152 identifier = Module->GetPrefix() + MakeIdentifierC(name);
1156 void TypeBase::SetTag(Tag::Type type, unsigned num, Tag::Mode mode)
1158 tag.type = type;
1159 tag.number = num;
1160 tag.mode = mode;
1164 void TypeBase::SetParameters(PStringList * list)
1166 parameters = *list;
1167 delete list;
1171 void TypeBase::MoveConstraints(TypeBase * from)
1173 from->constraints.DisallowDeleteObjects();
1175 while (!from->constraints.IsEmpty())
1176 constraints.Append(from->constraints.RemoveAt(0));
1178 from->constraints.AllowDeleteObjects();
1182 void TypeBase::FlattenUsedTypes()
1187 TypeBase * TypeBase::FlattenThisType(const TypeBase &)
1189 return this;
1193 BOOL TypeBase::IsChoice() const
1195 return FALSE;
1199 BOOL TypeBase::IsParameterizedType() const
1201 return FALSE;
1205 BOOL TypeBase::IsPrimitiveType() const
1207 return TRUE;
1211 void TypeBase::GenerateCplusplus(ostream & hdr, ostream & cxx)
1213 BeginGenerateCplusplus(hdr, cxx);
1215 // Close off the constructor implementation
1216 cxx << ")\n"
1217 "{\n";
1218 GenerateCplusplusConstraints(PString(), hdr, cxx);
1220 EndGenerateCplusplus(hdr, cxx);
1224 void TypeBase::GenerateForwardDecls(ostream &)
1229 void TypeBase::GenerateOperators(ostream &, ostream &, const TypeBase &)
1234 PString TypeBase::GetTypeName() const
1236 return GetAncestorClass();
1240 BOOL TypeBase::CanReferenceType() const
1242 return FALSE;
1246 BOOL TypeBase::ReferencesType(const TypeBase &)
1248 return FALSE;
1252 void TypeBase::SetImportPrefix(const PString &)
1257 BOOL TypeBase::IsParameterisedImport() const
1259 return FALSE;
1263 void TypeBase::BeginGenerateCplusplus(ostream & hdr, ostream & cxx)
1265 classNameString = GetIdentifier();
1267 if (!parameters.IsEmpty()) {
1268 templatePrefix = "template <";
1269 classNameString += '<';
1270 for (PINDEX i = 0; i < parameters.GetSize(); i++) {
1271 if (i > 0) {
1272 templatePrefix += ", ";
1273 classNameString += ", ";
1275 PString ident = MakeIdentifierC(parameters[i]);
1276 templatePrefix += "class " + ident;
1277 classNameString += ident;
1279 templatePrefix += ">\n";
1280 classNameString += '>';
1283 // Output header file declaration of class
1284 hdr << "//\n"
1285 "// " << GetName() << "\n"
1286 "//\n"
1287 "\n";
1288 GenerateForwardDecls(hdr);
1289 hdr << templatePrefix
1290 << "class " << GetIdentifier() << " : public " << GetTypeName() << "\n"
1291 "{\n"
1292 "#ifndef PASN_LEANANDMEAN\n"
1293 " PCLASSINFO(" << GetIdentifier() << ", " << GetTypeName() << ");\n"
1294 "#endif\n"
1295 " public:\n"
1296 " " << GetIdentifier() << "(unsigned tag = ";
1297 if (tag.type == Tag::Universal &&
1298 tag.number < PARRAYSIZE(UniversalTagNames) &&
1299 UniversalTagNames[tag.number] != NULL)
1300 hdr << UniversalTagNames[tag.number];
1301 else
1302 hdr << tag.number;
1303 hdr << ", TagClass tagClass = " << UniversalTagClassNames[tag.type] << ");\n\n";
1305 App & app = (App &)PProcess::Current();
1306 app.OutputAdditionalHeaders(hdr, GetIdentifier());
1308 // Output cxx file implementation of class
1309 cxx << "//\n"
1310 "// " << GetName() << "\n"
1311 "//\n"
1312 "\n"
1313 << GetTemplatePrefix()
1314 << GetClassNameString() << "::" << GetIdentifier() << "(unsigned tag, PASN_Object::TagClass tagClass)\n"
1315 " : " << GetTypeName() << "(tag, tagClass";
1319 void TypeBase::EndGenerateCplusplus(ostream & hdr, ostream & cxx)
1321 cxx << "}\n"
1322 "\n"
1323 "\n";
1325 GenerateOperators(hdr, cxx, *this);
1327 // Output header file declaration of class
1328 hdr << " PObject * Clone() const;\n"
1329 "};\n"
1330 "\n"
1331 "\n";
1333 // Output cxx file implementation of class
1334 cxx << GetTemplatePrefix()
1335 << "PObject * " << GetClassNameString() << "::Clone() const\n"
1336 "{\n"
1337 "#ifndef PASN_LEANANDMEAN\n"
1338 " PAssert(IsClass(" << GetClassNameString() << "::Class()), PInvalidCast);\n"
1339 "#endif\n"
1340 " return new " << GetClassNameString() << "(*this);\n"
1341 "}\n"
1342 "\n"
1343 "\n";
1345 isGenerated = TRUE;
1349 void TypeBase::GenerateCplusplusConstructor(ostream &, ostream & cxx)
1351 cxx << '(';
1352 if (HasNonStandardTag()) {
1353 if (tag.type == Tag::Universal &&
1354 tag.number < PARRAYSIZE(UniversalTagNames) &&
1355 UniversalTagNames[tag.number] != NULL)
1356 cxx << UniversalTagNames[tag.number];
1357 else
1358 cxx << tag.number;
1359 cxx << ", " << UniversalTagClassNames[tag.type];
1361 cxx << ')';
1365 void TypeBase::GenerateCplusplusConstraints(const PString & prefix, ostream & hdr, ostream & cxx)
1367 for (PINDEX i = 0; i < constraints.GetSize(); i++)
1368 constraints[i].GenerateCplusplus(" " + prefix + "SetConstraints(", hdr, cxx);
1372 /////////////////////////////////////////////////////////
1374 DefinedType::DefinedType(PString * name, BOOL parameter)
1375 : TypeBase(Tag::IllegalUniversalTag),
1376 referenceName(*name)
1378 delete name;
1379 baseType = NULL;
1380 unresolved = !parameter;
1384 DefinedType::DefinedType(TypeBase * refType, TypeBase * bType)
1385 : TypeBase(refType),
1386 referenceName(bType->GetName())
1388 MoveConstraints(refType);
1390 baseType = bType;
1391 unresolved = FALSE;
1395 DefinedType::DefinedType(TypeBase * refType, const PString & refName)
1396 : TypeBase(refType)
1398 MoveConstraints(refType);
1399 ConstructFromType(refType, refName);
1403 DefinedType::DefinedType(TypeBase * refType, const TypeBase & parent)
1404 : TypeBase(refType)
1406 if (!name)
1407 ConstructFromType(refType, parent.GetName() + '_' + name);
1408 else
1409 ConstructFromType(refType, parent.GetName() + "_subtype");
1413 void DefinedType::ConstructFromType(TypeBase * refType, const PString & name)
1415 referenceName = name;
1416 refType->SetName(new PString(name));
1418 Module->AppendType(refType);
1420 baseType = refType;
1421 unresolved = FALSE;
1425 void DefinedType::PrintOn(ostream & strm) const
1427 PrintStart(strm);
1428 strm << referenceName << ' ';
1429 PrintFinish(strm);
1433 BOOL DefinedType::CanReferenceType() const
1435 return TRUE;
1439 BOOL DefinedType::IsChoice() const
1441 if (baseType != NULL)
1442 return baseType->IsChoice();
1443 return FALSE;
1447 BOOL DefinedType::IsParameterizedType() const
1449 if (baseType != NULL)
1450 return baseType->IsParameterizedType();
1451 return FALSE;
1455 BOOL DefinedType::ReferencesType(const TypeBase & type)
1457 if (unresolved) {
1458 unresolved = FALSE;
1460 if ((baseType = Module->FindType(referenceName)) == NULL)
1461 PError << StdError(Warning) << "unresolved symbol: " << referenceName << endl;
1462 else {
1463 if (!HasNonStandardTag())
1464 defaultTag = tag = baseType->GetTag();
1468 return type.GetName() == referenceName;
1472 void DefinedType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1474 if (baseType != NULL)
1475 baseType->GenerateOperators(hdr, cxx, actualType);
1479 const char * DefinedType::GetAncestorClass() const
1481 if (baseType != NULL)
1482 return baseType->GetAncestorClass();
1483 return NULL;
1487 PString DefinedType::GetTypeName() const
1489 if (baseType == NULL)
1490 return referenceName;
1492 if (HasConstraints() && baseType->IsPrimitiveType())
1493 return baseType->GetTypeName();
1495 return baseType->GetIdentifier();
1499 /////////////////////////////////////////////////////////
1501 ParameterizedType::ParameterizedType(PString * name, TypesList * args)
1502 : DefinedType(name, FALSE),
1503 arguments(*args)
1505 delete args;
1509 void ParameterizedType::PrintOn(ostream & strm) const
1511 PrintStart(strm);
1512 strm << referenceName << " { ";
1513 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1514 if (i > 0)
1515 strm << ", ";
1516 strm << arguments[i].GetTypeName();
1518 strm << " }";
1519 PrintFinish(strm);
1523 BOOL ParameterizedType::IsParameterizedType() const
1525 return TRUE;
1529 BOOL ParameterizedType::ReferencesType(const TypeBase & type)
1531 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1532 if (arguments[i].ReferencesType(type))
1533 return TRUE;
1536 return DefinedType::ReferencesType(type);
1540 PString ParameterizedType::GetTypeName() const
1542 PString typeName = DefinedType::GetTypeName();
1543 if (!arguments.IsEmpty()) {
1544 typeName += '<';
1545 for (PINDEX i = 0; i < arguments.GetSize(); i++) {
1546 if (i > 0)
1547 typeName += ", ";
1548 typeName += arguments[i].GetTypeName();
1550 typeName += '>';
1552 return typeName;
1556 /////////////////////////////////////////////////////////
1558 SelectionType::SelectionType(PString * name, TypeBase * base)
1559 : TypeBase(Tag::IllegalUniversalTag),
1560 selection(*name)
1562 delete name;
1563 baseType = PAssertNULL(base);
1567 SelectionType::~SelectionType()
1569 delete baseType;
1573 void SelectionType::PrintOn(ostream & strm) const
1575 PrintStart(strm);
1576 strm << selection << '<' << *baseType;
1577 PrintFinish(strm);
1581 void SelectionType::FlattenUsedTypes()
1583 baseType = baseType->FlattenThisType(*this);
1587 TypeBase * SelectionType::FlattenThisType(const TypeBase & parent)
1589 return new DefinedType(this, parent);
1593 void SelectionType::GenerateCplusplus(ostream &, ostream &)
1595 PError << StdError(Fatal) << "Cannot generate code for Selection type" << endl;
1596 isGenerated = TRUE;
1600 const char * SelectionType::GetAncestorClass() const
1602 return "";
1606 BOOL SelectionType::CanReferenceType() const
1608 return TRUE;
1612 BOOL SelectionType::ReferencesType(const TypeBase & type)
1614 return baseType->ReferencesType(type);
1618 /////////////////////////////////////////////////////////
1620 BooleanType::BooleanType()
1621 : TypeBase(Tag::UniversalBoolean)
1626 void BooleanType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1628 hdr << " " << actualType.GetIdentifier() << " & operator=(BOOL v)";
1629 if (Module->UsingInlines())
1630 hdr << " { SetValue(v); return *this; }\n";
1631 else {
1632 hdr << ";\n";
1633 cxx << actualType.GetTemplatePrefix()
1634 << actualType.GetIdentifier() << " & "
1635 << actualType.GetClassNameString() << "::operator=(BOOL v)\n"
1636 "{\n"
1637 " SetValue(v);\n"
1638 " return *this;\n"
1639 "}\n"
1640 "\n"
1641 "\n";
1646 const char * BooleanType::GetAncestorClass() const
1648 return "PASN_Boolean";
1652 /////////////////////////////////////////////////////////
1654 IntegerType::IntegerType()
1655 : TypeBase(Tag::UniversalInteger)
1660 IntegerType::IntegerType(NamedNumberList * lst)
1661 : TypeBase(Tag::UniversalInteger),
1662 allowedValues(*lst)
1664 delete lst;
1668 void IntegerType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1670 hdr << " " << actualType.GetIdentifier() << " & operator=(int v)";
1671 if (Module->UsingInlines())
1672 hdr << " { SetValue(v); return *this; }\n";
1673 else {
1674 hdr << ";\n";
1675 cxx << actualType.GetTemplatePrefix()
1676 << actualType.GetIdentifier() << " & "
1677 << actualType.GetClassNameString() << "::operator=(int v)\n"
1678 "{\n"
1679 " SetValue(v);\n"
1680 " return *this;\n"
1681 "}\n"
1682 "\n"
1683 "\n";
1686 hdr << " " << actualType.GetIdentifier() << " & operator=(unsigned v)";
1687 if (Module->UsingInlines())
1688 hdr << " { SetValue(v); return *this; }\n";
1689 else {
1690 hdr << ";\n";
1691 cxx << actualType.GetTemplatePrefix()
1692 << actualType.GetIdentifier() << " & "
1693 << actualType.GetClassNameString() << "::operator=(unsigned v)\n"
1694 "{\n"
1695 " SetValue(v);\n"
1696 " return *this;\n"
1697 "}\n"
1698 "\n"
1699 "\n";
1704 const char * IntegerType::GetAncestorClass() const
1706 return "PASN_Integer";
1710 /////////////////////////////////////////////////////////
1712 EnumeratedType::EnumeratedType(NamedNumberList * enums, BOOL extend, NamedNumberList * ext)
1713 : TypeBase(Tag::UniversalEnumeration),
1714 enumerations(*enums)
1716 numEnums = enums->GetSize();
1717 delete enums;
1718 extendable = extend;
1719 if (ext != NULL) {
1720 ext->DisallowDeleteObjects();
1721 for (PINDEX i = 0; i < ext->GetSize(); i++)
1722 enumerations.Append(ext->GetAt(i));
1723 delete ext;
1728 void EnumeratedType::PrintOn(ostream & strm) const
1730 PrintStart(strm);
1731 strm << '\n';
1732 PINDEX i;
1733 for (i = 0; i < numEnums; i++)
1734 strm << indent() << enumerations[i] << '\n';
1735 if (extendable) {
1736 strm << "...\n";
1737 for (; i < enumerations.GetSize(); i++)
1738 strm << indent() << enumerations[i] << '\n';
1740 PrintFinish(strm);
1744 TypeBase * EnumeratedType::FlattenThisType(const TypeBase & parent)
1746 return new DefinedType(this, parent);
1750 void EnumeratedType::GenerateCplusplus(ostream & hdr, ostream & cxx)
1752 PINDEX i;
1753 PArgList & args = PProcess::Current().GetArguments();
1754 BOOL xml_output = args.HasOption('x');
1756 BeginGenerateCplusplus(hdr, cxx);
1758 int maxEnumValue = 0;
1759 for (i = 0; i < enumerations.GetSize(); i++) {
1760 int num = enumerations[i].GetNumber();
1761 if (maxEnumValue < num)
1762 maxEnumValue = num;
1765 // Generate enumerations and complete the constructor implementation
1766 hdr << " enum Enumerations {\n";
1767 cxx << ", " << maxEnumValue << ", " << (extendable ? "TRUE" : "FALSE") << "\n"
1768 "#ifndef PASN_NOPRINTON\n"
1769 " , \"";
1771 int prevNum = -1;
1772 for (i = 0; i < enumerations.GetSize(); i++) {
1773 if (i > 0) {
1774 hdr << ",\n";
1775 cxx << " \"";
1778 hdr << " e_" << MakeIdentifierC(enumerations[i].GetName());
1779 cxx << enumerations[i].GetName();
1781 int num = enumerations[i].GetNumber();
1782 if (num != prevNum+1) {
1783 hdr << " = " << num;
1784 cxx << '=' << num;
1786 prevNum = num;
1788 cxx << " \"\n";
1791 hdr << "\n"
1792 " };\n"
1793 "\n";
1794 cxx << "#endif\n"
1795 " )\n"
1796 "{\n";
1797 GenerateCplusplusConstraints(PString(), hdr, cxx);
1799 if (xml_output)
1801 hdr << " BOOL DecodeXER(PXER_Stream & strm);\n"
1802 " void EncodeXER(PXER_Stream & strm) const;\n";
1804 cxx << "}\n"
1805 "\n"
1806 << GetTemplatePrefix()
1807 << "BOOL " << GetClassNameString() << "::DecodeXER(PXER_Stream & strm)\n"
1808 "{\n"
1809 " PXMLElement * elem = strm.GetCurrentElement();\n"
1810 " PXMLObject * sub_elem = elem->GetElement();\n"
1811 "\n"
1812 " if (!elem || !elem->IsElement())\n"
1813 " return FALSE;\n"
1814 "\n"
1815 " PCaselessString id = ((PXMLElement *)sub_elem)->GetName();\n"
1816 "\n"
1817 " ";
1819 for (i = 0 ; i < enumerations.GetSize() ; i++) {
1820 cxx << " if (id == \"" << enumerations[i].GetName() << "\") {\n"
1821 " value = " << enumerations[i].GetNumber() << ";\n"
1822 " return TRUE;\n"
1823 " }\n"
1824 " else";
1827 cxx << "\n"
1828 " return FALSE;\n"
1829 "}\n"
1830 "\n";
1832 cxx << GetTemplatePrefix()
1833 << "void " << GetClassNameString() << "::EncodeXER(PXER_Stream & strm) const\n"
1834 "{\n"
1835 " PXMLElement * elem = strm.GetCurrentElement();\n"
1836 " PString id;\n"
1837 "\n"
1838 " switch(value)\n"
1839 " {\n";
1841 for (i = 0 ; i < enumerations.GetSize() ; i++) {
1842 cxx << " case " << enumerations[i].GetNumber() << ":\n"
1843 " elem->AddChild(new PXMLElement(elem, \"" << enumerations[i].GetName() << "\"));\n"
1844 " break;\n";
1847 cxx << " default:\n"
1848 " break;\n"
1849 " }\n";
1852 EndGenerateCplusplus(hdr, cxx);
1856 void EnumeratedType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1858 hdr << " " << actualType.GetIdentifier() << " & operator=(unsigned v)";
1859 if (Module->UsingInlines())
1860 hdr << " { SetValue(v); return *this; }\n";
1861 else {
1862 hdr << ";\n";
1863 cxx << actualType.GetTemplatePrefix()
1864 << actualType.GetIdentifier() << " & "
1865 << actualType.GetClassNameString() << "::operator=(unsigned v)\n"
1866 "{\n"
1867 " SetValue(v);\n"
1868 " return *this;\n"
1869 "}\n"
1870 "\n"
1871 "\n";
1876 const char * EnumeratedType::GetAncestorClass() const
1878 return "PASN_Enumeration";
1882 /////////////////////////////////////////////////////////
1884 RealType::RealType()
1885 : TypeBase(Tag::UniversalReal)
1890 const char * RealType::GetAncestorClass() const
1892 return "PASN_Real";
1896 /////////////////////////////////////////////////////////
1898 BitStringType::BitStringType()
1899 : TypeBase(Tag::UniversalBitString)
1904 BitStringType::BitStringType(NamedNumberList * lst)
1905 : TypeBase(Tag::UniversalBitString),
1906 allowedBits(*lst)
1908 delete lst;
1911 int BitStringType::GetIdentifierTokenContext() const
1913 return OID_IDENTIFIER;
1917 int BitStringType::GetBraceTokenContext() const
1919 return BITSTRING_BRACE;
1923 const char * BitStringType::GetAncestorClass() const
1925 return "PASN_BitString";
1929 /////////////////////////////////////////////////////////
1931 OctetStringType::OctetStringType()
1932 : TypeBase(Tag::UniversalOctetString)
1937 void OctetStringType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
1939 static const char * const types[] = {
1940 "char *", "PString &", "PBYTEArray &"
1943 PINDEX i;
1944 for (i = 0; i < PARRAYSIZE(types); i++) {
1945 hdr << " " << actualType.GetIdentifier() << "(const " << types[i] << " v)";
1946 if (Module->UsingInlines())
1947 hdr << " { SetValue(v); }\n";
1948 else {
1949 hdr << ";\n";
1950 cxx << actualType.GetTemplatePrefix()
1951 << actualType.GetIdentifier() << "::" << actualType.GetIdentifier() << "(const " << types[i] << " v)\n"
1952 "{\n"
1953 " SetValue(v);\n"
1954 "}\n"
1955 "\n"
1956 "\n";
1960 hdr << '\n';
1962 for (i = 0; i < PARRAYSIZE(types); i++) {
1963 hdr << " " << actualType.GetIdentifier() << " & operator=(const " << types[i] << " v)";
1964 if (Module->UsingInlines())
1965 hdr << " { SetValue(v); return *this; }\n";
1966 else {
1967 hdr << ";\n";
1968 cxx << actualType.GetTemplatePrefix()
1969 << actualType.GetIdentifier() << " & "
1970 << actualType.GetClassNameString() << "::operator=(const " << types[i] << " v)\n"
1971 "{\n"
1972 " SetValue(v);\n"
1973 " return *this;\n"
1974 "}\n"
1975 "\n"
1976 "\n";
1982 const char * OctetStringType::GetAncestorClass() const
1984 return "PASN_OctetString";
1988 /////////////////////////////////////////////////////////
1990 NullType::NullType()
1991 : TypeBase(Tag::UniversalNull)
1996 const char * NullType::GetAncestorClass() const
1998 return "PASN_Null";
2002 /////////////////////////////////////////////////////////
2004 SequenceType::SequenceType(TypesList * stnd,
2005 BOOL extend,
2006 TypesList * ext,
2007 unsigned tagNum)
2008 : TypeBase(tagNum)
2010 if (stnd != NULL) {
2011 numFields = stnd->GetSize();
2012 fields = *stnd;
2013 delete stnd;
2015 else
2016 numFields = 0;
2017 extendable = extend;
2018 if (ext != NULL) {
2019 ext->DisallowDeleteObjects();
2020 for (PINDEX i = 0; i < ext->GetSize(); i++)
2021 fields.Append(ext->GetAt(i));
2022 delete ext;
2027 void SequenceType::PrintOn(ostream & strm) const
2029 PrintStart(strm);
2030 strm << '\n';
2031 PINDEX i;
2032 for (i = 0; i < numFields; i++)
2033 strm << fields[i];
2034 if (extendable) {
2035 strm << indent() << "...\n";
2036 for (; i < fields.GetSize(); i++)
2037 strm << fields[i];
2039 PrintFinish(strm);
2043 void SequenceType::FlattenUsedTypes()
2045 for (PINDEX i = 0; i < fields.GetSize(); i++)
2046 fields.SetAt(i, fields[i].FlattenThisType(*this));
2050 TypeBase * SequenceType::FlattenThisType(const TypeBase & parent)
2052 return new DefinedType(this, parent);
2056 BOOL SequenceType::IsPrimitiveType() const
2058 return FALSE;
2062 void SequenceType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2064 PArgList & args = PProcess::Current().GetArguments();
2065 BOOL xml_output = args.HasOption('x');
2067 PINDEX i;
2069 BeginGenerateCplusplus(hdr, cxx);
2071 PINDEX baseOptions = 0;
2072 for (i = 0; i < fields.GetSize(); i++) {
2073 if (i < numFields && fields[i].IsOptional())
2074 baseOptions++;
2077 // Complete ancestor constructor parameters
2078 cxx << ", " << baseOptions << ", "
2079 << (extendable ? "TRUE" : "FALSE") << ", "
2080 << fields.GetSize() - numFields
2081 << ')';
2083 // Output enum for optional parameters
2084 BOOL outputEnum = FALSE;
2085 for (i = 0; i < fields.GetSize(); i++) {
2086 if (i >= numFields || fields[i].IsOptional()) {
2087 if (outputEnum)
2088 hdr << ",\n";
2089 else {
2090 hdr << " enum OptionalFields {\n";
2091 outputEnum = TRUE;
2093 hdr << " e_" << fields[i].GetIdentifier();
2097 if (outputEnum)
2098 hdr << "\n"
2099 " };\n"
2100 "\n";
2102 // Output the declarations and constructors for member variables
2103 for (i = 0; i < fields.GetSize(); i++) {
2104 PString varname = "m_" + fields[i].GetIdentifier();
2105 hdr << " " << fields[i].GetTypeName() << ' ' << varname << ";\n";
2106 if (fields[i].HasNonStandardTag()) {
2107 cxx << ",\n"
2108 " " << varname;
2109 fields[i].GenerateCplusplusConstructor(hdr, cxx);
2113 // Output declarations for generated functions
2114 hdr << "\n"
2115 " PINDEX GetDataLength() const;\n"
2116 " BOOL Decode(PASN_Stream & strm);\n"
2117 " void Encode(PASN_Stream & strm) const;\n"
2118 "#ifndef PASN_NOPRINTON\n"
2119 " void PrintOn(ostream & strm) const;\n"
2120 "#endif\n";
2122 if (xml_output)
2124 hdr << " BOOL PreambleDecodeXER(PXER_Stream & strm);\n";
2126 if (fields.GetSize())
2127 hdr << " void PreambleEncodeXER(PXER_Stream &) const;\n";
2131 if (numFields > 0)
2132 hdr << " Comparison Compare(const PObject & obj) const;\n";
2134 cxx << "\n"
2135 "{\n";
2136 GenerateCplusplusConstraints(PString(), hdr, cxx);
2137 for (i = 0; i < fields.GetSize(); i++) {
2138 PString ident = fields[i].GetIdentifier();
2139 fields[i].GenerateCplusplusConstraints("m_" + ident + ".", hdr, cxx);
2140 if (i >= numFields && !fields[i].IsOptional())
2141 cxx << " IncludeOptionalField(e_" << ident << ");\n";
2143 cxx << "}\n"
2144 "\n"
2145 "\n"
2146 "#ifndef PASN_NOPRINTON\n"
2147 << GetTemplatePrefix()
2148 << "void " << GetClassNameString() << "::PrintOn(ostream & strm) const\n"
2149 "{\n"
2150 " int indent = strm.precision() + 2;\n"
2151 " strm << \"{\\n\";\n";
2153 for (i = 0; i < fields.GetSize(); i++) {
2154 PString id = fields[i].GetIdentifier();
2155 if (i >= numFields || fields[i].IsOptional())
2156 cxx << " if (HasOptionalField(e_" << id << "))\n"
2157 " ";
2158 cxx << " strm << setw(indent+" << id.GetLength()+3 << ") << \""
2159 << id << " = \" << setprecision(indent) << m_" << id << " << '\\n';\n";
2162 cxx << " strm << setw(indent-1) << \"}\";\n"
2163 "}\n"
2164 "#endif\n"
2165 "\n"
2166 "\n";
2168 if (xml_output)
2170 cxx << GetTemplatePrefix()
2171 << "BOOL " << GetClassNameString() << "::PreambleDecodeXER(PXER_Stream & strm)\n"
2172 "{\n";
2174 if (fields.GetSize())
2176 cxx << " PXMLElement * elem = strm.GetCurrentElement();\n"
2177 " PXMLElement * sub_elem;\n"
2178 " BOOL result;\n"
2179 "\n";
2181 for (i = 0; i < fields.GetSize(); i++)
2183 PString id = fields[i].GetIdentifier();
2184 cxx << " if ((sub_elem = (PXMLElement *)elem->GetElement(\"" << id << "\")) && sub_elem->IsElement())\n"
2185 " {\n";
2187 if (i >= numFields || fields[i].IsOptional())
2188 cxx << " IncludeOptionalField(e_" << id << ");\n";
2190 cxx << " strm.SetCurrentElement(sub_elem);\n"
2191 " result = m_" << id << ".Decode(strm);\n"
2192 " strm.SetCurrentElement(sub_elem);\n"
2193 " if (!result)\n"
2194 " return FALSE;\n"
2195 " }\n"
2196 "\n";
2200 cxx << " return TRUE;\n"
2201 "}\n"
2202 "\n";
2204 if (fields.GetSize())
2206 cxx << GetTemplatePrefix()
2207 << "void " << GetClassNameString() << "::PreambleEncodeXER(PXER_Stream & strm) const\n"
2208 "{\n";
2210 cxx << " PXMLElement * elem = strm.GetCurrentElement();\n"
2211 " PXMLElement * sub_elem;\n"
2212 "\n";
2214 for (i = 0; i < fields.GetSize(); i++)
2216 PString id = fields[i].GetIdentifier();
2218 if (i >= numFields || fields[i].IsOptional())
2219 cxx << " if (HasOptionalField(e_" << id << "))\n"
2220 " {\n";
2222 cxx << " sub_elem = elem->AddChild(new PXMLElement(elem, \"" << id << "\"));\n"
2223 " strm.SetCurrentElement(sub_elem);\n"
2224 " m_" << id << ".Encode(strm);\n";
2226 if (i >= numFields || fields[i].IsOptional())
2227 cxx << " }\n";
2229 cxx << "\n";
2232 cxx << " strm.SetCurrentElement(elem);\n"
2233 "}\n"
2234 "\n";
2238 if (numFields > 0) {
2239 cxx << GetTemplatePrefix()
2240 << "PObject::Comparison " << GetClassNameString() << "::Compare(const PObject & obj) const\n"
2241 "{\n"
2242 "#ifndef PASN_LEANANDMEAN\n"
2243 " PAssert(PIsDescendant(this, " << GetClassNameString() << "), PInvalidCast);\n"
2244 "#endif\n"
2245 " const " << GetClassNameString() << " & other = (const " << GetClassNameString() << " &)obj;\n"
2246 "\n"
2247 " Comparison result;\n"
2248 "\n";
2250 for (i = 0; i < numFields; i++) {
2251 PString identifier = fields[i].GetIdentifier();
2252 cxx << " if ((result = m_" << identifier << ".Compare(other.m_" << identifier << ")) != EqualTo)\n"
2253 " return result;\n";
2256 cxx << "\n"
2257 " return PASN_Sequence::Compare(other);\n"
2258 "}\n"
2259 "\n"
2260 "\n";
2263 cxx << GetTemplatePrefix()
2264 << "PINDEX " << GetClassNameString() << "::GetDataLength() const\n"
2265 "{\n"
2266 " PINDEX length = 0;\n";
2268 for (i = 0; i < numFields; i++) {
2269 if (fields[i].IsOptional())
2270 cxx << " if (HasOptionalField(e_" << fields[i].GetIdentifier() << "))\n ";
2271 cxx << " length += m_" << fields[i].GetIdentifier() << ".GetObjectLength();\n";
2274 cxx << " return length;\n"
2275 "}\n"
2276 "\n"
2277 "\n"
2278 << GetTemplatePrefix()
2279 << "BOOL " << GetClassNameString() << "::Decode(PASN_Stream & strm)\n"
2280 "{\n"
2281 " if (!PreambleDecode(strm))\n"
2282 " return FALSE;\n\n";
2284 if (xml_output)
2286 cxx << " if (PIsDescendant(&strm, PXER_Stream))\n"
2287 " return TRUE;\n\n";
2290 for (i = 0; i < numFields; i++) {
2291 cxx << " if (";
2292 if (fields[i].IsOptional())
2293 cxx << "HasOptionalField(e_" << fields[i].GetIdentifier() << ") && ";
2294 cxx << "!m_" << fields[i].GetIdentifier() << ".Decode(strm))\n"
2295 " return FALSE;\n";
2298 for (; i < fields.GetSize(); i++)
2299 cxx << " if (!KnownExtensionDecode(strm, e_"
2300 << fields[i].GetIdentifier()
2301 << ", m_" << fields[i].GetIdentifier() << "))\n"
2302 " return FALSE;\n";
2304 cxx << "\n"
2305 " return UnknownExtensionsDecode(strm);\n"
2306 "}\n"
2307 "\n"
2308 "\n"
2309 << GetTemplatePrefix()
2310 << "void " << GetClassNameString() << "::Encode(PASN_Stream & strm) const\n"
2311 "{\n"
2312 " PreambleEncode(strm);\n\n";
2314 if (xml_output)
2316 cxx << " if (PIsDescendant(&strm, PXER_Stream))\n"
2317 " return;\n\n";
2320 for (i = 0; i < numFields; i++) {
2321 if (fields[i].IsOptional())
2322 cxx << " if (HasOptionalField(e_" << fields[i].GetIdentifier() << "))\n"
2323 " ";
2324 cxx << " m_" << fields[i].GetIdentifier() << ".Encode(strm);\n";
2327 for (; i < fields.GetSize(); i++)
2328 cxx << " KnownExtensionEncode(strm, e_"
2329 << fields[i].GetIdentifier()
2330 << ", m_" << fields[i].GetIdentifier() << ");\n";
2332 cxx << "\n"
2333 " UnknownExtensionsEncode(strm);\n";
2335 EndGenerateCplusplus(hdr, cxx);
2339 const char * SequenceType::GetAncestorClass() const
2341 return "PASN_Sequence";
2345 BOOL SequenceType::CanReferenceType() const
2347 return TRUE;
2351 BOOL SequenceType::ReferencesType(const TypeBase & type)
2353 for (PINDEX i = 0; i < fields.GetSize(); i++)
2354 if (fields[i].ReferencesType(type))
2355 return TRUE;
2356 return FALSE;
2360 /////////////////////////////////////////////////////////
2362 SequenceOfType::SequenceOfType(TypeBase * base, Constraint * constraint, unsigned tag)
2363 : TypeBase(tag)
2365 baseType = base;
2366 if (constraint != NULL)
2367 AddConstraint(constraint);
2371 SequenceOfType::~SequenceOfType()
2373 delete baseType;
2377 void SequenceOfType::PrintOn(ostream & strm) const
2379 PrintStart(strm);
2380 if (baseType == NULL)
2381 strm << "!!Null Type!!\n";
2382 else
2383 strm << *baseType << '\n';
2384 PrintFinish(strm);
2388 void SequenceOfType::FlattenUsedTypes()
2390 baseType = baseType->FlattenThisType(*this);
2394 TypeBase * SequenceOfType::FlattenThisType(const TypeBase & parent)
2396 if (!baseType->IsPrimitiveType() || baseType->HasConstraints())
2397 return new DefinedType(this, parent);
2399 // Search for an existing sequence of type
2400 PString seqName = "ArrayOf_" + baseType->GetTypeName();
2402 TypeBase * existingType = Module->FindType(seqName);
2403 if (existingType != NULL)
2404 return new DefinedType(this, existingType);
2406 return new DefinedType(this, seqName);
2410 BOOL SequenceOfType::IsPrimitiveType() const
2412 return FALSE;
2416 void SequenceOfType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2418 BeginGenerateCplusplus(hdr, cxx);
2419 cxx << ")\n"
2420 "{\n";
2421 GenerateCplusplusConstraints(PString(), hdr, cxx);
2422 cxx << "}\n"
2423 "\n"
2424 "\n";
2426 PString baseTypeName = baseType->GetTypeName();
2428 // Generate declarations for generated functions
2429 hdr << " PASN_Object * CreateObject() const;\n"
2430 " " << baseTypeName << " & operator[](PINDEX i) const";
2431 if (Module->UsingInlines())
2432 hdr << " { return (" << baseTypeName << " &)array[i]; }\n";
2433 else
2434 hdr << ";\n";
2436 // Generate implementation for functions
2437 cxx << GetTemplatePrefix()
2438 << "PASN_Object * " << GetClassNameString() << "::CreateObject() const\n"
2439 "{\n";
2441 if (baseType->HasConstraints()) {
2442 cxx << " " << baseTypeName << " * obj = new " << baseTypeName << ";\n";
2443 baseType->GenerateCplusplusConstraints("obj->", hdr, cxx);
2444 cxx << " return obj;\n";
2446 else
2447 cxx << " return new " << baseTypeName << ";\n";
2449 if (!Module->UsingInlines())
2450 cxx << "}\n"
2451 "\n"
2452 "\n"
2453 << GetTemplatePrefix()
2454 << baseTypeName << " & " << GetClassNameString() << "::operator[](PINDEX i) const\n"
2455 "{\n"
2456 " return (" << baseTypeName << " &)array[i];\n";
2458 EndGenerateCplusplus(hdr, cxx);
2462 void SequenceOfType::GenerateForwardDecls(ostream & hdr)
2464 if (baseType->IsParameterizedType())
2465 return;
2467 PString baseTypeName = baseType->GetTypeName();
2469 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2470 typesOutput += GetIdentifier();
2472 if (!typesOutput.Contains(baseTypeName))
2473 hdr << "class " << baseTypeName << ";\n\n";
2477 const char * SequenceOfType::GetAncestorClass() const
2479 return "PASN_Array";
2483 BOOL SequenceOfType::CanReferenceType() const
2485 return TRUE;
2489 BOOL SequenceOfType::ReferencesType(const TypeBase & type)
2491 return baseType->ReferencesType(type) && baseType->IsParameterizedType();
2495 /////////////////////////////////////////////////////////
2497 SetType::SetType()
2498 : SequenceType(NULL, FALSE, NULL, Tag::UniversalSet)
2503 SetType::SetType(SequenceType * seq)
2504 : SequenceType(*seq)
2506 tag.number = Tag::UniversalSet;
2510 const char * SetType::GetAncestorClass() const
2512 return "PASN_Set";
2516 /////////////////////////////////////////////////////////
2518 SetOfType::SetOfType(TypeBase * base, Constraint * constraint)
2519 : SequenceOfType(base, constraint, Tag::UniversalSet)
2524 /////////////////////////////////////////////////////////
2526 ChoiceType::ChoiceType(TypesList * stnd,
2527 BOOL extendable,
2528 TypesList * extensions)
2529 : SequenceType(stnd, extendable, extensions, Tag::IllegalUniversalTag)
2534 void ChoiceType::GenerateCplusplus(ostream & hdr, ostream & cxx)
2536 PINDEX i;
2539 BeginGenerateCplusplus(hdr, cxx);
2541 // Complete the ancestor constructor parameters
2542 cxx << ", " << numFields << ", " << (extendable ? "TRUE" : "FALSE");
2544 // Generate the enum's for each choice discriminator, and include strings for
2545 // PrintOn() debug output into acncestor constructor
2546 BOOL outputEnum = FALSE;
2547 int prevNum = -1;
2548 for (i = 0; i < fields.GetSize(); i++) {
2549 const Tag & fieldTag = fields[i].GetTag();
2550 if (fieldTag.mode == Tag::Automatic || !fields[i].IsChoice()) {
2551 if (outputEnum) {
2552 hdr << ",\n";
2553 cxx << " \"";
2555 else {
2556 hdr << " enum Choices {\n";
2557 cxx << "\n"
2558 "#ifndef PASN_NOPRINTON\n"
2559 " , \"";
2560 outputEnum = TRUE;
2563 hdr << " e_" << fields[i].GetIdentifier();
2564 cxx << fields[i].GetIdentifier();
2566 if (fieldTag.mode != Tag::Automatic && fieldTag.number != (unsigned)(prevNum+1)) {
2567 hdr << " = " << fieldTag.number;
2568 cxx << '=' << fieldTag.number;
2570 prevNum = fieldTag.number;
2571 cxx << " \"\n";
2575 if (outputEnum) {
2576 hdr << "\n"
2577 " };\n"
2578 "\n";
2579 cxx << "#endif\n"
2580 " ";
2583 cxx << ")\n"
2584 "{\n";
2585 GenerateCplusplusConstraints(PString(), hdr, cxx);
2586 cxx << "}\n"
2587 "\n"
2588 "\n";
2590 // Generate code for type safe cast operators of selected choice object
2591 BOOL needExtraLine = FALSE;
2593 if (Module->UsingOperators()) {
2594 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2595 typesOutput += GetIdentifier();
2597 for (i = 0; i < fields.GetSize(); i++) {
2598 PString type = fields[i].GetTypeName();
2599 if (!typesOutput.Contains(type)) {
2600 if (Module->UsingInlines()) {
2601 hdr << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2602 " operator " << type << " &() const { return *(" << type << " *)choice; }\n"
2603 "#else\n"
2604 " operator " << type << " &() { return *(" << type << " *)choice; }\n"
2605 " operator const " << type << " &() const { return *(const " << type << " *)choice; }\n"
2606 "#endif\n";
2608 else {
2609 hdr << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2610 " operator " << type << " &() const;\n"
2611 "#else\n"
2612 " operator " << type << " &();\n"
2613 " operator const " << type << " &() const;\n"
2614 "#endif\n";
2615 cxx << "#if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9\n"
2616 << GetTemplatePrefix()
2617 << GetClassNameString() << "::operator " << type << " &() const\n"
2618 "#else\n"
2619 << GetTemplatePrefix()
2620 << GetClassNameString() << "::operator " << type << " &()\n"
2621 "{\n"
2622 "#ifndef PASN_LEANANDMEAN\n"
2623 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2624 "#endif\n"
2625 " return *(" << type << " *)choice;\n"
2626 "}\n"
2627 "\n"
2628 "\n"
2629 << GetTemplatePrefix()
2630 << GetClassNameString() << "::operator const " << type << " &() const\n"
2631 "#endif\n"
2632 "{\n"
2633 "#ifndef PASN_LEANANDMEAN\n"
2634 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2635 "#endif\n"
2636 " return *(" << type << " *)choice;\n"
2637 "}\n"
2638 "\n"
2639 "\n";
2641 typesOutput += type;
2642 needExtraLine = TRUE;
2646 else {
2647 for (i = 0; i < fields.GetSize(); i++) {
2648 PString type = fields[i].GetTypeName();
2649 PString fieldName = fields[i].GetIdentifier();
2650 if (Module->UsingInlines()) {
2651 hdr << " " << type << " & m_" << fieldName << "() { return *(" << type << " *)choice; }\n"
2652 " const " << type << " & m_" << fieldName << "() const { return *(const " << type << " *)choice; }\n";
2654 else {
2655 hdr << " " << type << " & m_" << fieldName << "();\n"
2656 " const " << type << " & m_" << fieldName << "() const;\n";
2657 cxx << GetTemplatePrefix() << type << " & "
2658 << GetClassNameString() << "::m_" << fieldName << "()\n"
2659 "{\n"
2660 "#ifndef PASN_LEANANDMEAN\n"
2661 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2662 "#endif\n"
2663 " return *(" << type << " *)choice;\n"
2664 "}\n"
2665 "\n"
2666 "\n"
2667 << GetTemplatePrefix() << type << " const & "
2668 << GetClassNameString() << "::m_" << fieldName << "() const\n"
2669 "{\n"
2670 "#ifndef PASN_LEANANDMEAN\n"
2671 " PAssert(PIsDescendant(PAssertNULL(choice), " << type << "), PInvalidCast);\n"
2672 "#endif\n"
2673 " return *(" << type << " *)choice;\n"
2674 "}\n"
2675 "\n"
2676 "\n";
2679 needExtraLine = TRUE;
2682 if (needExtraLine)
2683 hdr << '\n';
2686 // Generate virtual function to create chosen object based on discriminator
2687 hdr << " BOOL CreateObject();\n";
2688 cxx << GetTemplatePrefix()
2689 << "BOOL " << GetClassNameString() << "::CreateObject()\n"
2690 "{\n";
2692 // special case: if choice is all NULLs then simply output code
2693 BOOL allNull = TRUE;
2694 for (i = 0; allNull && i < fields.GetSize(); i++)
2695 allNull = allNull && strcmp(fields[i].GetAncestorClass(), "PASN_Null") == 0;
2697 if (allNull) {
2698 cxx << " choice = (tag <= e_" << fields[fields.GetSize()-1].GetIdentifier() << ") ? new PASN_Null() : NULL;\n"
2699 << " return choice != NULL;\n";
2702 else {
2703 // declare an array of flags indicating whether the tag has been output or not
2704 PBYTEArray flags(fields.GetSize());
2705 for (i = 0; i < fields.GetSize(); i++)
2706 flags[i] = 0;
2708 // keep
2709 outputEnum = FALSE;
2710 for (i = 0; i < fields.GetSize(); i++) {
2712 if (fields[i].GetTag().mode == Tag::Automatic || !fields[i].IsChoice()) {
2714 // ignore this tag if output previously
2715 if (flags[i] != 0)
2716 continue;
2718 if (!outputEnum) {
2719 cxx << " switch (tag) {\n";
2720 outputEnum = TRUE;
2723 // if the field has constraints, then output it alone
2724 // otherwise, look for all fields with the same type
2725 PString name = fields[i].GetTypeName();
2726 if (fields[i].HasConstraints()) {
2727 cxx << " case e_" << fields[i].GetIdentifier() << " :\n";
2728 flags[i] = 1;
2729 } else {
2730 PINDEX j;
2731 for (j = i; j < fields.GetSize(); j++) {
2732 if (fields[j].GetTypeName() == name) {
2733 cxx << " case e_" << fields[j].GetIdentifier() << " :\n";
2734 flags[j] = 1;
2739 cxx << " choice = new " << name;
2740 fields[i].GenerateCplusplusConstructor(hdr, cxx);
2741 cxx << ";\n";
2742 fields[i].GenerateCplusplusConstraints(" choice->", hdr, cxx);
2743 cxx << " return TRUE;\n";
2747 if (outputEnum)
2748 cxx << " }\n"
2749 "\n";
2751 for (i = 0; i < fields.GetSize(); i++) {
2752 if (fields[i].GetTag().mode != Tag::Automatic && fields[i].IsChoice())
2753 cxx << " choice = new " << fields[i].GetTypeName() << "(tag, tagClass);\n"
2754 " if (((PASN_Choice*)choice)->CreateObject())\n"
2755 " return TRUE;\n"
2756 " delete choice;\n"
2757 "\n";
2760 cxx << " choice = NULL;\n"
2761 " return FALSE;\n";
2764 EndGenerateCplusplus(hdr, cxx);
2768 void ChoiceType::GenerateForwardDecls(ostream & hdr)
2770 // Output forward declarations for choice pointers, but not standard classes
2771 BOOL needExtraLine = FALSE;
2773 PStringSet typesOutput(PARRAYSIZE(StandardClasses), StandardClasses);
2774 typesOutput += GetIdentifier();
2776 PStringSet forwards;
2778 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2779 PString type = fields[i].GetTypeName();
2780 if (!fields[i].IsParameterizedType() &&
2781 !typesOutput.Contains(type) &&
2782 !forwards.Contains(type)) {
2783 hdr << "class " << type << ";\n";
2784 needExtraLine = TRUE;
2785 forwards.Include(type);
2789 if (needExtraLine)
2790 hdr << '\n';
2794 BOOL ChoiceType::IsPrimitiveType() const
2796 return FALSE;
2800 BOOL ChoiceType::IsChoice() const
2802 return TRUE;
2806 const char * ChoiceType::GetAncestorClass() const
2808 return "PASN_Choice";
2812 BOOL ChoiceType::ReferencesType(const TypeBase & type)
2814 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2815 if (fields[i].ReferencesType(type) && fields[i].IsParameterizedType())
2816 return TRUE;
2818 return FALSE;
2822 /////////////////////////////////////////////////////////
2824 EmbeddedPDVType::EmbeddedPDVType()
2825 : TypeBase(Tag::UniversalEmbeddedPDV)
2830 const char * EmbeddedPDVType::GetAncestorClass() const
2832 return "PASN_OctetString";
2836 /////////////////////////////////////////////////////////
2838 ExternalType::ExternalType()
2839 : TypeBase(Tag::UniversalExternalType)
2844 const char * ExternalType::GetAncestorClass() const
2846 return "PASN_OctetString";
2850 /////////////////////////////////////////////////////////
2852 AnyType::AnyType(PString * ident)
2853 : TypeBase(Tag::UniversalExternalType)
2855 if (ident != NULL) {
2856 identifier = *ident;
2857 delete ident;
2862 void AnyType::PrintOn(ostream & strm) const
2864 PrintStart(strm);
2865 if (!identifier)
2866 strm << "Defined by " << identifier;
2867 PrintFinish(strm);
2871 const char * AnyType::GetAncestorClass() const
2873 return "PASN_OctetString";
2877 /////////////////////////////////////////////////////////
2879 StringTypeBase::StringTypeBase(int tag)
2880 : TypeBase(tag)
2885 int StringTypeBase::GetBraceTokenContext() const
2887 return STRING_BRACE;
2891 static void GenerateOperator(const char * rhsType, ostream & hdr, ostream & cxx, const TypeBase & actualType)
2893 hdr << " " << actualType.GetIdentifier() << " & operator=(const " << rhsType << " v)";
2894 if (Module->UsingInlines())
2895 hdr << " { SetValue(v); return *this; }\n";
2896 else {
2897 hdr << ";\n";
2898 cxx << actualType.GetTemplatePrefix()
2899 << actualType.GetIdentifier() << " & "
2900 << actualType.GetClassNameString() << "::operator=(const " << rhsType << " v)\n"
2901 "{\n"
2902 " SetValue(v);\n"
2903 " return *this;\n"
2904 "}\n"
2905 "\n"
2906 "\n";
2911 void StringTypeBase::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
2913 GenerateOperator("char *", hdr, cxx, actualType);
2914 GenerateOperator("PString &", hdr, cxx, actualType);
2918 /////////////////////////////////////////////////////////
2920 BMPStringType::BMPStringType()
2921 : StringTypeBase(Tag::UniversalBMPString)
2926 const char * BMPStringType::GetAncestorClass() const
2928 return "PASN_BMPString";
2932 void BMPStringType::GenerateOperators(ostream & hdr, ostream & cxx, const TypeBase & actualType)
2934 StringTypeBase::GenerateOperators(hdr, cxx, actualType);
2935 GenerateOperator("PWORDArray &", hdr, cxx, actualType);
2936 GenerateOperator("PASN_BMPString &", hdr, cxx, actualType);
2940 /////////////////////////////////////////////////////////
2942 GeneralStringType::GeneralStringType()
2943 : StringTypeBase(Tag::UniversalGeneralString)
2948 const char * GeneralStringType::GetAncestorClass() const
2950 return "PASN_GeneralString";
2954 /////////////////////////////////////////////////////////
2956 GraphicStringType::GraphicStringType()
2957 : StringTypeBase(Tag::UniversalGraphicString)
2962 const char * GraphicStringType::GetAncestorClass() const
2964 return "PASN_GraphicString";
2968 /////////////////////////////////////////////////////////
2970 IA5StringType::IA5StringType()
2971 : StringTypeBase(Tag::UniversalIA5String)
2976 const char * IA5StringType::GetAncestorClass() const
2978 return "PASN_IA5String";
2982 /////////////////////////////////////////////////////////
2984 ISO646StringType::ISO646StringType()
2985 : StringTypeBase(Tag::UniversalVisibleString)
2990 const char * ISO646StringType::GetAncestorClass() const
2992 return "PASN_ISO646String";
2996 /////////////////////////////////////////////////////////
2998 NumericStringType::NumericStringType()
2999 : StringTypeBase(Tag::UniversalNumericString)
3004 const char * NumericStringType::GetAncestorClass() const
3006 return "PASN_NumericString";
3010 /////////////////////////////////////////////////////////
3012 PrintableStringType::PrintableStringType()
3013 : StringTypeBase(Tag::UniversalPrintableString)
3018 const char * PrintableStringType::GetAncestorClass() const
3020 return "PASN_PrintableString";
3024 /////////////////////////////////////////////////////////
3026 TeletexStringType::TeletexStringType()
3027 : StringTypeBase(Tag::UniversalTeletexString)
3032 const char * TeletexStringType::GetAncestorClass() const
3034 return "PASN_TeletexString";
3038 /////////////////////////////////////////////////////////
3040 T61StringType::T61StringType()
3041 : StringTypeBase(Tag::UniversalTeletexString)
3046 const char * T61StringType::GetAncestorClass() const
3048 return "PASN_T61String";
3052 /////////////////////////////////////////////////////////
3054 UniversalStringType::UniversalStringType()
3055 : StringTypeBase(Tag::UniversalUniversalString)
3060 const char * UniversalStringType::GetAncestorClass() const
3062 return "PASN_UniversalString";
3066 /////////////////////////////////////////////////////////
3068 VideotexStringType::VideotexStringType()
3069 : StringTypeBase(Tag::UniversalVideotexString)
3074 const char * VideotexStringType::GetAncestorClass() const
3076 return "PASN_VideotexString";
3080 /////////////////////////////////////////////////////////
3082 VisibleStringType::VisibleStringType()
3083 : StringTypeBase(Tag::UniversalVisibleString)
3088 const char * VisibleStringType::GetAncestorClass() const
3090 return "PASN_VisibleString";
3094 /////////////////////////////////////////////////////////
3096 UnrestrictedCharacterStringType::UnrestrictedCharacterStringType()
3097 : StringTypeBase(Tag::UniversalUniversalString)
3102 const char * UnrestrictedCharacterStringType::GetAncestorClass() const
3104 return "PASN_UnrestrictedString";
3108 /////////////////////////////////////////////////////////
3110 GeneralizedTimeType::GeneralizedTimeType()
3111 : TypeBase(Tag::UniversalGeneralisedTime)
3116 const char * GeneralizedTimeType::GetAncestorClass() const
3118 return "PASN_GeneralisedTime";
3122 /////////////////////////////////////////////////////////
3124 UTCTimeType::UTCTimeType()
3125 : TypeBase(Tag::UniversalUTCTime)
3130 const char * UTCTimeType::GetAncestorClass() const
3132 return "PASN_UniversalTime";
3136 /////////////////////////////////////////////////////////
3138 ObjectDescriptorType::ObjectDescriptorType()
3139 : TypeBase(Tag::UniversalObjectDescriptor)
3144 const char * ObjectDescriptorType::GetAncestorClass() const
3146 return "PASN_ObectDescriptor";
3150 /////////////////////////////////////////////////////////
3152 ObjectIdentifierType::ObjectIdentifierType()
3153 : TypeBase(Tag::UniversalObjectId)
3158 int ObjectIdentifierType::GetIdentifierTokenContext() const
3160 return OID_IDENTIFIER;
3164 int ObjectIdentifierType::GetBraceTokenContext() const
3166 return OID_BRACE;
3170 const char * ObjectIdentifierType::GetAncestorClass() const
3172 return "PASN_ObjectId";
3176 /////////////////////////////////////////////////////////
3178 ObjectClassFieldType::ObjectClassFieldType(PString * objclass, PString * field)
3179 : TypeBase(Tag::IllegalUniversalTag),
3180 asnObjectClassName(*objclass),
3181 asnObjectClassField(*field)
3183 delete objclass;
3184 delete field;
3188 const char * ObjectClassFieldType::GetAncestorClass() const
3190 return "PASN_OctetString";
3194 void ObjectClassFieldType::PrintOn(ostream & strm) const
3196 PrintStart(strm);
3197 strm << asnObjectClassName << '.' << asnObjectClassField;
3198 PrintFinish(strm);
3202 TypeBase * ObjectClassFieldType::FlattenThisType(const TypeBase & parent)
3204 return new DefinedType(this, parent);
3208 BOOL ObjectClassFieldType::IsPrimitiveType() const
3210 return FALSE;
3214 void ObjectClassFieldType::GenerateCplusplus(ostream & hdr, ostream & cxx)
3216 BeginGenerateCplusplus(hdr, cxx);
3218 hdr << " BOOL DecodeSubType(";
3219 GenerateCplusplusConstraints(PString(), hdr, cxx);
3220 hdr << " & obj) { return PASN_OctetString::DecodeSubType(obj); }\n"
3221 " void EncodeSubType(const ";
3222 GenerateCplusplusConstraints(PString(), hdr, cxx);
3223 hdr << " & obj) { PASN_OctetString::EncodeSubType(obj); } \n"
3224 "\n";
3226 cxx << ")\n"
3227 "{\n";
3229 EndGenerateCplusplus(hdr, cxx);
3233 BOOL ObjectClassFieldType::CanReferenceType() const
3235 return TRUE;
3239 BOOL ObjectClassFieldType::ReferencesType(const TypeBase & type)
3241 for (PINDEX i = 0; i < constraints.GetSize(); i++) {
3242 if (constraints[i].ReferencesType(type))
3243 return TRUE;
3245 return FALSE;
3249 /////////////////////////////////////////////////////////
3251 ImportedType::ImportedType(PString * theName, BOOL param)
3252 : TypeBase(Tag::IllegalUniversalTag)
3254 identifier = name = *theName;
3255 delete theName;
3257 parameterised = param;
3261 const char * ImportedType::GetAncestorClass() const
3263 return identifier;
3267 void ImportedType::AdjustIdentifier()
3269 identifier = modulePrefix + '_' + MakeIdentifierC(name);
3273 void ImportedType::GenerateCplusplus(ostream &, ostream &)
3278 void ImportedType::SetImportPrefix(const PString & prefix)
3280 modulePrefix = prefix;
3284 BOOL ImportedType::IsParameterisedImport() const
3286 return parameterised;
3290 /////////////////////////////////////////////////////////
3292 SearchType::SearchType(const PString & theName)
3293 : TypeBase(Tag::IllegalUniversalTag)
3295 identifier = name = theName;
3299 const char * SearchType::GetAncestorClass() const
3301 return identifier;
3305 /////////////////////////////////////////////////////////
3307 void ValueBase::SetValueName(PString * name)
3309 valueName = *name;
3310 delete name;
3314 void ValueBase::PrintBase(ostream & strm) const
3316 if (!valueName)
3317 strm << '\n' << indent() << valueName << '=';
3321 void ValueBase::GenerateCplusplus(ostream &, ostream &)
3323 PError << StdError(Warning) << "unsupported value type." << endl;
3327 /////////////////////////////////////////////////////////
3329 DefinedValue::DefinedValue(PString * name)
3330 : referenceName(*name)
3332 delete name;
3333 actualValue = NULL;
3334 unresolved = TRUE;
3338 void DefinedValue::PrintOn(ostream & strm) const
3340 PrintBase(strm);
3341 strm << referenceName;
3345 void DefinedValue::GenerateCplusplus(ostream & hdr, ostream & cxx)
3347 if (unresolved) {
3348 unresolved = FALSE;
3350 const ValuesList & values = Module->GetValues();
3351 for (PINDEX i = 0; i < values.GetSize(); i++) {
3352 if (values[i].GetName() == referenceName) {
3353 actualValue = &values[i];
3354 break;
3359 if (actualValue != NULL)
3360 actualValue->GenerateCplusplus(hdr, cxx);
3361 else
3362 cxx << "e_" << referenceName;
3366 /////////////////////////////////////////////////////////
3368 BooleanValue::BooleanValue(BOOL newVal)
3370 value = newVal;
3374 void BooleanValue::PrintOn(ostream & strm) const
3376 PrintBase(strm);
3377 strm << (value ? "TRUE" : "FALSE");
3381 void BooleanValue::GenerateCplusplus(ostream &, ostream & cxx)
3383 cxx << (value ? "TRUE" : "FALSE");
3387 /////////////////////////////////////////////////////////
3389 IntegerValue::IntegerValue(PInt64 newVal)
3391 value = newVal;
3395 void IntegerValue::PrintOn(ostream & strm) const
3397 PrintBase(strm);
3399 strm << value;
3403 void IntegerValue::GenerateCplusplus(ostream &, ostream & cxx)
3405 cxx << value;
3406 if (value > INT_MAX)
3407 cxx << 'U';
3411 /////////////////////////////////////////////////////////
3413 RealValue::RealValue(double newVal)
3415 value = newVal;
3419 /////////////////////////////////////////////////////////
3421 OctetStringValue::OctetStringValue(PString * newVal)
3423 // value = *newVal;
3424 delete newVal;
3428 /////////////////////////////////////////////////////////
3430 BitStringValue::BitStringValue(PString * newVal)
3432 // value = *newVal;
3433 delete newVal;
3437 BitStringValue::BitStringValue(PStringList * newVal)
3439 // value = *newVal;
3440 delete newVal;
3444 /////////////////////////////////////////////////////////
3446 CharacterValue::CharacterValue(BYTE c)
3448 value = c;
3452 CharacterValue::CharacterValue(BYTE t1, BYTE t2)
3454 value = (t1<<8) + t2;
3458 CharacterValue::CharacterValue(BYTE q1, BYTE q2, BYTE q3, BYTE q4)
3460 value = (q1<<24) + (q2<<16) + (q3<<8) + q4;
3464 void CharacterValue::PrintOn(ostream & strm) const
3466 strm << "'\\x" << hex << value << '\'';
3470 void CharacterValue::GenerateCplusplus(ostream &, ostream & cxx)
3472 cxx << value;
3476 /////////////////////////////////////////////////////////
3478 CharacterStringValue::CharacterStringValue(PString * newVal)
3480 value = *newVal;
3481 delete newVal;
3485 CharacterStringValue::CharacterStringValue(PStringList * newVal)
3487 for (PINDEX i = 0; i < newVal->GetSize(); i++)
3488 value += (*newVal)[i];
3489 delete newVal;
3493 void CharacterStringValue::PrintOn(ostream & strm) const
3495 strm << value;
3499 void CharacterStringValue::GenerateCplusplus(ostream &, ostream & cxx)
3501 cxx << value;
3505 /////////////////////////////////////////////////////////
3507 ObjectIdentifierValue::ObjectIdentifierValue(PString * newVal)
3509 value.Append(newVal);
3513 ObjectIdentifierValue::ObjectIdentifierValue(PStringList * newVal)
3515 value = *newVal;
3516 delete newVal;
3520 void ObjectIdentifierValue::PrintOn(ostream & strm) const
3522 PrintBase(strm);
3523 if (value.IsEmpty())
3524 strm << "empty object identifier";
3525 else {
3526 strm << value[0];
3527 for (PINDEX i = 1; i < value.GetSize(); i++)
3528 strm << '.' << value[i];
3530 strm << '\n';
3534 /////////////////////////////////////////////////////////
3536 void MinValue::PrintOn(ostream & strm) const
3538 strm << "MIN";
3542 void MinValue::GenerateCplusplus(ostream &, ostream & cxx)
3544 cxx << "MinimumValue";
3548 /////////////////////////////////////////////////////////
3550 void MaxValue::PrintOn(ostream & strm) const
3552 strm << "MAX";
3556 void MaxValue::GenerateCplusplus(ostream &, ostream & cxx)
3558 cxx << "MaximumValue";
3562 /////////////////////////////////////////////////////////
3564 SequenceValue::SequenceValue(ValuesList * list)
3566 if (list != NULL) {
3567 values = *list;
3568 delete list;
3573 void SequenceValue::PrintOn(ostream & strm) const
3575 strm << "{ ";
3576 for (PINDEX i = 0; i < values.GetSize(); i++) {
3577 if (i > 0)
3578 strm << ", ";
3579 strm << values[i];
3581 strm << " }";
3585 /////////////////////////////////////////////////////////
3587 MibBase::MibBase(PString * nam,
3588 PString * descr,
3589 PString * refer,
3590 ValueBase * val)
3591 : name(*nam)
3593 delete nam;
3594 if (descr != NULL) {
3595 description = *descr;
3596 delete descr;
3598 if (refer != NULL) {
3599 reference = *refer;
3600 delete refer;
3602 value = val;
3606 MibBase::~MibBase()
3608 delete value;
3612 /////////////////////////////////////////////////////////
3614 MibObject::MibObject(PString * nam,
3615 TypeBase * typ,
3616 Access acc,
3617 Status stat,
3618 PString * descr,
3619 PString * refer,
3620 PStringList * idx,
3621 ValueBase * defVal,
3622 ValueBase * setVal)
3623 : MibBase(nam, descr, refer, setVal)
3625 type = typ;
3626 access = acc;
3627 status = stat;
3628 if (idx != NULL) {
3629 index = *idx;
3630 delete idx;
3632 defaultValue = defVal;
3636 MibObject::~MibObject()
3638 delete type;
3639 delete defaultValue;
3643 void MibObject::PrintOn(ostream & strm) const
3645 strm << " Object: " << name << "\n " << *type
3646 << " " << description << "\n"
3647 " " << *value << '\n';
3651 /////////////////////////////////////////////////////////
3653 MibTrap::MibTrap(PString * nam, ValueBase * ent, ValuesList * var,
3654 PString * descr, PString * refer, ValueBase * val)
3655 : MibBase(nam, descr, refer, val)
3657 enterprise = ent;
3658 if (var != NULL) {
3659 variables = *var;
3660 delete var;
3665 MibTrap::~MibTrap()
3667 delete enterprise;
3671 void MibTrap::PrintOn(ostream & strm) const
3673 strm << " Trap: " << name << "\n " << *enterprise
3674 << " " << description << "\n"
3675 " " << *value << '\n';
3679 /////////////////////////////////////////////////////////
3681 ImportModule::ImportModule(PString * name, TypesList * syms)
3682 : fullModuleName(*name),
3683 shortModuleName(Module->GetImportModuleName(*name)),
3684 filename(shortModuleName.ToLower())
3686 delete name;
3687 symbols = *syms;
3688 delete syms;
3690 PStringArray renameArgs = shortModuleName.Tokenise(',');
3691 switch (renameArgs.GetSize())
3693 case 3 :
3694 filename = renameArgs[2];
3695 case 2 :
3696 directoryPrefix = renameArgs[1];
3697 shortModuleName = renameArgs[0];
3700 for (PINDEX i = 0; i < symbols.GetSize(); i++) {
3701 symbols[i].SetImportPrefix(shortModuleName);
3702 Module->AppendType(&symbols[i]);
3707 void ImportModule::PrintOn(ostream & strm) const
3709 strm << " " << fullModuleName << " (" << shortModuleName << "):\n";
3710 for (PINDEX i = 0; i < symbols.GetSize(); i++)
3711 strm << " " << symbols[i];
3712 strm << '\n';
3716 void ImportModule::GenerateCplusplus(ostream & hdr, ostream & cxx)
3718 hdr << "#include \"" << directoryPrefix << filename << ".h\"\n";
3720 for (PINDEX i = 0; i < symbols.GetSize(); i++) {
3721 if (symbols[i].IsParameterisedImport()) {
3722 cxx << "#include \"" << filename << "_t.cxx\"\n";
3723 break;
3729 /////////////////////////////////////////////////////////
3731 ModuleDefinition::ModuleDefinition(PString * name, PStringList * id, Tag::Mode defTagMode)
3732 : moduleName(*name),
3733 definitiveId(*id)
3735 delete name;
3736 delete id;
3737 defaultTagMode = defTagMode;
3738 exportAll = FALSE;
3739 indentLevel = 1;
3741 PArgList & args = PProcess::Current().GetArguments();
3742 if (args.HasOption('r')) {
3743 PStringArray renames = args.GetOptionString('r').Lines();
3744 for (PINDEX i = 0; i < renames.GetSize(); i++) {
3745 PINDEX equal = renames[i].Find('=');
3746 if (equal > 0 && equal != P_MAX_INDEX)
3747 importNames.SetAt(renames[i].Left(equal).Trim(), renames[i].Mid(equal+1).Trim());
3753 void ModuleDefinition::SetExportAll()
3755 exportAll = TRUE;
3759 void ModuleDefinition::SetExports(TypesList * syms)
3761 exports = *syms;
3762 delete syms;
3766 void ModuleDefinition::PrintOn(ostream & strm) const
3768 strm << moduleName << "\n"
3769 "Default Tags: " << Tag::modeNames[defaultTagMode] << "\n"
3770 "Exports:";
3771 if (exportAll)
3772 strm << " ALL";
3773 else {
3774 strm << "\n ";
3775 for (PINDEX i = 0; i < exports.GetSize(); i++)
3776 strm << exports[i] << ' ';
3777 strm << '\n';
3779 strm << "Imports:\n" << imports << "\n"
3780 "Types:\n" << types << "\n"
3781 "Values:\n" << values << "\n"
3782 "MIBs:\n" << mibs << endl;
3786 void ModuleDefinition::AppendType(TypeBase * type)
3788 types.Append(type);
3789 sortedTypes.Append(type);
3793 TypeBase * ModuleDefinition::FindType(const PString & name)
3795 PINDEX pos = sortedTypes.GetValuesIndex(SearchType(name));
3796 if (pos != P_MAX_INDEX)
3797 return &sortedTypes[pos];
3798 return NULL;
3802 PString ModuleDefinition::GetImportModuleName(const PString & moduleName)
3804 if (importNames.Contains(moduleName))
3805 return importNames[moduleName];
3807 PINDEX pos = moduleName.Find('-');
3808 if (pos > 32)
3809 pos = 32;
3810 return moduleName.Left(pos);
3814 void ModuleDefinition::GenerateCplusplus(const PFilePath & path,
3815 const PString & modName,
3816 const PString & headerPrefix,
3817 unsigned numFiles,
3818 BOOL useNamespaces,
3819 BOOL useInlines,
3820 BOOL useOperators,
3821 BOOL verbose)
3823 PArgList & args = PProcess::Current().GetArguments();
3824 BOOL xml_output = args.HasOption('x');
3825 PINDEX i;
3827 usingInlines = useInlines;
3828 usingOperators = useOperators;
3830 // Adjust the module name to what is specified to a default
3831 if (!modName)
3832 moduleName = modName;
3833 else
3834 moduleName = MakeIdentifierC(moduleName);
3836 // Set the prefix on all external class names
3837 if (!useNamespaces)
3838 classNamePrefix = moduleName + '_';
3841 if (verbose)
3842 cout << "Sorting " << types.GetSize() << " types..." << endl;
3845 // Create sorted list for faster searching.
3846 sortedTypes.DisallowDeleteObjects();
3847 for (i = 0; i < types.GetSize(); i++)
3848 sortedTypes.Append(&types[i]);
3850 // Flatten types by generating types for "inline" definitions
3851 for (i = 0; i < types.GetSize(); i++)
3852 types[i].FlattenUsedTypes();
3854 // Reorder types
3855 // Determine if we need a separate file for template closure
3856 BOOL hasTemplates = FALSE;
3857 types.DisallowDeleteObjects();
3858 PINDEX loopDetect = 0;
3859 PINDEX bubble = 0;
3860 while (bubble < types.GetSize()) {
3861 BOOL makesReference = FALSE;
3863 TypeBase & bubbleType = types[bubble];
3864 if (bubbleType.CanReferenceType()) {
3865 for (i = bubble; i < types.GetSize(); i++) {
3866 if (bubbleType.ReferencesType(types[i])) {
3867 makesReference = TRUE;
3868 break;
3873 if (makesReference) {
3874 types.Append(types.RemoveAt(bubble));
3875 if (loopDetect > types.GetSize()) {
3876 PError << StdError(Fatal)
3877 << "Recursive type definition: " << bubbleType.GetName() << endl;
3878 break;
3880 loopDetect++;
3882 else {
3883 loopDetect = bubble;
3884 bubble++;
3887 if (bubbleType.HasParameters())
3888 hasTemplates = TRUE;
3890 types.AllowDeleteObjects();
3892 // Adjust all of the C++ identifiers prepending module name
3893 for (i = 0; i < types.GetSize(); i++)
3894 types[i].AdjustIdentifier();
3897 // Generate the code
3898 if (verbose)
3899 cout << "Generating code (" << types.GetSize() << " classes) ..." << endl;
3902 // Output the special template closure file, if necessary
3903 PString templateFilename;
3904 if (hasTemplates) {
3905 OutputFile templateFile;
3906 if (!templateFile.Open(path, "_t", ".cxx"))
3907 return;
3909 for (i = 0; i < types.GetSize(); i++) {
3910 if (types[i].HasParameters()) {
3911 PStringStream dummy;
3912 types[i].GenerateCplusplus(dummy, templateFile);
3916 if (verbose)
3917 cout << "Completed " << templateFile.GetFilePath() << endl;
3919 templateFilename = templateFile.GetFilePath().GetFileName();
3922 // Start the header file
3923 OutputFile hdrFile;
3924 if (!hdrFile.Open(path, "", ".h"))
3925 return;
3927 hdrFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3929 hdrFile << "#ifndef __" << moduleName.ToUpper() << "_H\n"
3930 "#define __" << moduleName.ToUpper() << "_H\n"
3931 "\n"
3932 "#ifdef P_USE_PRAGMA\n"
3933 "#pragma interface\n"
3934 "#endif\n"
3935 "\n";
3937 if (xml_output)
3938 hdrFile << "#define P_EXPAT 1\n"
3939 "#include <ptclib/pxml.h>\n";
3941 hdrFile << "#include <ptclib/asner.h>\n"
3942 "\n";
3944 // Start the first (and maybe only) cxx file
3945 OutputFile cxxFile;
3946 if (!cxxFile.Open(path, numFiles > 1 ? "_1" : "", ".cxx"))
3947 return;
3949 PString headerName = hdrFile.GetFilePath().GetFileName();
3951 cxxFile << "#ifdef P_USE_PRAGMA\n"
3952 "#pragma implementation \"" << headerName << "\"\n"
3953 "#endif\n"
3954 "\n"
3955 "#include <ptlib.h>\n"
3956 "#include \"" << headerPrefix << headerName << "\"\n"
3957 "\n"
3958 "#define new PNEW\n"
3959 "\n"
3960 "\n";
3962 cxxFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
3964 // Include the template closure file.
3965 if (hasTemplates)
3966 cxxFile << "#include \"" << templateFilename << "\"\n\n";
3969 for (i = 0; i < imports.GetSize(); i++)
3970 imports[i].GenerateCplusplus(hdrFile, cxxFile);
3971 if (!imports.IsEmpty()) {
3972 hdrFile << "\n\n";
3973 cxxFile << "\n\n";
3977 if (useNamespaces) {
3978 hdrFile << "namespace " << moduleName << " {\n"
3979 "\n";
3980 cxxFile << "using namespace " << moduleName << ";\n"
3981 "\n";
3985 PINDEX classesPerFile = (types.GetSize()+numFiles-1)/numFiles;
3986 for (i = 0; i < types.GetSize(); i++) {
3987 if (i > 0 && i%classesPerFile == 0) {
3989 cxxFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
3990 "\n";
3992 cxxFile.Close();
3994 if (verbose)
3995 cout << "Completed " << cxxFile.GetFilePath() << endl;
3997 if (!cxxFile.Open(path, psprintf("_%u", i/classesPerFile+1), ".cxx"))
3998 return;
4000 cxxFile << "#include <ptlib.h>\n"
4001 "#include \"" << headerPrefix << headerName << "\"\n"
4002 "\n";
4004 if (useNamespaces)
4005 cxxFile << "using namespace " << moduleName << ";\n"
4006 "\n";
4007 cxxFile << "#define new PNEW\n"
4008 "\n"
4009 "\n";
4011 cxxFile << "#if ! H323_DISABLE_" << moduleName.ToUpper() << "\n\n";
4015 if (types[i].HasParameters()) {
4016 PStringStream dummy;
4017 types[i].GenerateCplusplus(hdrFile, dummy);
4019 else
4020 types[i].GenerateCplusplus(hdrFile, cxxFile);
4024 // Close off the files
4025 if (useNamespaces)
4026 hdrFile << "};\n"
4027 "\n";
4029 hdrFile << "#endif // __" << moduleName.ToUpper() << "_H\n"
4030 "\n";
4032 hdrFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
4033 "\n";
4035 cxxFile << "#endif // if ! H323_DISABLE_" << moduleName.ToUpper() << "\n"
4036 "\n";
4038 if (verbose)
4039 cout << "Completed " << cxxFile.GetFilePath() << endl;
4043 //////////////////////////////////////////////////////////////////////////////