]>
git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/tcl-asn/tclasn.c
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
21 * Allow spec of PDU to decode in asn<n> decode
22 * (Prefixing tp during decoding with PDU is not necessary)
32 #include <netinet/in.h>
34 typedef struct ChannelBuf
{
39 static void PutChannelBufInGenBuf
_ANSI_ARGS_((Tcl_Channel chan
, GenBuf
* gb
));
45 unsigned char result
= 0;
47 if (Tcl_Read(cb
->chan
,&result
,1)!=1)
57 static char result
[100];
62 if (*len
>sizeof(result
))
63 *len
= sizeof(result
);
64 *len
= Tcl_Read(cb
->chan
,result
,*len
);
74 ChanCopy (dst
, cb
, len
)
83 result
= Tcl_Read(cb
->chan
,dst
,len
);
93 ChanPeekCopy (dst
, cb
, len
)
98 unsigned long result
, result2
;
102 result
= ChanCopy(dst
,cb
,len
);
103 result2
= Tcl_Ungets(cb
->chan
,dst
,result
,0);
104 if (result2
!=result
) {
105 cb
->readError
= TRUE
;
114 unsigned char result
= 0;
115 ChanPeekCopy(&result
,cb
,1);
123 return cb
->readError
;
127 PutChannelBufInGenBuf (cb
, gb
)
132 cb
->readError
= FALSE
;
133 gb
->getByte
= (BufGetByteFcn
) ChanGetByte
;
134 gb
->getSeg
= (BufGetSegFcn
) ChanGetSeg
;
135 gb
->copy
= (BufCopyFcn
) ChanCopy
;
136 gb
->peekByte
= (BufPeekByteFcn
) ChanPeekByte
;
137 gb
->peekCopy
= (BufPeekCopyFcn
) ChanPeekCopy
;
138 gb
->readError
= (BufReadErrorFcn
) ChanReadError
;
141 #if TCL_MAJORVERSION<8
142 #define Tcl_GetStringResult(interp) (interp->result)
145 #define max(a,b) ((a)>(b)?(a):(b))
146 #define min(a,b) ((a)<(b)?(a):(b))
148 extern int matherr();
149 int *tclDummyMathPtr
= (int *) matherr
;
156 void myAsn1ErrorHandler (str
, severity
)
160 Tcl_AppendResult(interpG
,"ASN.1 error: ",str
,NULL
);
161 interpResultG
= TCL_ERROR
;
164 int equal (char* s1
, char* s2
)
166 return s1
==s2
|| (s1
&& s2
&& !strcmp(s1
,s2
));
169 int contained (char* in
, char* el
)
173 if (Tcl_SplitList(interpG
,in
,&argc
,&argv
)!=TCL_OK
)
176 if (equal(*argv
++,el
))
181 static struct TypePath
189 int TblDbgCallProc (cmdstart
, value
)
194 Tcl_DString cmd
, type
;
195 if (ntp
<=1 || !cmdstart
)
197 Tcl_DStringInit(&cmd
);
198 Tcl_DStringAppend(&cmd
,cmdstart
,-1);
199 Tcl_DStringInit(&type
);
200 for (i
=1; i
<ntp
; i
++)
202 Tcl_DStringAppendElement(&type
,tp
[i
].fieldname
?tp
[i
].fieldname
:tp
[i
].typename
);
206 sprintf(fmt
,"%d",tp
[i
].index
);
207 Tcl_DStringAppendElement(&type
,fmt
);
211 Tcl_DStringAppendElement(&cmd
,Tcl_DStringValue(&type
));
212 Tcl_DStringFree(&type
);
213 Tcl_DStringAppendElement(&cmd
,value
);
214 interpResultG
= Tcl_Eval(interpG
,Tcl_DStringValue(&cmd
));
215 Tcl_DStringFree(&cmd
);
216 return interpResultG
;
220 static char* TIN
[] = { "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
221 "NULL", "OBJECT IDENTIFIER", "REAL", "ENUMERATED", "SEQUENCE", "SET",
222 "SEQUENCE OF", "SET OF", "CHOICE", "TYPEREF" };
224 #define SPECIALID_STR -1
227 TblEncAsk (tid
, v
, precmd
)
234 Tcl_DString cmd
, type
;
237 Tcl_DStringInit(&cmd
);
238 Tcl_DStringAppend(&cmd
,precmd
,-1);
239 Tcl_DStringInit(&type
);
240 for (i
=1; i
<ntp
; i
++)
242 Tcl_DStringAppendElement(&type
,tp
[i
].fieldname
?tp
[i
].fieldname
:tp
[i
].typename
);
245 sprintf(fmt
,"%d",tp
[i
].index
);
246 Tcl_DStringAppendElement(&type
,fmt
);
250 Tcl_DStringAppendElement(&cmd
,Tcl_DStringValue(&type
));
251 Tcl_DStringFree(&type
);
252 result
= Tcl_Eval(interpG
,Tcl_DStringValue(&cmd
));
253 Tcl_DStringFree(&cmd
);
256 iresult
= Tcl_GetStringResult(interpG
);
260 *(AsnBool
*)v
= !(!strcmp(iresult
,"0") || toupper(*iresult
)=='F' || !*iresult
);
264 *(AsnInt
*)v
= atoi(iresult
);
267 sscanf(iresult
,"%lf",(AsnReal
*)v
);
270 ((AsnBits
*)v
)->bitLen
= strlen(iresult
);
271 ((AsnBits
*)v
)->bits
= Asn1Alloc(((AsnBits
*)v
)->bitLen
?(((AsnBits
*)v
)->bitLen
-1)/8+1:0);
272 for (i
=0; iresult
[i
]; i
++)
274 SetAsnBit((AsnBits
*)v
,i
);
276 case TBL_OCTETSTRING
:
278 ((AsnOcts
*)v
)->octs
= Asn1Alloc(strlen(iresult
)); /* Might be too much, but don't care */
279 for (i
=((AsnOcts
*)v
)->octetLen
=0; iresult
[i
]; i
++,((AsnOcts
*)v
)->octetLen
++)
280 if (iresult
[i
]=='\\')
283 strncpy(fmt
,iresult
+i
+1,3);
285 ((AsnOcts
*)v
)->octs
[((AsnOcts
*)v
)->octetLen
] = strtol(fmt
,&skipto
,8);
289 ((AsnOcts
*)v
)->octs
[((AsnOcts
*)v
)->octetLen
] = iresult
[i
];
292 *(char**)v
= Asn1Alloc(strlen(iresult
)+1);
293 strcpy(*(char**)v
,iresult
);
298 Tcl_ResetResult(interpG
);
303 TblEncType
PARAMS ((type
, b
, implicit
, bytesEncoded
),
307 unsigned long int *bytesEncoded
)
310 unsigned long int tmpBytesEncoded
= 0;
311 unsigned int currElmt
;
326 if (type
->typeId
==TBL_TYPEREF
&& !tp
[ntp
-1].typename
)
327 tp
[ntp
-1].typename
= type
->content
->a
.typeRef
->typeDefPtr
->typeName
.octs
;
328 if (type
->typeId
!=TBL_TYPEREF
&& !tp
[ntp
-1].typename
)
329 tp
[ntp
-1].typename
= TIN
[type
->typeId
];
330 if (!tp
[ntp
-1].fieldname
)
331 tp
[ntp
-1].fieldname
= type
->fieldName
.octs
;
333 switch (type
->typeId
)
338 * carry over implicit ref if goes
339 * through typeref with no tags
341 implicitRef
= type
->content
->a
.typeRef
->implicit
||
343 ((type
->tagList
== NULL
) || LIST_EMPTY (type
->tagList
)));
345 result
= TblEncType (type
->content
->a
.typeRef
->typeDefPtr
->type
, b
, implicitRef
,
353 /* rvs though list value and list type def */
354 currElmt
= LIST_COUNT (type
->content
->a
.elmts
);
355 tmp
= CURR_LIST_NODE (type
->content
->a
.elmts
);
356 result
= TblEncAsk(SPECIALID_STR
,&elmtname
,tbltypecmdG
);
359 FOR_EACH_LIST_ELMT_RVS (elmt
, type
->content
->a
.elmts
)
362 || contained(elmtname
,elmt
->fieldName
.octs
)
363 || !elmt
->fieldName
.octetLen
&&
364 (elmt
->typeId
==TBL_TYPEREF
&& contained(elmtname
,
365 elmt
->content
->a
.typeRef
->typeDefPtr
->typeName
.octs
)
366 || elmt
->typeId
!=TBL_TYPEREF
&& contained(elmtname
,
369 tp
[ntp
].typename
= tp
[ntp
].fieldname
= NULL
;
372 result
= TblEncType (elmt
, b
, FALSE
, &tmpBytesEncoded
);
375 Asn1Free(optavail
.bits
);
382 /* restore list curr in case recursive type */
383 SET_CURR_LIST_NODE (type
->content
->a
.elmts
, tmp
);
388 result
= TblEncAsk(TBL_INTEGER
,&tp
[ntp
-1].index
,tbltypecmdG
);
391 elmt
= FIRST_LIST_ELMT (type
->content
->a
.elmts
);
392 for (;tp
[ntp
-1].index
>=1;tp
[ntp
-1].index
--)
394 tp
[ntp
].typename
= tp
[ntp
].fieldname
= NULL
;
397 result
= TblEncType (elmt
, b
, FALSE
, &tmpBytesEncoded
);
405 result
= TblEncAsk(SPECIALID_STR
,&elmtname
,tbltypecmdG
);
408 tmp
= CURR_LIST_NODE (type
->content
->a
.elmts
);
410 FOR_EACH_LIST_ELMT(elmt
, type
->content
->a
.elmts
)
411 if (equal(elmtname
,elmt
->fieldName
.octs
))
417 FOR_EACH_LIST_ELMT(elmt
, type
->content
->a
.elmts
)
418 if (!elmt
->fieldName
.octetLen
)
420 if (elmt
->typeId
==TBL_TYPEREF
)
422 if (equal(elmtname
,elmt
->content
->a
.typeRef
->typeDefPtr
->typeName
.octs
))
428 else if (equal(elmtname
,TIN
[elmt
->typeId
]))
435 SET_CURR_LIST_NODE (type
->content
->a
.elmts
, tmp
);
438 tp
[ntp
].typename
= tp
[ntp
].fieldname
= NULL
;
441 result
= TblEncType(choice
,b
,FALSE
,&tmpBytesEncoded
);
449 result
= TblEncAsk(type
->typeId
,&unival
,tblvalcmdG
);
452 tmpBytesEncoded
+= BEncAsnBoolContent (b
, &unival
.bo
);
453 if (interpResultG
!=TCL_OK
)
454 return interpResultG
;
459 result
= TblEncAsk(type
->typeId
,&unival
,tblvalcmdG
);
462 tmpBytesEncoded
+= BEncAsnIntContent (b
, &unival
.in
);
463 if (interpResultG
!=TCL_OK
)
464 return interpResultG
;
468 result
= TblEncAsk(type
->typeId
,&unival
,tblvalcmdG
);
471 tmpBytesEncoded
+= BEncAsnBitsContent (b
, &unival
.bi
);
472 Asn1Free(unival
.bi
.bits
);
473 if (interpResultG
!=TCL_OK
)
474 return interpResultG
;
477 case TBL_OCTETSTRING
:
478 result
= TblEncAsk(type
->typeId
,&unival
,tblvalcmdG
);
481 tmpBytesEncoded
+= BEncAsnOctsContent (b
, &unival
.oc
);
482 Asn1Free(unival
.oc
.octs
);
483 if (interpResultG
!=TCL_OK
)
484 return interpResultG
;
488 tmpBytesEncoded
+= BEncAsnNullContent (b
, NULL
);
489 if (interpResultG
!=TCL_OK
)
490 return interpResultG
;
494 result
= TblEncAsk(type
->typeId
,&unival
,tblvalcmdG
);
497 tmpBytesEncoded
+= BEncAsnOidContent (b
, &unival
.oc
);
498 Asn1Free(unival
.oc
.octs
);
499 if (interpResultG
!=TCL_OK
)
500 return interpResultG
;
504 result
= TblEncAsk(type
->typeId
,&unival
,tblvalcmdG
);
507 tmpBytesEncoded
+= BEncAsnRealContent (b
, &unival
.re
);
508 if (interpResultG
!=TCL_OK
)
509 return interpResultG
;
513 Tcl_AppendResult(interpG
,"strange type",NULL
);
518 TblEncodeTagsAndLens (type
, b
, implicit
, &tmpBytesEncoded
);
519 (*bytesEncoded
) += tmpBytesEncoded
;
526 TblEnc
PARAMS (( type
, b
),
530 unsigned long int bytesEncoded
= 0;
533 result
= TblEncType (type
, b
, FALSE
, &bytesEncoded
);
534 if (result
==TCL_OK
&& BufWriteError (b
))
536 Tcl_AppendResult(interpG
,"error writing buffer",NULL
);
539 interpResultG
= result
;
548 TblDbgValue (type
, val
, pvalue
)
554 switch (type
->typeId
)
557 Tcl_DStringAppend(pvalue
,*(AsnBool
*)val
? "TRUE" :"FALSE", -1);
561 sprintf(fmt
,"%d",*(AsnInt
*)val
);
562 Tcl_DStringAppend(pvalue
,fmt
, -1);
566 AsnBits
* v
= (AsnBits
*)val
;
568 for (i
=0; i
<v
->bitLen
; i
++)
569 Tcl_DStringAppend(pvalue
,GetAsnBit(v
,i
)?"1":"0", -1);
572 case TBL_OCTETSTRING
:
575 AsnOcts
* v
= (AsnOcts
*)val
;
577 for (i
=0; i
<v
->octetLen
; i
++)
578 if (v
->octs
[i
]=='\\' || !isprint(v
->octs
[i
]))
580 sprintf(fmt
,"\\%03o",v
->octs
[i
]);
581 Tcl_DStringAppend(pvalue
,fmt
,-1);
584 Tcl_DStringAppend(pvalue
,v
->octs
+i
,1);
588 Tcl_DStringAppend(pvalue
,"NULL", -1);
591 sprintf(fmt
,"%G",*(AsnReal
*)val
);
592 Tcl_DStringAppend(pvalue
,fmt
, -1);
601 TblDbgType
PARAMS ((type
, val
, begin
),
609 if (type
->typeId
==TBL_TYPEREF
&& !tp
[ntp
-1].typename
)
610 tp
[ntp
-1].typename
= type
->content
->a
.typeRef
->typeDefPtr
->typeName
.octs
;
611 if (type
->typeId
!=TBL_TYPEREF
&& !tp
[ntp
-1].typename
)
612 tp
[ntp
-1].typename
= TIN
[type
->typeId
];
613 if (!tp
[ntp
-1].fieldname
)
614 tp
[ntp
-1].fieldname
= type
->fieldName
.octs
;
615 if (type
->typeId
>= TBL_SEQUENCE
&& type
->typeId
<= TBL_CHOICE
)
617 result
= TblDbgCallProc(tbltypecmdG
,"1");
618 if (type
->typeId
== TBL_SEQUENCEOF
|| type
->typeId
== TBL_SETOF
)
620 tp
[ntp
].typename
= tp
[ntp
].fieldname
= NULL
;
625 else if (type
->typeId
!=TBL_TYPEREF
)
627 if (type
->typeId
< TBL_SEQUENCE
)
630 Tcl_DStringInit(&value
);
631 TblDbgValue(type
,val
,&value
);
632 result
= TblDbgCallProc(tblvalcmdG
,Tcl_DStringValue(&value
));
633 Tcl_DStringFree(&value
);
636 if (type
->typeId
== TBL_SEQUENCEOF
|| type
->typeId
== TBL_SETOF
)
638 result
= TblDbgCallProc(tbltypecmdG
,"-1");
640 tp
[ntp
-1].typename
= tp
[ntp
-1].fieldname
= NULL
;
648 TBLType
* TblFindType (type
, argv
, followref
, ptr
, ptnnl
)
653 TBLNamedNumberList
** ptnnl
;
660 if (ptr
&& !*ptr
&& type
->constraint
)
661 *ptr
= type
->constraint
;
662 if (ptnnl
&& !*ptnnl
&& type
->values
)
663 *ptnnl
= type
->values
;
664 if (!followref
|| type
->typeId
!=TBL_TYPEREF
)
667 switch (type
->typeId
)
670 return TblFindType(type
->content
->a
.typeRef
->typeDefPtr
->type
,argv
,followref
,ptr
,ptnnl
);
674 tmp
= CURR_LIST_NODE (type
->content
->a
.elmts
);
676 FOR_EACH_LIST_ELMT(elmt
,type
->content
->a
.elmts
)
677 if (equal(*argv
,elmt
->fieldName
.octs
))
679 result
= TblFindType(elmt
,argv
+1,followref
,ptr
,ptnnl
);
683 FOR_EACH_LIST_ELMT(elmt
,type
->content
->a
.elmts
)
684 if (!elmt
->fieldName
.octetLen
)
686 if (elmt
->typeId
==TBL_TYPEREF
)
688 if (equal(*argv
,elmt
->content
->a
.typeRef
->typeDefPtr
->typeName
.octs
)) {
689 result
= TblFindType(elmt
->content
->a
.typeRef
->typeDefPtr
->type
,argv
+1,followref
,ptr
,ptnnl
);
693 else if (equal(*argv
,TIN
[elmt
->typeId
])) {
694 result
= TblFindType(elmt
,argv
+1,followref
,ptr
,ptnnl
);
699 SET_CURR_LIST_NODE (type
->content
->a
.elmts
, tmp
);
703 if (**argv
>='0'&&**argv
<='9')
705 return TblFindType(FIRST_LIST_ELMT(type
->content
->a
.elmts
),argv
,followref
,ptr
,ptnnl
);
712 TBLType
* TblTypeOfPath (interp
, tbl
, path
, followref
, ptd
, ptr
, ptnnl
)
718 TBLNamedNumberList
** ptnnl
;
720 TBLModule
* tm
= NULL
;
722 TBLType
* type
= NULL
;
725 if (Tcl_SplitList(interp
,path
,&argc
,&argv
)!=TCL_OK
)
727 if (argc
>=2 && (tm
= TblFindModule(tbl
,argv
[0])))
732 if (argc
<1 || !(td
=TblFindTypeDef(tbl
,tm
?tm
->name
.octs
:NULL
,argv
[0],&tm
))
733 || !(type
=TblFindType(td
->type
,argv
+1,followref
,ptr
,ptnnl
)))
734 Tcl_AppendResult(interp
,"wrong typepath \"",path
,
735 "\", should be ?module? typedef ?subtype? ...", NULL
);
738 Tcl_Free((char*)argv
);
742 int dowrite (Tcl_Channel chan
, char* buffer
, int n
)
748 onewrite
= Tcl_Write(chan
,buffer
+written
,n
-written
);
757 int TblCmdEncode (interp
, tbl
, chan
, path
, valcmd
, typecmd
)
770 TBLType
* type
= TblTypeOfPath (interp
, tbl
, path
, FALSE
, NULL
, NULL
, NULL
);
773 Tcl_AppendResult(interp
,"wrong typepath \"",path
,"\"",NULL
);
778 interpResultG
= TCL_OK
;
780 tbltypecmdG
= typecmd
?typecmd
:valcmd
;
782 ep
= ExpBufAllocBufAndData();
783 ExpBufResetInWriteRvsMode (ep
); /* set up to hold encoding (= writing) */
784 PutExpBufInGenBuf (ep
, &gb
);
785 write
= TblEnc(type
,&gb
);
786 ep
= ExpBufListFirstBuf(ep
);
788 for (b
=ep
;interpResultG
==TCL_OK
&& b
;b
=ExpBufNext(b
))
790 if (dowrite(chan
,ExpBufDataPtr(b
),ExpBufDataSize(b
))!=ExpBufDataSize(b
))
792 Asn1Error("Error during writing");
796 ExpBufFreeBufAndDataList (ep
);
797 return interpResultG
;
800 int doread (Tcl_Channel chan
, char* buffer
, int n
, int checkeof
)
806 oneread
= Tcl_Read(chan
,buffer
+haveread
,n
-haveread
);
812 if (checkeof
&& oneread
==0 && haveread
==0)
813 /* Nothing there although select sais readable -> EOF */
821 int TblCmdDecode (interp
, tbl
, chan
, path
, valcmd
, typecmd
)
832 unsigned long bytesDecoded
;
835 TBLType
* type
= TblTypeOfPath (interp
, tbl
, path
, FALSE
, NULL
, NULL
, NULL
);
838 Tcl_AppendResult(interp
,"wrong typepath \"",path
,"\"",NULL
);
842 result
= Tcl_Read(chan
,&test
,1);
844 Tcl_AppendResult(interp
,"read failed",NULL
);
848 Tcl_AppendResult(interp
,"0",NULL
);
851 result
= Tcl_Ungets(chan
,&test
,1,0);
853 Tcl_AppendResult(interp
,"ungets failed",NULL
);
858 PutChannelBufInGenBuf(&cb
,&gb
);
861 interpResultG
= TCL_OK
;
863 tbltypecmdG
= typecmd
;
866 result
= TdeDecodeSpecific(tbl
,&gb
,type
,&bytesDecoded
,TblDbgType
,NULL
,NULL
);
867 if (interpResultG
==TCL_OK
)
870 Asn1Error("TdeDecodeSpecific failed");
872 if (interpResultG
==TCL_OK
)
875 sprintf(buffer
,"%u",(int)bytesDecoded
);
876 Tcl_SetResult(interp
,buffer
,TCL_VOLATILE
);
878 return interpResultG
;
881 int TblRealType (type
)
884 if (type
->typeId
==TBL_TYPEREF
)
885 return TblRealType(type
->content
->a
.typeRef
->typeDefPtr
->type
);
890 TBLModule
* TblModuleOfTypeDef (tbl
, td
)
899 /* look in all modules and return typedef with given id */
900 tmp1
= CURR_LIST_NODE (tbl
->modules
);
901 FOR_EACH_LIST_ELMT (tm
, tbl
->modules
)
903 tmp2
= CURR_LIST_NODE (tm
->typeDefs
);
904 FOR_EACH_LIST_ELMT (td2
, tm
->typeDefs
)
907 SET_CURR_LIST_NODE (tm
->typeDefs
, tmp2
);
908 SET_CURR_LIST_NODE (tbl
->modules
, tmp1
);
911 SET_CURR_LIST_NODE (tm
->typeDefs
, tmp2
);
913 SET_CURR_LIST_NODE (tbl
->modules
, tmp1
);
917 void TblDescType (ps
, tbl
, tm
, td
, type
, tr
, tnnl
)
924 TBLNamedNumberList
* tnnl
;
927 Tcl_DStringStartSublist(ps
);
928 Tcl_DStringAppendElement(ps
,tm
->name
.octs
);
929 Tcl_DStringAppendElement(ps
,td
->typeName
.octs
);
930 Tcl_DStringAppendElement(ps
,td
->isPdu
?"pdu":"sub");
931 Tcl_DStringEndSublist(ps
);
933 Tcl_DStringAppendElement(ps
,type
->fieldName
.octs
);
935 Tcl_DStringAppendElement(ps
,TIN
[type
->typeId
]);
936 Tcl_DStringStartSublist(ps
);
938 tr
= type
->constraint
;
941 sprintf(fmt
,"%d",tr
->from
);
942 Tcl_DStringAppendElement(ps
,fmt
);
943 if (tr
->to
!=tr
->from
) {
944 sprintf(fmt
,"%d",tr
->to
);
945 Tcl_DStringAppendElement(ps
,fmt
);
948 Tcl_DStringEndSublist(ps
);
949 Tcl_DStringStartSublist(ps
);
954 FOR_EACH_LIST_ELMT(tnn
,tnnl
)
957 Tcl_DStringStartSublist(ps
);
958 sprintf(fmt
,"%d",tnn
->value
);
959 Tcl_DStringAppendElement(ps
,fmt
);
960 if (tnn
->name
.octetLen
)
961 Tcl_DStringAppendElement(ps
,tnn
->name
.octs
);
962 Tcl_DStringEndSublist(ps
);
965 Tcl_DStringEndSublist(ps
);
967 switch (type
->content
->choiceId
) {
968 case TBLTYPECONTENT_ELMTS
:
971 void* tmp
= CURR_LIST_NODE (type
->content
->a
.elmts
);
972 Tcl_DStringStartSublist(ps
);
973 FOR_EACH_LIST_ELMT(elmt
,type
->content
->a
.elmts
)
975 Tcl_DStringStartSublist(ps
);
976 TblDescType(ps
,tbl
,tm
,NULL
,elmt
,NULL
,NULL
);
977 Tcl_DStringEndSublist(ps
);
978 Tcl_DStringAppendElement(ps
,elmt
->optional
?"0":"1");
980 Tcl_DStringEndSublist(ps
);
981 SET_CURR_LIST_NODE (type
->content
->a
.elmts
, tmp
);
984 case TBLTYPECONTENT_TYPEREF
:
986 TBLTypeDef
* td
= type
->content
->a
.typeRef
->typeDefPtr
;
987 Tcl_DStringStartSublist(ps
);
988 Tcl_DStringAppendElement(ps
,TblModuleOfTypeDef(tbl
,td
)->name
.octs
);
989 Tcl_DStringAppendElement(ps
,td
->typeName
.octs
);
990 Tcl_DStringEndSublist(ps
);
998 typedef struct TblCmdData
{
1003 int TblCmd (tcd
, interp
, argc
, argv
)
1013 l
= strlen(argv
[1]);
1015 if (argc
==2 && !strncmp(argv
[1],"close",l
)) {
1016 Tcl_DeleteCommand(interp
,tcd
->name
);
1018 } else if (!strncmp(argv
[1],"decode",l
) && (argc
>=5 && argc
<=6)) {
1020 Tcl_Channel chan
= Tcl_GetChannel(interp
,argv
[2],&mode
);
1023 if (!(mode
& TCL_READABLE
)) {
1024 Tcl_AppendResult(interp
, "channel \"", argv
[2],
1025 "\" wasn't opened for reading", NULL
);
1028 return TblCmdDecode(interp
,tcd
->tbl
,chan
,argv
[3],argv
[4],argv
[5]);
1029 } else if (!strncmp(argv
[1],"encode",l
) && (argc
>=5 && argc
<=6)) {
1031 Tcl_Channel chan
= Tcl_GetChannel(interp
,argv
[2],&mode
);
1034 if (!(mode
& TCL_WRITABLE
)) {
1035 Tcl_AppendResult(interp
, "channel \"", argv
[2],
1036 "\" wasn't opened for writing", NULL
);
1039 return TblCmdEncode(interp
,tcd
->tbl
,chan
,argv
[3],argv
[4],argv
[5]);
1040 } else if (argc
==2 && !strncmp(argv
[1],"modules",l
)) {
1042 FOR_EACH_LIST_ELMT (tm
, tcd
->tbl
->modules
)
1043 Tcl_AppendElement(interp
,tm
->name
.octs
);
1045 } else if (!strncmp(argv
[1],"type",l
) && (argc
==3
1046 || argc
==4 && !strncmp(argv
[2],"-followref",max(strlen(argv
[2]),2)))) {
1048 TBLRange
* tr
= NULL
;
1049 TBLNamedNumberList
* tnnl
= NULL
;
1050 TBLType
* type
= TblTypeOfPath(interp
,tcd
->tbl
,argv
[argc
-1],argc
==4,
1057 Tcl_DStringInit(&ds
);
1058 TblDescType(&ds
,tcd
->tbl
,TblModuleOfTypeDef(tcd
->tbl
,td
),
1059 type
==td
->type
?td
:NULL
,type
,tr
,tnnl
);
1060 Tcl_DStringResult(interp
,&ds
);
1061 Tcl_DStringFree(&ds
);
1065 } else if (argc
>=2 && argc
<=3 && !strncmp(argv
[1],"types",l
)) {
1068 int moduleFound
= 0;
1070 Tcl_DStringInit(&ds
);
1071 FOR_EACH_LIST_ELMT (tm
, tcd
->tbl
->modules
)
1072 if (argc
==2 || equal(tm
->name
.octs
,argv
[2])) {
1074 FOR_EACH_LIST_ELMT (td
, tm
->typeDefs
) {
1075 Tcl_DStringStartSublist(&ds
);
1076 Tcl_DStringAppendElement(&ds
,tm
->name
.octs
);
1077 Tcl_DStringAppendElement(&ds
,td
->typeName
.octs
);
1078 Tcl_DStringEndSublist(&ds
);
1081 Tcl_DStringResult(interp
,&ds
);
1082 Tcl_DStringFree(&ds
);
1083 if (argc
==3 && !moduleFound
) {
1084 Tcl_AppendResult(interp
,argv
[0]," ",argv
[1],": module \"",argv
[2],
1091 Tcl_AppendResult(interp
, "wrong # args: should be \"",
1094 " | types ?module?",
1095 " | type ?-followref? {?module? typedef ?subtype? ...}",
1096 " | decode channel {?module? typedef ?subtype? ...} valcmd ?typecmd?",
1097 " | encode channel {?module? typedef ?subtype? ...} valcmd ?typecmd?",
1103 void TblCmdFree (tcd
)
1110 int TableCmd (clientData
, interp
, argc
, argv
)
1111 ClientData clientData
;
1116 static int ntbl
= 0;
1121 Tcl_AppendResult(interp
, "wrong # args: should be \"",
1122 argv
[0], " path\"", NULL
);
1127 interpResultG
= TCL_OK
;
1128 tbl
= LoadTblFile(argv
[1]);
1129 if (!tbl
&& interpResultG
==TCL_OK
) {
1130 Asn1Error("Can't load grammar table");
1133 if (interpResultG
!=TCL_OK
)
1134 return interpResultG
;
1136 tcd
= (TblCmdData
*) ckalloc(sizeof(*tcd
));
1137 sprintf(tcd
->name
,"asn%d",++ntbl
);
1139 Tcl_CreateCommand(interp
,tcd
->name
,TblCmd
,tcd
,TblCmdFree
);
1140 Tcl_AppendResult(interp
,tcd
->name
,NULL
);
1145 *----------------------------------------------------------------------
1149 * This procedure performs application-specific initialization.
1150 * Most applications, especially those that incorporate additional
1151 * packages, will have their own version of this procedure.
1154 * Returns a standard Tcl completion code, and leaves an error
1155 * message in interp->result if an error occurs.
1158 * Depends on the startup script.
1160 *----------------------------------------------------------------------
1166 Tcl_Interp
*interp
; /* Interpreter for application. */
1168 if (Tcl_Init(interp
) == TCL_ERROR
) {
1171 if (Tk_Init(interp
) == TCL_ERROR
) {
1176 * Call Tcl_CreateCommand for application-specific commands, if
1177 * they weren't already created by the init procedures called above.
1180 Asn1InstallErrorHandler(myAsn1ErrorHandler
);
1181 InitNibbleMem(1024,1024);
1182 Tcl_CreateCommand(interp
, "asn", TableCmd
, NULL
, NULL
);