2 * compiler/core/snacc.c---Compiles ASN.1 src files into an internal type tree.
3 * Imported type/value references are resolved if possible.
4 * Produces C or C++ encoder/decoder/print/free code and .h for
5 * data struct and prototypes.
6 * Generated C can be either ANSI or old style via macros.
7 * Produces values for OBJECT IDENTIFIERs, INTEGERs and BOOLEANs
13 * See the README file for compiling tips. This should compile
14 * with ANSI or non-ANSI c compilers.
16 * each ASN.1 source file must contain a complete ASN.1 module:
17 * <ModName> DEFINITIONS ::= BEGIN ... END
19 * 91/09/04---modified to handle new data struct (ASN.1 generated)
20 * for module info. MS.
23 * Copyright (C) 1991, 1992 Michael Sample
24 * and the University of British Columbia
26 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
31 * This program and the associated libraries are distributed in the hope
32 * that they will be useful, but WITHOUT ANY WARRANTY; without even the
33 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
34 * PURPOSE. See the GNU General Public License and GNU Library General
35 * Public License for more details.
39 * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/compiler/core/snacc.c,v 1.1 2001/06/20 21:27:59 dmitch Exp $
41 * Revision 1.1 2001/06/20 21:27:59 dmitch
42 * Adding missing snacc compiler files.
44 * Revision 1.1.1.1 1999/03/16 18:06:52 aram
45 * Originals from SMIME Free Library.
47 * Revision 1.10 1997/05/07 15:18:35 wan
48 * Added (limited) size constraints, bitstring and enumeration names to tables
50 * Revision 1.9 1997/02/16 15:12:21 rj
51 * made ``return *this after calling abort()'' a compile time option.
53 * Revision 1.8 1997/01/02 08:50:55 rj
54 * - use the TIME_WITH_SYS_TIME flag (checked and generated by configure)
55 * - do not silently ignore the -tcl option if not compiled for tcl code generation
57 * Revision 1.7 1995/09/07 19:13:39 rj
58 * new options -mA and -mC for snacc(1) that switch the names used between those defined in the ASN.1 files and those used in the generated C++ code.
59 * uses newly introduced enum MetaNameStyle.
61 * Revision 1.6 1995/08/17 15:00:13 rj
62 * the PDU flag belongs to the metacode, not only to the tcl interface. (type and variable named adjusted)
64 * Revision 1.5 1995/07/25 19:34:06 rj
65 * bug report address changed to protect an innocent's mailbox :-)
67 * snacc -h now prints the usage to stdout.
69 * allow for more than one PDU per .asn1 file set:
70 * - struct TclPDU becomes a linked list.
71 * - it gets a flag `used' to detect invalid command line arguments.
73 * code for idl backend added.
75 * by default, snacc now derives output file names from the .asn1 input file name instead of the module name.
77 * changed `_' to `-' in file names.
79 * Revision 1.4 1994/12/11 20:21:06 rj
80 * #include string(s).h
82 * Revision 1.3 1994/10/08 03:23:27 rj
83 * since i was still irritated by cpp standing for c++ and not the C preprocessor, i renamed them to cxx (which is one known suffix for C++ source files). since the standard #define is __cplusplus, cplusplus would have been the more obvious choice, but it is a little too long.
85 * code for meta structures added (provides information about the generated code itself).
87 * code for Tcl interface added (makes use of the above mentioned meta code).
89 * Revision 1.2 1994/09/01 00:44:31 rj
90 * snacc_config.h and other superfluous .h files removed. version string moved into a separate version.h file.
92 * Revision 1.1 1994/08/28 09:49:37 rj
93 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
98 /* Enables VDA's DER SUPPORT. If gVDADER_RULES == 1 then support is on,
99 * other wise it is off. Define _gVDADER_RULES so snacc.h does not
100 * redefine the global gVDADER_RULES with it's extern (avoids a compile
102 ** COMPILER EXECUTION FLAGS: "-D -C -u ../../../snaccVC/asn-useful.asn1
103 sm_vdatypes.asn sm_x501ud.asn sm_x411ub.asn sm_x411mtsas.asn
104 sm_x501if.asn sm_x520sa.asn sm_x509cmn.asn sm_x509af.asn
105 sm_x509ce.asn sm_cms.asn sm_ess.asn tst_email.asn
107 -D -C -u ../../../snaccVC/asn-useful.asn1 sm_vdatypes.asn sm_x501ud.asn sm_x411ub.asn sm_x411mtsas.asn sm_x501if.asn sm_x520sa.asn sm_x509cmn.asn sm_x509af.asn sm_x509ce.asn sm_cms.asn sm_ess.asn tst_email.asn tst_email2.asn
109 #define _gVDADER_RULES
115 #if TIME_WITH_SYS_TIME
116 # include <sys/time.h>
120 # include <sys/time.h>
126 #if STDC_HEADERS || HAVE_STRING_H
133 #include "asn-incl.h"
136 #include "asn1module.h"
138 #include "parser.h" /* for parser (ech!) globals */
139 #include "dependency.h"
140 #include "link-types.h"
141 #include "link-values.h"
144 #include "recursive.h"
146 #include "normalize.h"
147 #include "do-macros.h"
148 #include "snacc-util.h"
153 #include "str-util.h"
155 #include "c-gen/rules.h" /* for c file generation */
156 #include "c-gen/type-info.h"
157 #include "c-gen/gen-code.h"
159 #include "c++-gen/rules.h" /* for c++ file generation */
160 #include "c++-gen/types.h"
161 #include "c++-gen/gen-code.h"
163 #include "gen-tbls.h" /* for type table generation */
166 #include "idl-gen/rules.h"
167 #include "idl-gen/types.h"
168 #include "idl-gen/gen-code.h"
172 /* prototypes for this file's routines */
174 Module
*ParseAsn1File
PROTO ((char *fileName
));
176 void GenCCode
PROTO ((ModuleList
*allMods
, long int longJmpVal
, int genTypes
, int genEncoders
, int genDecoders
, int genPrinters
, int genValues
, int genFree
));
178 void GenCxxCode
PROTO ((ModuleList
*allMods
, long int longJmpVal
, int genTypes
, int genEncoders
, int genDecoders
, int genPrinters
, int genValues
, int genFree
, if_META (MetaNameStyle genMeta COMMA MetaPDU
*meta_pdus COMMA
) if_TCL (int genTcl COMMA
) int novolatilefuncs
));
180 void GenIDLCode
PROTO ((ModuleList
*allMods
, long int longJmpVal
, int genTypes
, int genPrinters
, int genValues
, int genFree
));
182 int ModNamesUnique
PROTO ((ModuleList
*m
));
184 Module
*usefulTypeModG
= NULL
;
185 static char versionG
[] = VERSION
;
186 static char releasedateG
[] = RELDATE
;
187 static char bugreportaddressG
[] = BUGREPADDR
;
188 int maxFileNameLenG
= -1; /* values > 2 are considered valid */
189 /* this is used in back_ends/c_gen/str_util.c */
192 Usage
PARAMS ((prgName
, fp
),
196 fprintf (fp
, "\nUsage: %s ", prgName
);
197 fprintf (fp
, "[-h] [-P] [-t] [-v] [-e] [-d] [-p] [-f]\n");
199 fprintf (fp
, " [-c | -C | -[T|O] <table output file> | -idl ]\n");
201 fprintf (fp
, " [-c | -C | -[T|O] <table output file>]\n");
203 fprintf (fp
, " [-u <useful types ASN.1 file>]\n");
204 fprintf (fp
, " [-mm] [-mf <max file name length>]\n");
205 fprintf (fp
, " [-l <neg number>]\n");
207 fprintf (fp
, " [-meta <type list>] [-mA | -mC]\n");
209 fprintf (fp
, " [-tcl <type list>]\n");
212 fprintf (fp
, " <ASN.1 file list>\n\n");
213 fprintf (fp
, " -h prints this msg\n");
214 fprintf (fp
, " -c generate C encoders and decoders (default)\n");
215 fprintf (fp
, " -C generate C++ encoders and decoders\n");
216 fprintf (fp
, " -novolat for broken C++ compilers: return *this after calling abort()\n");
217 fprintf (fp
, " -T <filename> write a type table file for the ASN.1 modules to file filename\n");
218 fprintf (fp
, " -O <filename> writes the type table file in the original (<1.3b2) format\n");
220 fprintf (fp
, " -idl generate CORBA IDL\n");
222 fprintf (fp
, " -u <filename> specifies the ASN.1 file with definition of the useful types\n");
223 fprintf (fp
, " (i.e. PrintableString). See the useful.asn1 file (in the\n");
224 fprintf (fp
, " snacc/asn1specs/ directory).\n");
225 fprintf (fp
, " -P print the parsed ASN.1 modules to stdout from their parse trees\n");
226 fprintf (fp
, " (helpful debugging)\n");
227 fprintf (fp
, " -t generate type definitions\n");
228 fprintf (fp
, " -v generate value definitions (limited)\n");
229 fprintf (fp
, " -e generate encode routines\n");
230 fprintf (fp
, " -d generate decode routines\n");
231 fprintf (fp
, " -p generate print routines\n");
232 fprintf (fp
, " -f generate hierarchical free routines (C only)\n");
233 fprintf (fp
, " note: if none of -t -v -e -d -p -f are given, all are generated.\n");
234 fprintf (fp
, " These do not affect type tables.\n");
237 fprintf (fp
, " -mm mangle output file name into module name (by default, the output file\n");
238 fprintf (fp
, " inherits the input file's name, with only the suffix replaced)\n");
239 fprintf (fp
, " -mf <num> num is maximum file name length for the generated source files\n");
241 fprintf (fp
, " -l <neg num> where to start error longjmp values decending from (obscure).\n");
244 fprintf (fp
, " -meta <type list> generate meta code that describes the generated types. Implies -C.\n");
245 fprintf (fp
, " -mA metacode: use names as defined in the ASN.1 files.\n");
246 fprintf (fp
, " -mC metacode: use names as used in the generated C++ files.\n");
248 fprintf (fp
, " -tcl <type list> generate code for a Tcl interpreter. Implies -meta.\n");
250 fprintf (fp
, " <type list> has the following syntax: <module>.<type>[,<module>.<type>[...]]\n");
251 fprintf (fp
, " the types listed are the top level PDUs.\n");
254 fprintf (fp
, "\nUse `-' as the ASN.1 source file name to parse stdin.\n\n");
257 fprintf (fp
, "This ASN.1 compiler produces C or C++ BER encoders and decoders or type tables.\n");
259 fprintf (fp
, "\nVersion %s, %s.\n", versionG
, releasedateG
);
261 fprintf (fp
, "Please send bug reports and comments to %s.\n\n", bugreportaddressG
);
263 fprintf (fp
, "Please see %s for new versions and where to send bug reports and comments.\n\n", bugreportaddressG
);
266 fprintf (fp
, "Copyright (C) 1993 Michael Sample and UBC\n");
267 fprintf (fp
, "Copyright (C) 1994, 1995 by Robert Joop and GMD FOKUS\n\n");
269 fprintf (fp
, "This program is free software; you can redistribute it and/or modify\n");
270 fprintf (fp
, "it under the terms of the GNU General Public License as published by\n");
271 fprintf (fp
, "the Free Software Foundation; either version 2 of the License, or\n");
272 fprintf (fp
, "(at your option) any later version.\n\n");
274 fprintf (fp
, "This program is distributed in the hope that it will be useful,\n");
275 fprintf (fp
, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
276 fprintf (fp
, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
277 fprintf (fp
, "GNU General Public License for more details.\n\n");
280 fprintf (fp, "You should have received a copy of the GNU General Public License\n");
281 fprintf (fp, "along with this program; if not, write to the Free Software\n");
282 fprintf (fp, "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n");
294 static MetaPDU
*parse_type_list (arg
)
297 MetaPDU
*meta_pdus
= NULL
;
299 for (module = strtok (arg
, ".:"); module; module = strtok (NULL
, ".:"))
301 MetaPDU
*pdu
= MT (MetaPDU
);
302 char *type
= strtok (NULL
, " /,;");
305 fprintf (stderr
, "usage: {-meta|-tcl} module.type[,module.type[...]]\n");
308 pdu
->module = module;
312 pdu
->next
= meta_pdus
;
319 int main
PARAMS ((argc
, argv
),
333 char *usefulTypeModFileName
;
335 int printModuleFlag
= FALSE
; /* default: Don't print */
336 int genTypeTbls
= 0; /* default: Don't gen tbls */
338 int genTypeCode
= FALSE
;
339 int genEncodeCode
= FALSE
;
340 int genDecodeCode
= FALSE
;
341 int genPrintCode
= FALSE
;
342 int genValueCode
= FALSE
;
343 int genFreeCode
= FALSE
;
345 MetaNameStyle genMetaCode
= META_off
;
346 MetaPDU
*meta_pdus
= NULL
;
348 int genTclCode
= FALSE
;
351 int genCCode
= FALSE
; /* defaults to C if neither specified */
352 int genCxxCode
= FALSE
;
354 int genIDLCode
= FALSE
;
356 long longJmpVal
= -100;
357 int novolatilefuncs
= FALSE
;
360 /* prints yacc debugging info to stdout */
367 Usage (argv
[0], stderr
);
371 srcList
= (SRC_FILE
*) Malloc ((argc
-1) * sizeof (SRC_FILE
));
375 * parse cmd line args
378 usefulTypeModFileName
= NULL
;
379 for (currArg
= 1; (currArg
< argc
); )
381 if ((argv
[currArg
][0] == '-') && (argv
[currArg
][1] != '\0'))
382 switch (argv
[currArg
][1])
391 Usage (argv
[0], stdout
);
396 printModuleFlag
= TRUE
;
407 if (!strcmp (argv
[currArg
]+1, "idl"))
418 if (!strcmp (argv
[currArg
]+1, "tcl"))
421 meta_pdus
= parse_type_list (argv
[++currArg
]);
424 genMetaCode
= META_backend_names
;
436 genEncodeCode
= TRUE
;
441 genDecodeCode
= TRUE
;
461 if (!strcmp (argv
[currArg
]+1, "novolat"))
463 novolatilefuncs
= TRUE
;
476 if (argv
[currArg
][2] != '\0') /* no space after -u */
478 usefulTypeModFileName
= &argv
[currArg
][2];
483 usefulTypeModFileName
= argv
[currArg
+1];
489 if (argv
[currArg
][2] != '\0') /* no space after -l */
491 longJmpVal
= atoi (&argv
[currArg
][2]);
496 longJmpVal
= atoi (argv
[currArg
+1]);
503 genTypeTbls
= argv
[currArg
][1]=='T'?2:1;
504 if (argv
[currArg
][2] != '\0') /* no space after -T */
506 tblFileName
= &argv
[currArg
][2];
511 tblFileName
= argv
[currArg
+1];
518 if (argv
[currArg
][2] == 'f')
520 if (argv
[currArg
][3] != '\0') /* no space after -mf */
522 maxFileNameLenG
= atoi (&argv
[currArg
][3]);
527 maxFileNameLenG
= atoi (argv
[currArg
+1]);
533 else if (!strcmp (argv
[currArg
]+1, "meta"))
535 meta_pdus
= parse_type_list (argv
[++currArg
]);
537 genMetaCode
= META_backend_names
;
542 else if (!strcmp (argv
[currArg
]+1, "mA"))
544 genMetaCode
= META_asn1_names
;
549 else if (!strcmp (argv
[currArg
]+1, "mC"))
551 genMetaCode
= META_backend_names
;
557 else if (argv
[currArg
][2] == 'm')
564 /* else fall through to default error */
568 fprintf (stderr
, "%s: ERROR---unknown cmd line option `%s'\n\n", argv
[0], argv
[currArg
]);
569 Usage (argv
[0], stderr
);
573 else /* asn1srcFileName */
574 srcList
[numSrcFiles
++].fileName
= argv
[currArg
++];
579 if (numSrcFiles
== 0)
581 fprintf (stderr
, "%s: ERROR---no ASN.1 source files were specified\n", argv
[0]);
582 Usage (argv
[0], stderr
);
588 * set default options
590 if (!(genTypeCode
|| genValueCode
|| genEncodeCode
|| genDecodeCode
||
591 genFreeCode
|| genPrintCode
))
595 genEncodeCode
= TRUE
;
596 genDecodeCode
= TRUE
;
601 else if (genCCode
+ genCxxCode
+ genTypeTbls
607 fprintf (stderr
, "%s: ERROR---Choose only one of the -c -C or -T options\n", argv
[0]);
608 Usage (argv
[0], stderr
);
612 if (!genCCode
&& !genCxxCode
&& !genTypeTbls
617 genCCode
= TRUE
; /* default to C if neither specified */
622 * parse 'useful' type module for linking purposes only (if given)
623 * the useful type encode, decode, print, free routines are
624 * already in the runtime library.
626 if (usefulTypeModFileName
!= NULL
)
628 usefulTypeModG
= ParseAsn1File (usefulTypeModFileName
);
630 if (usefulTypeModG
== NULL
)
635 fprintf (stderr
, " Hmmm, you didn't specify a useful types ASN.1 file with the `-u' option.\n");
636 fprintf (stderr
, " I'll continue assuming your ASN.1 file(s) don't need any useful types.\n");
641 * STEP 2---parse each ASN.1 src file
643 allMods
= (ModuleList
*)AsnListNew (sizeof (void*));
644 for (i
= 0; i
< numSrcFiles
; i
++)
646 currMod
= ParseAsn1File (srcList
[i
].fileName
);
652 * insert this module at the head of the list
653 * of already parsed (if any) modules
655 tmpModHndl
= (Module
**)AsnListAppend (allMods
);
656 *tmpModHndl
= currMod
;
658 } /* end per src file for loop */
662 * Check that the module names/oids are unique.
664 if (!ModNamesUnique (allMods
))
666 fprintf (stderr
, "Conflicting module names, cannot proceed.\n");
674 * Now that all files have been parsed,
675 * link local and locatable import type refs
677 if (LinkTypeRefs (allMods
) < 0)
679 fprintf (stderr
, "Type linking errors---cannot proceed\n");
687 * Parse constructed values now that types are all parsed
688 * and have been linked. Need type info to be able to
689 * parse values easily (elimitate ambiguity).
691 FOR_EACH_LIST_ELMT (currMod
, allMods
)
693 if (ParseValues (allMods
, currMod
) != 0)
694 fprintf (stderr
, "WARNING: Value parsing error (s), attempting to continue\n");
700 * Value parsing may have defined some new values
701 * so can link local and locatable import value refs now.
703 if (LinkValueRefs (allMods
) < 0)
705 fprintf (stderr
, "Value linking errors---cannot proceed\n");
714 * - adding type/value defs as nec
715 * - mark type defs with ANY DEFINED BY id if nec
716 * so they are put in the id to ANY type hash tbl.
719 FOR_EACH_LIST_ELMT (currMod
, allMods
)
721 ProcessMacros (currMod
);
722 if (currMod
->status
== MOD_ERROR
)
730 * convert silly type constructs into
731 * a normal format, leaving behind pure type/value info
732 * eg: expand COMPONENTS OF refs, SELECTION types.
733 * boil down values into simplest rep. (eg OID -> ENC_OID)
736 FOR_EACH_LIST_ELMT (currMod
, allMods
)
738 NormalizeModule (currMod
);
739 if (currMod
->status
== MOD_ERROR
)
748 * Mark recusive types. Currently the recursive information is
749 * not used elsewhere.
751 FOR_EACH_LIST_ELMT (currMod
, allMods
)
753 MarkRecursiveTypes (currMod
);
759 * Check for errors in the ASN.1 modules.
760 * Check all modules and exit if errors were found
763 if (usefulTypeModG
!= NULL
)
765 ErrChkModule (usefulTypeModG
);
766 if (usefulTypeModG
->status
== MOD_ERROR
)
770 FOR_EACH_LIST_ELMT (currMod
, allMods
)
772 ErrChkModule (currMod
);
773 if (currMod
->status
== MOD_ERROR
)
785 * exit if any sundry errors occurred at any point.
786 * smallErrG is set upon finding small errors that prevent code
787 * production but should not affect the other processing/error
788 * checking steps. This allows full display of errors.
793 * for debugging show "parsed" version of ASN.1 module if
794 * the print flag is set.
795 * Dumps each module to stdout. Printed from Module data struct
796 * print here before exiting otherwise print after sorting
800 FOR_EACH_LIST_ELMT (currMod
, allMods
)
803 PrintModule (stdout
, currMod
);
812 * Make C/C++ typenames/routine names for enc/decode.
813 * Type/Value renaming will occur if name conflicts
814 * arise between modules.
816 * NOTE: this is done before sorting the types because
817 * the type sorting routine may use the 'isPtr'
818 * information to help order knots of recursive types.
821 FillCTypeInfo (&cRulesG
, allMods
);
824 FillCxxTypeInfo (&cxxRulesG
, allMods
);
828 FillIDLTypeInfo (&idlRulesG
, allMods
);
834 * Sort each typedef list such that independent types are
835 * before the types that depend on them
837 * modules remain in same order as given on command line
838 * (cmd line file order should be
839 * least dependent module-> most dependent module
840 * so that include file order in generated src is correct)
841 * (useful.asn1 is always considered 'first' if given)
843 SortAllDependencies (allMods
);
846 * for debugging show "parsed" version of ASN.1 module.
847 * dumps each module to stdout. Printed from Module data struct
848 * Shows the results of normalization and sorting.
852 FOR_EACH_LIST_ELMT (currMod
, allMods
)
855 PrintModule (stdout
, currMod
);
861 * Final Step: Code/Type Table generation
864 GenCCode (allMods
, longJmpVal
, genTypeCode
, genValueCode
, genEncodeCode
, genDecodeCode
, genPrintCode
, genFreeCode
);
867 GenCxxCode (allMods
, longJmpVal
, genTypeCode
, genValueCode
, genEncodeCode
, genDecodeCode
, genPrintCode
, genFreeCode
, if_META (genMetaCode COMMA meta_pdus COMMA
) if_TCL (genTclCode COMMA
) novolatilefuncs
);
869 else if (genTypeTbls
)
870 GenTypeTbls (allMods
, tblFileName
, genTypeTbls
);
874 GenIDLCode (allMods
, longJmpVal
, genTypeCode
, genValueCode
, genPrintCode
, genFreeCode
);
877 return 0; /* keep make happy */
884 * Calls the yacc/lex parser given a the ASN.1 src file's filename.
885 * Returns a Module *for the given ASN.1 module. If the filename is
889 ParseAsn1File
PARAMS ((fileName
),
897 * Open input file for lexical analyzer/parser
898 * Use stdin if the filename is "-"
900 if (strcmp (fileName
, "-") == 0)
903 fprintf (stderr
, "ERROR---asn1 src file `%s' cannot be processed without output filename mangling\n", fileName
);
909 fPtr
= fopen (fileName
, "r");
913 fprintf (stderr
, "ERROR---asn1 src file `%s' cannot be opened for reading\n", fileName
);
917 retVal
= (Module
*)Malloc (sizeof (Module
));
920 * Init Parser by giving it a ptr to the Module data struct
921 * to initialize/use, and the file name associtated with
922 * the given FILE *, fPtr (for error reporting).
923 * fPtr should be an opened FILE *to an ASN.1 source FILE
925 InitAsn1Parser (retVal
, fileName
, fPtr
);
929 * parse the current asn1 src file into the
932 parseResult
= yyparse();
934 if (parseResult
!= 0 || retVal
->status
== MOD_ERROR
)
936 /* parser will print exact err msg */
937 fprintf (stderr
, "Parsing errors---cannot proceed\n");
946 } /* ParseAsn1File */
950 * Given the list of parsed, linked, normalized, error-checked and sorted
951 * modules, and some code generation flags, generates C code and
952 * writes it to files derived from each modules name. Each module
953 * gets 2 source files, one .h for data struct and prototypes, the other .c
954 * for the enc/dec/print/free routine code.
957 GenCCode
PARAMS ((allMods
, longJmpVal
, genTypes
, genValues
, genEncoders
, genDecoders
, genPrinters
, genFree
),
958 ModuleList
*allMods _AND_
959 long int longJmpVal _AND_
962 int genEncoders _AND_
963 int genDecoders _AND_
964 int genPrinters _AND_
968 char *modBaseFileName
;
972 int fNameConflict
= FALSE
;
975 * Make names for each module's encoder/decoder src and hdr files
976 * so import references can be made via include files.
977 * If file names conflict, print error msg & exit.
979 fNames
= NewObjList();
980 FOR_EACH_LIST_ELMT (currMod
, allMods
)
982 modBaseFileName
= MakeBaseFileName (keepbaseG
983 ? currMod
->asn1SrcFileName
984 : currMod
->modId
->name
); /* shorten module name if necessary (SYSV etc) */
985 currMod
->cHdrFileName
= MakeCHdrFileName (modBaseFileName
);
986 currMod
->cSrcFileName
= MakeCSrcFileName (modBaseFileName
);
988 if (ObjIsDefined (fNames
, currMod
->cHdrFileName
, StrObjCmp
) ||
989 ObjIsDefined (fNames
, currMod
->cSrcFileName
, StrObjCmp
))
991 fprintf (stderr
, "Ack! ERROR---file name conflict for generated source files with names `%s' and `%s'.\n\n", currMod
->cHdrFileName
, currMod
->cSrcFileName
);
992 fprintf (stderr
, "This usually means the max file name length is truncating the file names.\n");
993 fprintf (stderr
, "Try re-naming the modules with shorter names or increasing the argument to -mf option (if you are using it).\n");
994 fprintf (stderr
, "This error can also be caused by 2 modules with the same names but different OBJECT IDENTIFIERs.");
995 fprintf (stderr
, " Try renaming the modules to correct this.\n");
996 fNameConflict
= TRUE
;
1000 DefineObj (&fNames
, currMod
->cHdrFileName
);
1001 DefineObj (&fNames
, currMod
->cSrcFileName
);
1003 Free (modBaseFileName
);
1008 FreeDefinedObjs (&fNames
);
1012 FOR_EACH_LIST_ELMT (currMod
, allMods
)
1014 cHdrFilePtr
= fopen (currMod
->cHdrFileName
, "w");
1015 cSrcFilePtr
= fopen (currMod
->cSrcFileName
, "w");
1016 if ((cSrcFilePtr
== NULL
) || (cHdrFilePtr
== NULL
))
1020 PrintCCode (cSrcFilePtr
, cHdrFilePtr
, allMods
, currMod
, &cRulesG
, longJmpVal
, genTypes
, genValues
, genEncoders
, genDecoders
, genPrinters
, genFree
);
1022 fclose (cHdrFilePtr
);
1023 fclose (cSrcFilePtr
);
1031 * Given the list of parsed, linked, normalized, error-checked and sorted
1032 * modules, and some code generation flags, generates C++ code and
1033 * writes it to files derived from each modules name. Each module
1034 * gets 2 source files, one .h for data struct and prototypes, the other .C
1035 * for the enc/dec/print/free routine code.
1038 GenCxxCode
PARAMS ((allMods
, longJmpVal
, genTypes
, genValues
, genEncoders
, genDecoders
, genPrinters
, genFree
, if_META (genMeta COMMA meta_pdus COMMA
) if_TCL (genTcl COMMA
) novolatilefuncs
),
1039 ModuleList
*allMods _AND_
1040 long int longJmpVal _AND_
1043 int genEncoders _AND_
1044 int genDecoders _AND_
1045 int genPrinters _AND_
1047 if_META (MetaNameStyle genMeta _AND_
)
1048 if_META (MetaPDU
*meta_pdus _AND_
)
1049 if_TCL (int genTcl _AND_
)
1050 int novolatilefuncs
)
1053 char *modBaseFileName
;
1057 FILE *hdbFilePtr
; /* 19.8.93 IBM-ENC */
1058 FILE *sdbFilePtr
; /* 19.8.93 IBM-ENC */
1059 #endif /* _IBM_ENC_ */
1061 int fNameConflict
= FALSE
;
1064 static const char metabasefn
[] = "modules";
1072 * Make names for each module's encoder/decoder src and hdr files
1073 * so import references can be made via include files
1074 * check for truncation --> name conflicts & exit if nec
1076 fNames
= NewObjList();
1079 DefineObj (&fNames
, meta
.srcfn
= MakeCxxSrcFileName (metabasefn
));
1081 FOR_EACH_LIST_ELMT (currMod
, allMods
)
1083 modBaseFileName
= MakeBaseFileName (keepbaseG
1084 ? currMod
->asn1SrcFileName
1085 : currMod
->modId
->name
); /* shorten module name if necessary (SYSV etc) */
1086 currMod
->cxxHdrFileName
= MakeCxxHdrFileName (modBaseFileName
);
1087 currMod
->cxxSrcFileName
= MakeCxxSrcFileName (modBaseFileName
);
1089 currMod
->dbHdrFileName
= MakedbHdrFileName (modBaseFileName
); /* 19.8.93 IBM-ENC */
1090 currMod
->dbSrcFileName
= MakedbSrcFileName (modBaseFileName
); /* 19.8.93 IBM-ENC */
1091 #endif /* _IBM_ENC_ */
1096 out
= currMod
->cxxname
= (char *)malloc (strlen (in
= currMod
->modId
->name
)+1);
1098 *out
++ = *in
== '-' ? '_' : *in
;
1103 if (ObjIsDefined (fNames
, currMod
->cxxHdrFileName
, StrObjCmp
) || ObjIsDefined (fNames
, currMod
->cxxSrcFileName
, StrObjCmp
))
1105 fprintf (stderr
, "Ack! ERROR---file name conflict for generated source files with names `%s' and `%s'.\n\n", currMod
->cxxHdrFileName
, currMod
->cxxSrcFileName
);
1106 fprintf (stderr
, "This usually means the max file name length is truncating the file names.\n");
1107 fprintf (stderr
, "Try re-naming the modules with shorter names or increasing the argument to -mf option (if you are using it).\n");
1108 fprintf (stderr
, "This error can also be caused by 2 modules have the same names but different OBJECT IDENTIFIERs.");
1109 fprintf (stderr
, " Try renaming the modules to correct this.\n");
1110 fNameConflict
= TRUE
;
1114 DefineObj (&fNames
, currMod
->cxxHdrFileName
);
1115 DefineObj (&fNames
, currMod
->cxxSrcFileName
);
1117 Free (modBaseFileName
);
1122 FreeDefinedObjs (&fNames
);
1130 time_t now
= time (NULL
);
1132 if (!(meta
.srcfp
= fopen (meta
.srcfn
, "w")))
1137 fprintf (meta
.srcfp
, "// NOTE: this is a machine generated file--editing not recommended\n");
1138 fprintf (meta
.srcfp
, "//\n");
1139 fprintf (meta
.srcfp
, "// modules.C - reference to all modules and their types\n");
1140 fprintf (meta
.srcfp
, "//\n");
1141 fprintf (meta
.srcfp
, "// This file was generated by snacc on %s", ctime (&now
));
1144 FOR_EACH_LIST_ELMT (currMod
, allMods
)
1147 * create and fill .h file for module's data structs
1149 hdrFilePtr
= fopen (currMod
->cxxHdrFileName
, "w");
1150 srcFilePtr
= fopen (currMod
->cxxSrcFileName
, "w");
1152 if ((hdrFilePtr
== NULL
) || (srcFilePtr
== NULL
))
1154 hdbFilePtr
= fopen (currMod
->dbHdrFileName
, "w"); /* 19.8.93 IBM-ENC */
1155 sdbFilePtr
= fopen (currMod
->dbSrcFileName
, "w"); /* 19.8.93 IBM-ENC */
1156 if ((hdrFilePtr
== NULL
) || (srcFilePtr
== NULL
) ||
1157 (hdbFilePtr
== NULL
) || (sdbFilePtr
== NULL
)) /* 19.8.93 IBM-ENC */
1158 #endif /* _IBM_ENC_ */
1162 PrintCxxCode (srcFilePtr
, hdrFilePtr
,
1163 if_IBM_ENC (sdbFilePtr COMMA hdbFilePtr COMMA
/* 19.8.93 IBM-ENC */)
1164 if_META (genMeta COMMA
&meta COMMA meta_pdus COMMA
)
1165 allMods
, currMod
, &cxxRulesG
, longJmpVal
,
1166 genTypes
, genValues
, genEncoders
, genDecoders
, genPrinters
, genFree
,
1167 if_TCL (genTcl COMMA
) novolatilefuncs
);
1169 fclose (hdrFilePtr
);
1170 fclose (srcFilePtr
);
1172 fclose (hdbFilePtr
); /* 19.8.93 IBM-ENC */
1173 fclose (sdbFilePtr
); /* 19.8.93 IBM-ENC */
1174 #endif /* _IBM_ENC_ */
1180 fprintf (meta
.srcfp
, "\n");
1181 fprintf (meta
.srcfp
, "#ifndef META\n");
1182 fprintf (meta
.srcfp
, "#define META 1\n");
1183 fprintf (meta
.srcfp
, "#endif\n");
1186 for (pdu
=meta_pdus
; pdu
; pdu
=pdu
->next
)
1188 fprintf (stderr
, "warning: PDU %s.%s couldn't be found\n", pdu
->module, pdu
->type
);
1191 fprintf (meta
.srcfp
, "#ifndef TCL\n");
1192 fprintf (meta
.srcfp
, "#define TCL META\n");
1193 fprintf (meta
.srcfp
, "#endif\n");
1195 fprintf (meta
.srcfp
, "\n");
1197 fprintf (meta
.srcfp
, "#include \"asn-incl.h\"\n");
1198 FOR_EACH_LIST_ELMT (currMod
, allMods
)
1199 fprintf (meta
.srcfp
, "#include \"%s\"\n", currMod
->cxxHdrFileName
);
1200 fprintf (meta
.srcfp
, "\n");
1202 fprintf (meta
.srcfp
, "#if META\n\n");
1204 fprintf (meta
.srcfp
, "const AsnModuleDesc *asnModuleDescs[] =\n");
1205 fprintf (meta
.srcfp
, "{\n");
1206 FOR_EACH_LIST_ELMT (currMod
, allMods
)
1207 fprintf (meta
.srcfp
, " &%sModuleDesc,\n", currMod
->cxxname
);
1208 fprintf (meta
.srcfp
, " NULL\n");
1209 fprintf (meta
.srcfp
, "};\n\n");
1213 fprintf (meta
.srcfp
, "#if TCL\n\n");
1215 fprintf (meta
.srcfp
, "// hack to avoid the neccessity to list -ltk -ltcl both before and after -lasn1tcl:\n");
1216 fprintf (meta
.srcfp
, "static int (*dummy)(Tcl_Interp *) = Tcl_AppInit;\n\n");
1218 fprintf (meta
.srcfp
, "#endif // TCL\n\n");
1221 fprintf (meta
.srcfp
, "#endif // META\n");
1223 fclose (meta
.srcfp
);
1231 * Given the list of parsed, linked, normalized, error-checked and sorted
1232 * modules, and some code generation flags, generates C++ code and
1233 * writes it to files derived from each modules name. Each module
1234 * gets 2 source files, one .h for data struct and prototypes, the other .C
1235 * for the enc/dec/print/free routine code.
1238 GenIDLCode
PARAMS ((allMods
, longJmpVal
, genTypes
, genValues
, genPrinters
, genFree
),
1239 ModuleList
*allMods _AND_
1240 long int longJmpVal _AND_
1243 int genPrinters _AND_
1247 char *modBaseFileName
;
1250 int fNameConflict
= FALSE
;
1253 * Make names for each module's encoder/decoder src and hdr files
1254 * so import references can be made via include files
1255 * check for truncation --> name conflicts & exit if nec
1257 fNames
= NewObjList();
1258 FOR_EACH_LIST_ELMT (currMod
, allMods
)
1260 modBaseFileName
= MakeBaseFileName (keepbaseG
1261 ? currMod
->asn1SrcFileName
1262 : currMod
->modId
->name
); /* shorten module name if necessary (SYSV etc) */
1263 currMod
->idlFileName
= MakeIDLFileName (modBaseFileName
);
1267 out
= currMod
->idlname
= (char *)malloc (strlen (in
= currMod
->modId
->name
)+1);
1269 *out
++ = *in
== '-' ? '_' : *in
;
1273 if (ObjIsDefined (fNames
, currMod
->idlFileName
, StrObjCmp
))
1275 fprintf (stderr
, "Ack! ERROR---file name conflict for generated source file with name `%s'.\n\n", currMod
->idlFileName
);
1276 fprintf (stderr
, "This usually means the max file name length is truncating the file names.\n");
1277 fprintf (stderr
, "Try re-naming the modules with shorter names or increasing the argument to -mf option (if you are using it).\n");
1278 fprintf (stderr
, "This error can also be caused by 2 modules have the same names but different OBJECT IDENTIFIERs.");
1279 fprintf (stderr
, " Try renaming the modules to correct this.\n");
1280 fNameConflict
= TRUE
;
1284 DefineObj (&fNames
, currMod
->idlFileName
);
1286 Free (modBaseFileName
);
1291 FreeDefinedObjs (&fNames
);
1296 FOR_EACH_LIST_ELMT (currMod
, allMods
)
1299 * create and fill .h file for module's data structs
1301 idlFilePtr
= fopen (currMod
->idlFileName
, "w");
1302 if (idlFilePtr
== NULL
)
1306 PrintIDLCode (idlFilePtr
, allMods
, currMod
, &idlRulesG
, longJmpVal
, genValues
);
1308 fclose (idlFilePtr
);
1316 * returns 1 if the module names and oid's are unique.
1317 * otherwise returns 0
1319 int ModNamesUnique
PARAMS ((mods
),
1327 names
= NewObjList();
1328 oids
= NewObjList();
1330 FOR_EACH_LIST_ELMT (m
, mods
)
1332 if (((m
->modId
->oid
!= NULL
) &&
1333 ObjIsDefined (oids
, m
->modId
->oid
, OidObjCmp
)))
1335 /* oops, 2 modules have the same oid */
1336 PrintErrLoc (m
->asn1SrcFileName
, 1);
1337 fprintf (stderr
, "ERROR---2 modules have the OBJECT IDENTIFIER `");
1338 PrintOid (stderr
, m
->modId
->oid
);
1339 fprintf (stderr
, "'.\n");
1342 /* name is only signficant if oid is empty */
1343 else if ((m
->modId
->oid
== NULL
) &&
1344 (ObjIsDefined (names
, m
->modId
->name
, StrObjCmp
)))
1346 /* oops, 2 modules have the same name */
1347 PrintErrLoc (m
->asn1SrcFileName
, 1);
1348 fprintf (stderr
, "ERROR---2 modules have the name `%s'\n", m
->modId
->name
);
1353 DefineObj (&names
, m
->modId
->name
);
1354 if (m
->modId
->oid
!= NULL
)
1355 DefineObj (&oids
, m
->modId
->oid
);
1358 FreeDefinedObjs (&names
);
1359 FreeDefinedObjs (&oids
);
1361 } /* ModNamesUnique */