Doc fix.
[libtasn1.git] / lib / structure.c
blobd437a8cc7f94f1932f3445aa681df4caf4db264a
1 /*
2 * Copyright (C) 2002 Fabio Fiorina
3 * Copyright (C) 2004 Simon Josefsson
5 * This file is part of LIBASN1.
7 * The LIBTASN1 library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /*****************************************************/
24 /* File: structure.c */
25 /* Description: Functions to create and delete an */
26 /* ASN1 tree. */
27 /*****************************************************/
30 #include <int.h>
31 #include <errors.h>
32 #include <structure.h>
33 #include "parser_aux.h"
34 #include "der.h"
35 #include <gstr.h>
38 extern char _asn1_identifierMissing[];
41 /******************************************************/
42 /* Function : _asn1_add_node_only */
43 /* Description: creates a new NODE_ASN element. */
44 /* Parameters: */
45 /* type: type of the new element (see TYPE_ */
46 /* and CONST_ constants). */
47 /* Return: pointer to the new element. */
48 /******************************************************/
49 node_asn *
50 _asn1_add_node_only(unsigned int type)
52 node_asn *punt;
54 punt=(node_asn *) _asn1_malloc(sizeof(node_asn));
55 if (punt==NULL) return NULL;
57 punt->left=NULL;
58 punt->name=NULL;
59 punt->type=type;
60 punt->value=NULL;
61 punt->down=NULL;
62 punt->right=NULL;
64 return punt;
68 /******************************************************************/
69 /* Function : _asn1_find_left */
70 /* Description: returns the NODE_ASN element with RIGHT field that*/
71 /* points the element NODE. */
72 /* Parameters: */
73 /* node: NODE_ASN element pointer. */
74 /* Return: NULL if not found. */
75 /******************************************************************/
76 node_asn *
77 _asn1_find_left(node_asn *node)
79 if((node==NULL) || (node->left==NULL) ||
80 (node->left->down==node)) return NULL;
82 return node->left;
86 asn1_retCode
87 _asn1_create_static_structure(ASN1_TYPE pointer,char* output_file_name,char *vector_name)
89 FILE *file;
90 node_asn *p;
91 unsigned long t;
93 file=fopen( output_file_name,"w");
95 if(file==NULL) return ASN1_FILE_NOT_FOUND;
97 fprintf(file,"\n#include \"libtasn1.h\"\n\n");
98 fprintf(file,"const ASN1_ARRAY_TYPE %s[]={\n",vector_name);
100 p=pointer;
102 while(p){
103 fprintf(file," {");
105 if(p->name) fprintf(file,"\"%s\",",p->name);
106 else fprintf(file,"0,");
108 t=p->type;
109 if(p->down) t|=CONST_DOWN;
110 if(p->right) t|=CONST_RIGHT;
112 fprintf(file,"%lu,",t);
114 if(p->value) fprintf(file,"\"%s\"},\n",p->value);
115 else fprintf(file,"0},\n");
117 if(p->down){
118 p=p->down;
120 else if(p->right){
121 p=p->right;
123 else{
124 while(1){
125 p=_asn1_find_up(p);
126 if(p==pointer){
127 p=NULL;
128 break;
130 if(p->right){
131 p=p->right;
132 break;
138 fprintf(file," {0,0,0}\n};\n");
140 fclose(file);
142 return ASN1_SUCCESS;
147 * asn1_array2tree - Creates the structures needed to manage the ASN1 definitions.
148 * @array: specify the array that contains ASN.1 declarations
149 * @definitions: return the pointer to the structure created by
150 * *ARRAY ASN.1 declarations
151 * @errorDescription: return the error description.
153 * Creates the structures needed to manage the ASN.1 definitions.
154 * @array is a vector created by asn1_parser2array().
156 * Returns:
158 * ASN1_SUCCESS: Structure created correctly.
160 * ASN1_ELEMENT_NOT_EMPTY: *@definitions not ASN1_TYPE_EMPTY.
162 * ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
163 * is not defined (see @errorDescription for more information).
165 * ASN1_ARRAY_ERROR: The array pointed by @array is wrong.
167 asn1_retCode
168 asn1_array2tree(const ASN1_ARRAY_TYPE *array,ASN1_TYPE *definitions,
169 char *errorDescription)
171 node_asn *p,*p_last=NULL;
172 unsigned long k;
173 int move;
174 asn1_retCode result;
177 if(*definitions != ASN1_TYPE_EMPTY)
178 return ASN1_ELEMENT_NOT_EMPTY;
180 move=UP;
182 k=0;
183 while(array[k].value || array[k].type || array[k].name){
184 p=_asn1_add_node(array[k].type&(~CONST_DOWN));
185 if(array[k].name) _asn1_set_name(p,array[k].name);
186 if(array[k].value) _asn1_set_value(p,array[k].value,
187 strlen(array[k].value)+1);
189 if(*definitions==NULL) *definitions=p;
191 if(move==DOWN) _asn1_set_down(p_last,p);
192 else if(move==RIGHT) _asn1_set_right(p_last,p);
194 p_last=p;
196 if(array[k].type&CONST_DOWN) move=DOWN;
197 else if(array[k].type&CONST_RIGHT) move=RIGHT;
198 else{
199 while(1){
200 if(p_last==*definitions) break;
202 p_last= _asn1_find_up(p_last);
204 if(p_last==NULL) break;
206 if(p_last->type&CONST_RIGHT){
207 p_last->type&=~CONST_RIGHT;
208 move=RIGHT;
209 break;
211 } /* while */
213 k++;
214 } /* while */
216 if(p_last==*definitions){
217 result=_asn1_check_identifier(*definitions);
218 if(result==ASN1_SUCCESS){
219 _asn1_change_integer_value(*definitions);
220 _asn1_expand_object_id(*definitions);
223 else{
224 result=ASN1_ARRAY_ERROR;
227 if (errorDescription!=NULL) {
228 if(result==ASN1_IDENTIFIER_NOT_FOUND) {
229 Estrcpy(errorDescription,":: identifier '");
230 Estrcat(errorDescription,_asn1_identifierMissing);
231 Estrcat(errorDescription,"' not found");
233 else
234 errorDescription[0]=0;
237 if(result != ASN1_SUCCESS){
238 _asn1_delete_list_and_nodes();
239 *definitions=ASN1_TYPE_EMPTY;
241 else
242 _asn1_delete_list();
244 return result;
249 * asn1_delete_structure - Deletes the structure pointed by *ROOT.
250 * @structure: pointer to the structure that you want to delete.
252 * Deletes the structure *@structure. At the end, *@structure is set
253 * to ASN1_TYPE_EMPTY.
255 * Returns:
257 * ASN1_SUCCESS: Everything OK.
259 * ASN1_ELEMENT_NOT_FOUND: *@structure was ASN1_TYPE_EMPTY.
262 asn1_retCode
263 asn1_delete_structure(ASN1_TYPE *structure)
265 node_asn *p,*p2,*p3;
267 if(*structure==ASN1_TYPE_EMPTY) return ASN1_ELEMENT_NOT_FOUND;
269 p=*structure;
270 while(p){
271 if(p->down){
272 p=p->down;
274 else{ /* no down */
275 p2=p->right;
276 if(p!=*structure){
277 p3=_asn1_find_up(p);
278 _asn1_set_down(p3,p2);
279 _asn1_remove_node(p);
280 p=p3;
282 else{ /* p==root */
283 p3=_asn1_find_left(p);
284 if(!p3){
285 p3=_asn1_find_up(p);
286 if(p3) _asn1_set_down(p3,p2);
287 else{
288 if(p->right) p->right->left=NULL;
291 else _asn1_set_right(p3,p2);
292 _asn1_remove_node(p);
293 p=NULL;
298 *structure=ASN1_TYPE_EMPTY;
299 return ASN1_SUCCESS;
304 * asn1_delete_element - Deletes the element of a structure.
305 * @structure: pointer to the structure that contains the element you
306 * want to delete.
307 * @element_name: element's name you want to delete.
309 * Deletes the element named *@element_name inside *@structure.
311 * Returns:
313 * ASN1_SUCCESS: Everything OK.
315 * ASN1_ELEMENT_NOT_FOUND: The name element was not found.
318 asn1_retCode
319 asn1_delete_element(ASN1_TYPE structure,const char *element_name)
321 node_asn *p2,*p3,*source_node;
323 source_node=_asn1_find_node(structure,element_name);
325 if(source_node==ASN1_TYPE_EMPTY) return ASN1_ELEMENT_NOT_FOUND;
327 p2=source_node->right;
328 p3=_asn1_find_left(source_node);
329 if(!p3){
330 p3=_asn1_find_up(source_node);
331 if(p3)
332 _asn1_set_down(p3,p2);
333 else
334 if(source_node->right) source_node->right->left=NULL;
336 else _asn1_set_right(p3,p2);
338 return asn1_delete_structure(&source_node);
342 node_asn *
343 _asn1_copy_structure3(node_asn *source_node)
345 node_asn *dest_node,*p_s,*p_d,*p_d_prev;
346 int len,len2,move, tlen;
348 if(source_node==NULL) return NULL;
350 dest_node=_asn1_add_node_only(source_node->type);
352 p_s=source_node;
353 p_d=dest_node;
355 move=DOWN;
358 if(move!=UP){
359 if(p_s->name) _asn1_set_name(p_d,p_s->name);
360 if(p_s->value){
361 switch(type_field(p_s->type)){
362 case TYPE_OCTET_STRING: case TYPE_BIT_STRING: case TYPE_GENERALSTRING:
363 case TYPE_INTEGER:
364 len2=-1;
365 len=_asn1_get_length_der(p_s->value,&len2);
366 _asn1_set_value(p_d,p_s->value,len+len2);
367 break;
368 default:
369 tlen = strlen(p_s->value);
371 if (tlen > 0)
372 _asn1_set_value(p_d,p_s->value,tlen+1);
375 move=DOWN;
377 else move=RIGHT;
379 if(move==DOWN){
380 if(p_s->down){
381 p_s=p_s->down;
382 p_d_prev=p_d;
383 p_d=_asn1_add_node_only(p_s->type);
384 _asn1_set_down(p_d_prev,p_d);
386 else move=RIGHT;
389 if(p_s==source_node) break;
391 if(move==RIGHT){
392 if(p_s->right){
393 p_s=p_s->right;
394 p_d_prev=p_d;
395 p_d=_asn1_add_node_only(p_s->type);
396 _asn1_set_right(p_d_prev,p_d);
398 else move=UP;
400 if(move==UP){
401 p_s=_asn1_find_up(p_s);
402 p_d=_asn1_find_up(p_d);
404 }while(p_s!=source_node);
406 return dest_node;
410 node_asn *
411 _asn1_copy_structure2(node_asn *root,const char *source_name)
413 node_asn *source_node;
415 source_node=_asn1_find_node(root,source_name);
417 return _asn1_copy_structure3(source_node);
422 asn1_retCode
423 _asn1_type_choice_config(node_asn *node)
425 node_asn *p,*p2,*p3,*p4;
426 int move,tlen;
428 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
430 p=node;
431 move=DOWN;
433 while(!((p==node) && (move==UP))){
434 if(move!=UP){
435 if((type_field(p->type)==TYPE_CHOICE) &&
436 (p->type&CONST_TAG)){
437 p2=p->down;
438 while(p2){
439 if(type_field(p2->type)!=TYPE_TAG){
440 p2->type|=CONST_TAG;
441 p3=_asn1_find_left(p2);
442 while(p3){
443 if(type_field(p3->type)==TYPE_TAG){
444 p4=_asn1_add_node_only(p3->type);
445 tlen = strlen(p3->value);
446 if (tlen > 0)
447 _asn1_set_value(p4,p3->value,tlen+1);
448 _asn1_set_right(p4,p2->down);
449 _asn1_set_down(p2,p4);
451 p3=_asn1_find_left(p3);
454 p2=p2->right;
456 p->type&=~(CONST_TAG);
457 p2=p->down;
458 while(p2){
459 p3=p2->right;
460 if(type_field(p2->type)==TYPE_TAG) asn1_delete_structure(&p2);
461 p2=p3;
464 move=DOWN;
466 else move=RIGHT;
468 if(move==DOWN){
469 if(p->down) p=p->down;
470 else move=RIGHT;
473 if(p==node) {move=UP; continue;}
475 if(move==RIGHT){
476 if(p->right) p=p->right;
477 else move=UP;
479 if(move==UP) p=_asn1_find_up(p);
482 return ASN1_SUCCESS;
486 asn1_retCode
487 _asn1_expand_identifier(node_asn **node,node_asn *root)
489 node_asn *p,*p2,*p3;
490 char name2[MAX_NAME_SIZE+2];
491 int move;
493 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
495 p=*node;
496 move=DOWN;
498 while(!((p==*node) && (move==UP))){
499 if(move!=UP){
500 if(type_field(p->type)==TYPE_IDENTIFIER){
501 _asn1_str_cpy(name2, sizeof(name2), root->name);
502 _asn1_str_cat(name2, sizeof(name2), ".");
503 _asn1_str_cat(name2, sizeof(name2), p->value);
504 p2=_asn1_copy_structure2(root,name2);
505 if(p2==NULL){
506 return ASN1_IDENTIFIER_NOT_FOUND;
508 _asn1_set_name(p2,p->name);
509 p2->right=p->right;
510 p2->left=p->left;
511 if(p->right) p->right->left=p2;
512 p3=p->down;
513 if(p3){
514 while(p3->right) p3=p3->right;
515 _asn1_set_right(p3,p2->down);
516 _asn1_set_down(p2,p->down);
519 p3=_asn1_find_left(p);
520 if(p3) _asn1_set_right(p3,p2);
521 else{
522 p3=_asn1_find_up(p);
523 if(p3) _asn1_set_down(p3,p2);
524 else {
525 p2->left=NULL;
529 if(p->type & CONST_SIZE) p2->type|=CONST_SIZE;
530 if(p->type & CONST_TAG) p2->type|=CONST_TAG;
531 if(p->type & CONST_OPTION) p2->type|=CONST_OPTION;
532 if(p->type & CONST_DEFAULT) p2->type|=CONST_DEFAULT;
533 if(p->type & CONST_SET) p2->type|=CONST_SET;
534 if(p->type & CONST_NOT_USED) p2->type|=CONST_NOT_USED;
536 if(p==*node) *node=p2;
537 _asn1_remove_node(p);
538 p=p2;
539 move=DOWN;
540 continue;
542 move=DOWN;
544 else move=RIGHT;
546 if(move==DOWN){
547 if(p->down) p=p->down;
548 else move=RIGHT;
551 if(p==*node) {move=UP; continue;}
553 if(move==RIGHT){
554 if(p->right) p=p->right;
555 else move=UP;
557 if(move==UP) p=_asn1_find_up(p);
560 return ASN1_SUCCESS;
565 * asn1_create_element - Creates a structure of type SOURCE_NAME.
566 * @definitions: pointer to the structure returned by "parser_asn1" function
567 * @source_name: the name of the type of the new structure (must be
568 * inside p_structure).
569 * @element: pointer to the structure created.
571 * Creates a structure of type @source_name.
573 * Example: using "pkix.asn"
574 * result=asn1_create_structure(cert_def,"PKIX1.Certificate",certptr);
576 * Returns:
578 * ASN1_SUCCESS: Creation OK.
580 * ASN1_ELEMENT_NOT_FOUND: SOURCE_NAME isn't known
582 asn1_retCode
583 asn1_create_element(ASN1_TYPE definitions,const char *source_name,
584 ASN1_TYPE *element)
586 node_asn *dest_node;
587 int res;
589 dest_node=_asn1_copy_structure2(definitions,source_name);
591 if(dest_node==NULL) return ASN1_ELEMENT_NOT_FOUND;
593 _asn1_set_name(dest_node,"");
595 res=_asn1_expand_identifier(&dest_node,definitions);
596 _asn1_type_choice_config(dest_node);
598 *element=dest_node;
600 return res;
605 * asn1_print_structure - Prints on the standard output the structure's tree
606 * @out: pointer to the output file (e.g. stdout).
607 * @structure: pointer to the structure that you want to visit.
608 * @name: an element of the structure
609 * @mode: specify how much of the structure to print, can be
610 * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE,
611 * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL.
613 * Prints on the @out file descriptor the structure's tree starting
614 * from the @name element inside the structure @structure.
616 void
617 asn1_print_structure(FILE *out,ASN1_TYPE structure,const char *name,int mode)
619 node_asn *p,*root;
620 int k,indent=0,len,len2,len3;
622 if(out==NULL) return;
624 root=_asn1_find_node(structure,name);
626 if(root==NULL) return;
628 p=root;
629 while(p){
630 if(mode == ASN1_PRINT_ALL){
631 for(k=0;k<indent;k++)fprintf(out," ");
632 fprintf(out,"name:");
633 if(p->name) fprintf(out,"%s ",p->name);
634 else fprintf(out,"NULL ");
636 else{
637 switch(type_field(p->type)){
638 case TYPE_CONSTANT:
639 case TYPE_TAG:
640 case TYPE_SIZE:
641 break;
642 default:
643 for(k=0;k<indent;k++)fprintf(out," ");
644 fprintf(out,"name:");
645 if(p->name) fprintf(out,"%s ",p->name);
646 else fprintf(out,"NULL ");
650 if(mode != ASN1_PRINT_NAME){
651 switch(type_field(p->type)){
652 case TYPE_CONSTANT:
653 if(mode == ASN1_PRINT_ALL)
654 fprintf(out,"type:CONST");break;
655 case TYPE_TAG:
656 if(mode == ASN1_PRINT_ALL)
657 fprintf(out,"type:TAG");break;
658 case TYPE_SIZE:
659 if(mode == ASN1_PRINT_ALL)
660 fprintf(out,"type:SIZE");break;
661 case TYPE_DEFAULT:
662 fprintf(out,"type:DEFAULT");break;
663 case TYPE_NULL:
664 fprintf(out,"type:NULL");break;
665 case TYPE_IDENTIFIER:
666 fprintf(out,"type:IDENTIFIER");break;
667 case TYPE_INTEGER:
668 fprintf(out,"type:INTEGER");break;
669 case TYPE_ENUMERATED:
670 fprintf(out,"type:ENUMERATED");break;
671 case TYPE_TIME:
672 fprintf(out,"type:TIME");break;
673 case TYPE_BOOLEAN:
674 fprintf(out,"type:BOOLEAN");break;
675 case TYPE_SEQUENCE:
676 fprintf(out,"type:SEQUENCE");break;
677 case TYPE_BIT_STRING:
678 fprintf(out,"type:BIT_STR");break;
679 case TYPE_OCTET_STRING:
680 fprintf(out,"type:OCT_STR");break;
681 case TYPE_GENERALSTRING:
682 fprintf(out,"type:GENERALSTRING");break;
683 case TYPE_SEQUENCE_OF:
684 fprintf(out,"type:SEQ_OF");break;
685 case TYPE_OBJECT_ID:
686 fprintf(out,"type:OBJ_ID");break;
687 case TYPE_ANY:
688 fprintf(out,"type:ANY");break;
689 case TYPE_SET:
690 fprintf(out,"type:SET");break;
691 case TYPE_SET_OF:
692 fprintf(out,"type:SET_OF");break;
693 case TYPE_CHOICE:
694 fprintf(out,"type:CHOICE");break;
695 case TYPE_DEFINITIONS:
696 fprintf(out,"type:DEFINITIONS");break;
697 default:
698 break;
702 if((mode == ASN1_PRINT_NAME_TYPE_VALUE) ||
703 (mode == ASN1_PRINT_ALL)){
704 switch(type_field(p->type)){
705 case TYPE_CONSTANT:
706 if(mode == ASN1_PRINT_ALL)
707 if(p->value) fprintf(out," value:%s",p->value);
708 break;
709 case TYPE_TAG:
710 if(mode == ASN1_PRINT_ALL)
711 if (p->value) fprintf(out," value:%s",p->value);
712 break;
713 case TYPE_SIZE:
714 if(mode == ASN1_PRINT_ALL)
715 if(p->value) fprintf(out," value:%s",p->value);
716 break;
717 case TYPE_DEFAULT:
718 if(p->value) fprintf(out," value:%s",p->value);
719 else if(p->type & CONST_TRUE) fprintf(out," value:TRUE");
720 else if(p->type & CONST_FALSE) fprintf(out," value:FALSE");
721 break;
722 case TYPE_IDENTIFIER:
723 if(p->value) fprintf(out," value:%s",p->value);
724 break;
725 case TYPE_INTEGER:
726 if(p->value){
727 len2=-1;
728 len=_asn1_get_length_der(p->value,&len2);
729 fprintf(out," value:0x");
730 for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
732 break;
733 case TYPE_ENUMERATED:
734 if(p->value){
735 len2=-1;
736 len=_asn1_get_length_der(p->value,&len2);
737 fprintf(out," value:0x");
738 for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
740 break;
741 case TYPE_TIME:
742 if(p->value) fprintf(out," value:%s",p->value);
743 break;
744 case TYPE_BOOLEAN:
745 if(p->value){
746 if(p->value[0]=='T') fprintf(out," value:TRUE");
747 else if(p->value[0]=='F') fprintf(out," value:FALSE");
749 break;
750 case TYPE_BIT_STRING:
751 if(p->value){
752 len2=-1;
753 len=_asn1_get_length_der(p->value,&len2);
754 fprintf(out," value(%i):",(len-1)*8-(p->value[len2]));
755 for(k=1;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
757 break;
758 case TYPE_OCTET_STRING:
759 if(p->value){
760 len2=-1;
761 len=_asn1_get_length_der(p->value,&len2);
762 fprintf(out," value:");
763 for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
765 break;
766 case TYPE_GENERALSTRING:
767 if(p->value){
768 len2=-1;
769 len=_asn1_get_length_der(p->value,&len2);
770 fprintf(out," value:");
771 for(k=0;k<len;k++) fprintf(out,"%02x",(p->value)[k+len2]);
773 break;
774 case TYPE_OBJECT_ID:
775 if(p->value) fprintf(out," value:%s",p->value);
776 break;
777 case TYPE_ANY:
778 if(p->value){
779 len3=-1;
780 len2=_asn1_get_length_der(p->value,&len3);
781 fprintf(out," value:");
782 for(k=0;k<len2;k++) fprintf(out,"%02x",(p->value)[k+len3]);
784 break;
785 case TYPE_SET:
786 case TYPE_SET_OF:
787 case TYPE_CHOICE:
788 case TYPE_DEFINITIONS:
789 case TYPE_SEQUENCE_OF:
790 case TYPE_SEQUENCE:
791 case TYPE_NULL:
792 break;
793 default:
794 break;
798 if(mode==ASN1_PRINT_ALL){
799 if(p->type&0x1FFFFF00){
800 fprintf(out," attr:");
801 if(p->type & CONST_UNIVERSAL) fprintf(out,"UNIVERSAL,");
802 if(p->type & CONST_PRIVATE) fprintf(out,"PRIVATE,");
803 if(p->type & CONST_APPLICATION) fprintf(out,"APPLICATION,");
804 if(p->type & CONST_EXPLICIT) fprintf(out,"EXPLICIT,");
805 if(p->type & CONST_IMPLICIT) fprintf(out,"IMPLICIT,");
806 if(p->type & CONST_TAG) fprintf(out,"TAG,");
807 if(p->type & CONST_DEFAULT) fprintf(out,"DEFAULT,");
808 if(p->type & CONST_TRUE) fprintf(out,"TRUE,");
809 if(p->type & CONST_FALSE) fprintf(out,"FALSE,");
810 if(p->type & CONST_LIST) fprintf(out,"LIST,");
811 if(p->type & CONST_MIN_MAX) fprintf(out,"MIN_MAX,");
812 if(p->type & CONST_OPTION) fprintf(out,"OPTION,");
813 if(p->type & CONST_1_PARAM) fprintf(out,"1_PARAM,");
814 if(p->type & CONST_SIZE) fprintf(out,"SIZE,");
815 if(p->type & CONST_DEFINED_BY) fprintf(out,"DEF_BY,");
816 if(p->type & CONST_GENERALIZED) fprintf(out,"GENERALIZED,");
817 if(p->type & CONST_UTC) fprintf(out,"UTC,");
818 if(p->type & CONST_SET) fprintf(out,"SET,");
819 if(p->type & CONST_NOT_USED) fprintf(out,"NOT_USED,");
820 if(p->type & CONST_ASSIGN) fprintf(out,"ASSIGNMENT,");
824 if(mode == ASN1_PRINT_ALL){
825 fprintf(out,"\n");
827 else{
828 switch(type_field(p->type)){
829 case TYPE_CONSTANT:
830 case TYPE_TAG:
831 case TYPE_SIZE:
832 break;
833 default:
834 fprintf(out,"\n");
838 if(p->down){
839 p=p->down;
840 indent+=2;
842 else if(p==root){
843 p=NULL;
844 break;
846 else if(p->right) p=p->right;
847 else{
848 while(1){
849 p=_asn1_find_up(p);
850 if(p==root){
851 p=NULL;
852 break;
854 indent-=2;
855 if(p->right){
856 p=p->right;
857 break;
867 * asn1_number_of_elements - Counts the number of elements of a structure.
868 * @element: pointer to the root of an ASN1 structure.
869 * @name: the name of a sub-structure of ROOT.
870 * @num: pointer to an integer where the result will be stored
872 * Counts the number of elements of a sub-structure called NAME with
873 * names equal to "?1","?2", ...
875 * Returns:
877 * ASN1_SUCCESS: Creation OK.
879 * ASN1_ELEMENT_NOT_FOUND: NAME isn't known.
881 * ASN1_GENERIC_ERROR: Pointer num equal to NULL.
884 asn1_retCode
885 asn1_number_of_elements(ASN1_TYPE element,const char *name,int *num)
887 node_asn *node,*p;
889 if(num==NULL) return ASN1_GENERIC_ERROR;
891 *num=0;
893 node=_asn1_find_node(element,name);
894 if(node==NULL) return ASN1_ELEMENT_NOT_FOUND;
896 p=node->down;
898 while(p){
899 if((p->name) && (p->name[0]=='?')) (*num)++;
900 p=p->right;
903 return ASN1_SUCCESS;
908 * asn1_find_structure_from_oid - Locate structure defined by a specific OID.
909 * @definitions: ASN1 definitions
910 * @oidValue: value of the OID to search (e.g. "1.2.3.4").
912 * Search the structure that is defined just after an OID definition.
914 * Returns: NULL when OIDVALUE not found, otherwise the pointer to a
915 * constant string that contains the element name defined just
916 * after the OID.
919 const char*
920 asn1_find_structure_from_oid (ASN1_TYPE definitions,
921 const char *oidValue)
923 char definitionsName[MAX_NAME_SIZE],name[2*MAX_NAME_SIZE+1];
924 char value[MAX_NAME_SIZE];
925 ASN1_TYPE p;
926 int len;
927 asn1_retCode result;
929 if((definitions==ASN1_TYPE_EMPTY) || (oidValue==NULL))
930 return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
933 strcpy(definitionsName,definitions->name);
934 strcat(definitionsName,".");
936 /* search the OBJECT_ID into definitions */
937 p=definitions->down;
938 while(p){
939 if((type_field(p->type)==TYPE_OBJECT_ID) &&
940 (p->type & CONST_ASSIGN)){
941 strcpy(name,definitionsName);
942 strcat(name,p->name);
944 len=MAX_NAME_SIZE;
945 result=asn1_read_value(definitions,name,value,&len);
947 if((result == ASN1_SUCCESS) && (!strcmp(oidValue,value))){
948 p=p->right;
949 if(p==NULL) /* reach the end of ASN1 definitions */
950 return NULL; /* ASN1_ELEMENT_NOT_FOUND; */
952 return p->name;
955 p=p->right;
958 return NULL; /* ASN1_ELEMENT_NOT_FOUND; */