726 lines
21 KiB
C
726 lines
21 KiB
C
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
|
|
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
|
|
|
|
#include "precomp.h"
|
|
|
|
#ifndef HAS_GETOPT
|
|
extern int getopt(int argc, char **argv, const char *opts);
|
|
extern char *optarg;
|
|
extern int optind;
|
|
#endif
|
|
|
|
int pass;
|
|
|
|
/* if ForceAllTypes is set, asn1c will generate encoding functions for */
|
|
/* all types (default: only for sequence/set/choice/sequence of/set of) */
|
|
int ForceAllTypes = 0;
|
|
|
|
/* type to use for unconstrained integers/semiconstrained signed integers */
|
|
char *IntegerRestriction = "ASN1int32_t";
|
|
|
|
/* type to use for semiconstrained unsigned integers */
|
|
char *UIntegerRestriction = "ASN1uint32_t";
|
|
|
|
/* type to use for real */
|
|
char *RealRestriction = "double";
|
|
|
|
/* output language */
|
|
Language_e g_eProgramLanguage = eLanguage_C;
|
|
|
|
/* alignment of encoding */
|
|
Alignment_e Alignment = eAlignment_Aligned;
|
|
|
|
/* encoding to generate code for */
|
|
Encoding_e g_eEncodingRule = eEncoding_Packed;
|
|
|
|
/* subencoding to generate code for */
|
|
SubEncoding_e g_eSubEncodingRule = eSubEncoding_Basic;
|
|
|
|
/* target compiler supports 64 bit integers */
|
|
int Has64Bits = 0;
|
|
|
|
/* zero out allocated buffers for decoded data */
|
|
int g_fDecZeroMemory = 1;
|
|
|
|
/* debug module name */
|
|
int g_nDbgModuleName = 0;
|
|
|
|
/* source file and header file pointers */
|
|
FILE *g_finc, *g_fout;
|
|
|
|
// default tag type in this module
|
|
TagType_e g_eDefTagType = eTagType_Unknown;
|
|
|
|
/* original main module name without postfixed _Module */
|
|
char *g_pszOrigModuleName = NULL;
|
|
char *g_pszOrigModuleNameLowerCase = NULL;
|
|
|
|
/* enable long name (prefixed with module name for imported) */
|
|
int g_fLongNameForImported = 0;
|
|
|
|
// extra struct type name postfixed with _s, and its original name is its pointer type.
|
|
int g_fExtraStructPtrTypeSS = 0;
|
|
|
|
// the default structure type for Sequence Of and Set Of
|
|
TypeRules_e g_eDefTypeRuleSS_NonSized = eTypeRules_SinglyLinkedList;
|
|
TypeRules_e g_eDefTypeRuleSS_Sized = eTypeRules_FixedArray;
|
|
|
|
// ignore the assertion
|
|
int g_fNoAssert = 0;
|
|
|
|
// object identifier is 16-node array
|
|
int g_fOidArray = 0;
|
|
|
|
// case based optimizer switch
|
|
int g_fCaseBasedOptimizer = 1;
|
|
|
|
// enable in-file directive
|
|
int g_fMicrosoftExtensions = 1;
|
|
|
|
// all platforms: little endian (default) and big endian
|
|
int g_fAllEndians = 0;
|
|
|
|
// directive begin, end, AND
|
|
int g_chDirectiveBegin = '#';
|
|
int g_chDirectiveEnd = '#';
|
|
int g_chDirectiveAND = '&';
|
|
|
|
// postfix
|
|
char *g_pszApiPostfix = "ID";
|
|
char *g_pszChoicePostfix = "choice";
|
|
char *g_pszOptionPostfix = "option";
|
|
|
|
// option value
|
|
char *g_pszOptionValue = "option_bits";
|
|
|
|
// invisble file array
|
|
int g_cGhostFiles = 0;
|
|
GhostFile_t g_aGhostFiles[16];
|
|
|
|
int _cdecl main(int argc, char **argv)
|
|
{
|
|
FILE *finc, *fout;
|
|
char *p;
|
|
int c, chInvalidDir;
|
|
LLSTATE in, out;
|
|
UndefinedSymbol_t *lastundef;
|
|
Assignment_t *a, **aa;
|
|
LLTERM *tokens;
|
|
unsigned ntokens;
|
|
int fSupported;
|
|
char *psz;
|
|
char incfilename[256], outfilename[256], module[256];
|
|
|
|
/* parse options */
|
|
// if an option is followed by ':', then it has a parameter.
|
|
while ((c = getopt(argc, argv, "ab:c:d:e:fg:hil:mn:o:p:q:s:t:uv:wy")) != EOF)
|
|
{
|
|
chInvalidDir = 0;
|
|
switch (c)
|
|
{
|
|
case 'a':
|
|
|
|
/* enable for all platforms: little endian and big endian */
|
|
g_fAllEndians = 1;
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
/* maximum number of bits of target machine */
|
|
if (atoi(optarg) == 32) {
|
|
Has64Bits = 0;
|
|
break;
|
|
}
|
|
if (atoi(optarg) == 64) {
|
|
Has64Bits = 1;
|
|
break;
|
|
}
|
|
fprintf(stderr, "Bad number of bits specified.\n");
|
|
MyExit(1);
|
|
/*NOTREACHED*/
|
|
|
|
case 'c':
|
|
|
|
// Choice postfix
|
|
psz = strdup(optarg);
|
|
if (psz && isalpha(*psz))
|
|
{
|
|
g_pszChoicePostfix = psz;
|
|
}
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
// sequence of and set of data structure types
|
|
if (! stricmp(optarg, "linked") || ! stricmp(optarg, "slinked"))
|
|
{
|
|
g_eDefTypeRuleSS_NonSized = eTypeRules_SinglyLinkedList;
|
|
}
|
|
else
|
|
if (! stricmp(optarg, "lenptr"))
|
|
{
|
|
g_eDefTypeRuleSS_NonSized = eTypeRules_LengthPointer;
|
|
}
|
|
else
|
|
if (! stricmp(optarg, "dlinked"))
|
|
{
|
|
g_eDefTypeRuleSS_NonSized = eTypeRules_DoublyLinkedList;
|
|
}
|
|
else
|
|
{
|
|
goto usage;
|
|
}
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
/* encoding to generate code for */
|
|
if (!stricmp(optarg, "packed"))
|
|
{
|
|
g_eEncodingRule = eEncoding_Packed;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "basic"))
|
|
{
|
|
g_eEncodingRule = eEncoding_Basic;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "per"))
|
|
{
|
|
g_eEncodingRule = eEncoding_Packed;
|
|
Alignment = eAlignment_Aligned;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "cer"))
|
|
{
|
|
g_eEncodingRule = eEncoding_Basic;
|
|
g_eSubEncodingRule = eSubEncoding_Canonical;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "der"))
|
|
{
|
|
g_eEncodingRule = eEncoding_Basic;
|
|
g_eSubEncodingRule = eSubEncoding_Distinguished;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "ber"))
|
|
{
|
|
g_eEncodingRule = eEncoding_Basic;
|
|
g_eSubEncodingRule = eSubEncoding_Basic;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Bad encoding specified.\n");
|
|
fprintf(stderr, "Allowed encodings are:\n");
|
|
fprintf(stderr, "- packed (default)\n");
|
|
fprintf(stderr, "- basic\n");
|
|
MyExit(1);
|
|
/*NOTREACHED*/
|
|
}
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
/* force generation of encoding/decoding functions for all types */
|
|
ForceAllTypes = 1;
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
/* ghost asn1 files */
|
|
g_aGhostFiles[g_cGhostFiles].pszFileName = strdup(optarg);
|
|
g_aGhostFiles[g_cGhostFiles++].pszModuleName = NULL;
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
goto usage;
|
|
|
|
case 'i':
|
|
|
|
/* ignore assertion */
|
|
g_fNoAssert = 1;
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
/* set output language */
|
|
if (!stricmp(optarg, "c")) {
|
|
g_eProgramLanguage = eLanguage_C;
|
|
break;
|
|
}
|
|
if (!stricmp(optarg, "c++") || !stricmp(optarg, "cpp")) {
|
|
g_eProgramLanguage = eLanguage_Cpp;
|
|
break;
|
|
}
|
|
goto usage;
|
|
|
|
case 'm':
|
|
|
|
/* enable Microsoft extension */
|
|
g_fMicrosoftExtensions = 1;
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
/* debug module name */
|
|
g_nDbgModuleName = 0;
|
|
{
|
|
int len = strlen(optarg);
|
|
if (len > 4)
|
|
len = 4;
|
|
memcpy(&g_nDbgModuleName, optarg, len);
|
|
}
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
// Option postfix
|
|
psz = strdup(optarg);
|
|
if (psz && isalpha(*psz))
|
|
{
|
|
g_pszOptionPostfix = psz;
|
|
}
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
// API postfix
|
|
psz = strdup(optarg);
|
|
if (psz && isalpha(*psz))
|
|
{
|
|
g_pszApiPostfix = psz;
|
|
}
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
// sequence of and set of data structure types
|
|
if (! stricmp(optarg, "linked") || ! stricmp(optarg, "slinked"))
|
|
{
|
|
g_eDefTypeRuleSS_Sized = eTypeRules_SinglyLinkedList;
|
|
}
|
|
else
|
|
if (! stricmp(optarg, "lenptr"))
|
|
{
|
|
g_eDefTypeRuleSS_Sized = eTypeRules_LengthPointer;
|
|
}
|
|
else
|
|
if (! stricmp(optarg, "array"))
|
|
{
|
|
g_eDefTypeRuleSS_Sized = eTypeRules_FixedArray;
|
|
}
|
|
else
|
|
if (! stricmp(optarg, "pointer"))
|
|
{
|
|
g_eDefTypeRuleSS_Sized = eTypeRules_PointerToElement | eTypeRules_FixedArray;
|
|
}
|
|
else
|
|
if (! stricmp(optarg, "dlinked"))
|
|
{
|
|
g_eDefTypeRuleSS_Sized = eTypeRules_DoublyLinkedList;
|
|
}
|
|
else
|
|
{
|
|
goto usage;
|
|
}
|
|
break;
|
|
|
|
case 's':
|
|
|
|
/* set subencoding */
|
|
if (!stricmp(optarg, "aligned"))
|
|
{
|
|
Alignment = eAlignment_Aligned;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "unaligned"))
|
|
{
|
|
Alignment = eAlignment_Unaligned;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "cer"))
|
|
{
|
|
g_eSubEncodingRule = eSubEncoding_Canonical;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "der"))
|
|
{
|
|
g_eSubEncodingRule = eSubEncoding_Distinguished;
|
|
}
|
|
else
|
|
if (!stricmp(optarg, "basic"))
|
|
{
|
|
g_eSubEncodingRule = eSubEncoding_Basic;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Bad sub-encoding specified.\n");
|
|
fprintf(stderr, "Allowed sub-encodings are:\n");
|
|
fprintf(stderr, "- aligned (default) or unaligned\n");
|
|
fprintf(stderr, "- basic (default), cer or der\n");
|
|
MyExit(1);
|
|
/*NOTREACHED*/
|
|
}
|
|
break;
|
|
|
|
case 't':
|
|
|
|
/* specify type to use for unconstrained/semiconstrained types */
|
|
p = strchr(optarg, '=');
|
|
if (!p)
|
|
goto usage;
|
|
*p++ = 0;
|
|
if (!stricmp(optarg, "integer")) {
|
|
if (!stricmp(p, "ASN1int32_t")) {
|
|
IntegerRestriction = "ASN1int32_t";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1uint32_t")) {
|
|
IntegerRestriction = "ASN1uint32_t";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1int64_t")) {
|
|
IntegerRestriction = "ASN1int64_t";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1uint64_t")) {
|
|
IntegerRestriction = "ASN1uint64_t";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1intx_t")) {
|
|
IntegerRestriction = "ASN1intx_t";
|
|
break;
|
|
}
|
|
}
|
|
if (!stricmp(optarg, "unsigned")) {
|
|
if (!stricmp(p, "ASN1int32_t")) {
|
|
UIntegerRestriction = "ASN1int32_t";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1uint32_t")) {
|
|
UIntegerRestriction = "ASN1uint32_t";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1int64_t")) {
|
|
UIntegerRestriction = "ASN1int64_t";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1uint64_t")) {
|
|
UIntegerRestriction = "ASN1uint64_t";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1intx_t")) {
|
|
UIntegerRestriction = "ASN1intx_t";
|
|
break;
|
|
}
|
|
}
|
|
if (!stricmp(optarg, "real")) {
|
|
if (!stricmp(p, "double")) {
|
|
RealRestriction = "double";
|
|
break;
|
|
}
|
|
if (!stricmp(p, "ASN1real_t")) {
|
|
RealRestriction = "ASN1real_t";
|
|
break;
|
|
}
|
|
}
|
|
goto usage;
|
|
|
|
case 'u':
|
|
|
|
// no case-based optimizer
|
|
g_fCaseBasedOptimizer = 0;
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
// Option value
|
|
psz = strdup(optarg);
|
|
if (psz && isalpha(*psz))
|
|
{
|
|
g_pszOptionValue = psz;
|
|
}
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
// --#OID ARRAY#--
|
|
g_fOidArray = 1;
|
|
break;
|
|
|
|
case 'y':
|
|
|
|
/* enable long name (prefixed with module name for imported) */
|
|
g_fLongNameForImported = 1;
|
|
break;
|
|
|
|
default:
|
|
|
|
chInvalidDir = c;
|
|
|
|
usage:
|
|
fprintf(stderr,"ASN.1 Compiler V1.0\n");
|
|
fprintf(stderr, "Copyright (C) Microsoft Corporation, U.S.A., 1997-1998. All rights reserved.\n");
|
|
fprintf(stderr, "Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved.\n");
|
|
if (chInvalidDir)
|
|
{
|
|
fprintf(stderr, "Invalid option -%c\n", chInvalidDir);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Usage: %s [options] [imported.asn1 ...] main.asn1\n", argv[0]);
|
|
fprintf(stderr, "Options:\n");
|
|
fprintf(stderr, "-h\t\tthis help\n");
|
|
fprintf(stderr, "-z\t\tzero out allocated buffers for decoded data\n");
|
|
fprintf(stderr, "-x\t\tbridge APIs\n");
|
|
fprintf(stderr, "-a\t\textra type definition for structure\n");
|
|
fprintf(stderr, "-n name\t\tmodule name for debugging purpose\n");
|
|
// fprintf(stderr, "-l language\tgenerate code for <language> (c (default), c++)\n");
|
|
// fprintf(stderr, "-b 64\t\tenable 64 bit support\n");
|
|
fprintf(stderr, "-e encoding\tuse <encoding> as encoding rule\n");
|
|
fprintf(stderr, "\t\t(possible values: packed (default), basic)\n");
|
|
fprintf(stderr, "-s subencoding\tuse <subencoding> as subencoding rules\n");
|
|
fprintf(stderr, "\t\t(possible values: aligned (default) or unaligned,\n");
|
|
fprintf(stderr, "\t\tbasic (default), canonical or distinguished)\n");
|
|
fprintf(stderr, "-t type=rest.\trestrict/unrestrict a unconstrained/semiconstrained type:\n");
|
|
fprintf(stderr, "\t\tinteger=type\tuse <type> (ASN1[u]int32_t, ASN1[u]int64_t or\n\t\t\t\tASN1intx_t) for unconstrained integers\n\t\t\t\t(default: ASN1int32_t)\n");
|
|
fprintf(stderr, "\t\tunsigned=type\tuse <type> (ASN1[u]int32_t, ASN1[u]int64_t or\n\t\t\t\tASN1intx_t) for positive semiconstrained\n\t\t\t\tintegers (default: ASN1uint32_t)\n");
|
|
fprintf(stderr, "\t\treal=type\tuse <type> (double or ASN1real_t) for\n\t\t\t\tunconstrained floating point numbers\n\t\t\t\t(default: double)\n");
|
|
}
|
|
MyExit(1);
|
|
}
|
|
}
|
|
|
|
/* check if any modules are given */
|
|
if (argc < optind + 1)
|
|
goto usage;
|
|
|
|
/* check for unsupported encoding */
|
|
fSupported = TRUE;
|
|
if (g_eEncodingRule == eEncoding_Packed)
|
|
{
|
|
if (Alignment != eAlignment_Aligned || g_eSubEncodingRule != eSubEncoding_Basic)
|
|
{
|
|
fSupported = FALSE;
|
|
}
|
|
}
|
|
else
|
|
if (g_eEncodingRule == eEncoding_Basic)
|
|
{
|
|
// if (Alignment != eAlignment_Aligned || g_eSubEncodingRule == eSubEncoding_Distinguished)
|
|
if (Alignment != eAlignment_Aligned)
|
|
{
|
|
fSupported = FALSE;
|
|
}
|
|
}
|
|
if (! fSupported)
|
|
{
|
|
fprintf(stderr, "Encoding not implemented (yet)\n");
|
|
MyExit(1);
|
|
}
|
|
|
|
/* initialize */
|
|
InitBuiltin();
|
|
|
|
/* scan file(s) */
|
|
#if defined(LLDEBUG) && LLDEBUG > 0
|
|
pass = 1;
|
|
fprintf(stderr, "Pass 1: Scanning input file\n");
|
|
#endif
|
|
readfiles(argv + optind);
|
|
llscanner(&tokens, &ntokens);
|
|
|
|
/* setup initial state */
|
|
in.Assignments = Builtin_Assignments;
|
|
in.AssignedObjIds = Builtin_ObjIds;
|
|
in.Undefined = NULL;
|
|
in.BadlyDefined = NULL;
|
|
in.Module = NULL;
|
|
in.MainModule = NULL;
|
|
in.Imported = NULL;
|
|
in.TagDefault = eTagType_Unknown;
|
|
in.ExtensionDefault = eExtensionType_None;
|
|
lastundef = NULL;
|
|
|
|
/* parse the modules */
|
|
do {
|
|
#if defined(LLDEBUG) && LLDEBUG > 0
|
|
fprintf(stderr, "Pass %d: Parsing \n", ++pass);
|
|
#endif
|
|
|
|
/* parse modules */
|
|
if (!llparser(tokens, ntokens, &in, &out)) {
|
|
llprinterror(stderr);
|
|
MyExit(1);
|
|
}
|
|
|
|
/* if undefined symbols remain the same as in previous pass */
|
|
/* than print these undefined symbols and MyExit */
|
|
if (!CmpUndefinedSymbolList(out.Assignments, out.Undefined, lastundef))
|
|
UndefinedError(out.Assignments, out.Undefined, out.BadlyDefined);
|
|
|
|
/* setup data for next pass */
|
|
in = out;
|
|
aa = &in.Assignments;
|
|
for (a = Builtin_Assignments; a; a = a->Next) {
|
|
*aa = DupAssignment(a);
|
|
aa = &(*aa)->Next;
|
|
}
|
|
*aa = NewAssignment(eAssignment_NextPass);
|
|
aa = &(*aa)->Next;
|
|
*aa = out.Assignments;
|
|
lastundef = out.Undefined;
|
|
in.Undefined = NULL;
|
|
in.BadlyDefined = NULL;
|
|
|
|
/* continue parsing until no undefined symbols left */
|
|
} while (lastundef);
|
|
|
|
/* build internal information */
|
|
#if defined(LLDEBUG) && LLDEBUG > 0
|
|
fprintf(stderr, "Pass %d: Building internal information \n", ++pass);
|
|
#endif
|
|
Examination(&out.Assignments, out.MainModule);
|
|
ExaminePER(out.Assignments);
|
|
ExamineBER(out.Assignments);
|
|
|
|
// remember who is the local duplicate of imported types
|
|
for (a = out.Assignments; a; a = a->Next)
|
|
{
|
|
a->fImportedLocalDuplicate = IsImportedLocalDuplicate(out.Assignments, out.MainModule, a) ? 1 : 0;
|
|
}
|
|
|
|
/* create file names and open files */
|
|
#if defined(LLDEBUG) && LLDEBUG > 0
|
|
fprintf(stderr, "Pass %d: Code generation \n", ++pass);
|
|
#endif
|
|
|
|
// create module name
|
|
StripModuleName(module, argv[argc - 1]);
|
|
|
|
// create inc file and out file names
|
|
strcpy(incfilename, module);
|
|
strcat(incfilename, ".h");
|
|
strcpy(outfilename, module);
|
|
strcat(outfilename, ".c");
|
|
for (p = module; *p; p++)
|
|
*p = (char)toupper(*p);
|
|
finc = fopen(incfilename, "w");
|
|
if (!finc) {
|
|
perror(incfilename);
|
|
MyExit(1);
|
|
}
|
|
fout = fopen(outfilename, "w");
|
|
if (!fout) {
|
|
perror(outfilename);
|
|
MyExit(1);
|
|
}
|
|
|
|
// lonchanc: change the full path name to file name only
|
|
{
|
|
char *psz = strrchr(module, '\\');
|
|
if (psz)
|
|
{
|
|
strcpy(module, psz+1);
|
|
}
|
|
}
|
|
|
|
// save the original module names
|
|
g_pszOrigModuleName = strdup(module);
|
|
g_pszOrigModuleNameLowerCase = strdup(module);
|
|
{
|
|
char *psz;
|
|
for (psz = g_pszOrigModuleNameLowerCase; *psz; psz++)
|
|
{
|
|
*psz = (char)tolower(*psz);
|
|
}
|
|
}
|
|
|
|
// lonchanc: append "_Module" to module name
|
|
strcat(module, "_Module");
|
|
|
|
/* code generation */
|
|
g_finc = finc;
|
|
g_fout = fout;
|
|
GenInc(out.Assignments, finc, module);
|
|
GenPrg(out.Assignments, fout, module, incfilename);
|
|
|
|
setoutfile(finc);
|
|
output("\n#ifdef __cplusplus\n");
|
|
outputni("} /* extern \"C\" */\n");
|
|
output("#endif\n\n");
|
|
output("#endif /* _%s_H_ */\n", module);
|
|
setoutfile(fout);
|
|
|
|
/* finitialize */
|
|
fclose(finc);
|
|
fclose(fout);
|
|
#if defined(LLDEBUG) && LLDEBUG > 0
|
|
fprintf(stderr, "Finished. \n");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/* why is this function not in MS libc? */
|
|
#ifndef HAS_GETOPT
|
|
char *optarg;
|
|
int optind = 1;
|
|
static int optpos = 1;
|
|
|
|
/* get the next option from the command line arguments */
|
|
int getopt(int argc, char **argv, const char *options) {
|
|
char *p, *q;
|
|
|
|
optarg = NULL;
|
|
|
|
/* find start of next option */
|
|
do {
|
|
if (optind >= argc)
|
|
return EOF;
|
|
if (*argv[optind] != '-' && *argv[optind] != '/')
|
|
return EOF;
|
|
p = argv[optind] + optpos++;
|
|
if (!*p) {
|
|
optind++;
|
|
optpos = 1;
|
|
}
|
|
} while (!*p);
|
|
|
|
/* find option in option string */
|
|
q = strchr(options, *p);
|
|
if (!q)
|
|
return '?';
|
|
|
|
/* set optarg for parameterized option and adjust optind and optpos for next call */
|
|
if (q[1] == ':') {
|
|
if (p[1]) {
|
|
optarg = p + 1;
|
|
optind++;
|
|
optpos = 1;
|
|
} else if (++optind < argc) {
|
|
optarg = argv[optind];
|
|
optind++;
|
|
optpos = 1;
|
|
} else {
|
|
return '?';
|
|
}
|
|
}
|
|
|
|
/* return found option */
|
|
return *p;
|
|
}
|
|
#endif
|
|
|
|
|
|
void StripModuleName(char *pszDst, char *pszSrc)
|
|
{
|
|
strcpy(pszDst, pszSrc);
|
|
if (!strcmp(pszDst + strlen(pszDst) - 5, ".asn1"))
|
|
pszDst[strlen(pszDst) - 5] = 0;
|
|
else if (!strcmp(pszDst + strlen(pszDst) - 4, ".asn"))
|
|
pszDst[strlen(pszDst) - 4] = 0;
|
|
}
|
|
|
|
|