1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <assert.h>
6 
7 #include "asn1parser.h"
8 
9 /*
10  * Construct a new empty reference.
11  */
12 asn1p_ref_t *
asn1p_ref_new(int _lineno)13 asn1p_ref_new(int _lineno) {
14 	asn1p_ref_t *ref;
15 
16 	ref = calloc(1, sizeof *ref);
17 	if(ref) {
18 		ref->_lineno = _lineno;
19 	}
20 
21 	return ref;
22 }
23 
24 void
asn1p_ref_free(asn1p_ref_t * ref)25 asn1p_ref_free(asn1p_ref_t *ref) {
26 	if(ref) {
27 		if(ref->components) {
28 			int i = ref->comp_count;
29 			while(i--) {
30 				if(ref->components[i].name)
31 				free(ref->components[i].name);
32 				ref->components[i].name = 0;
33 			}
34 			free(ref->components);
35 			ref->components = 0;
36 		}
37 
38 		free(ref);
39 	}
40 }
41 
42 static enum asn1p_ref_lex_type_e
asn1p_ref_name2lextype(char * name)43 asn1p_ref_name2lextype(char *name) {
44 	enum asn1p_ref_lex_type_e lex_type;
45 	int has_lowercase = 0;
46 
47 	if(*name == '&') {
48 		if(name[1] >= 'A' && name[1] <= 'Z') {
49 			lex_type = RLT_AmpUppercase;
50 		} else {
51 			lex_type = RLT_Amplowercase;
52 		}
53 	} else if(*name >= 'A' && *name <= 'Z') {
54 		char *p;
55 
56 		for(p = name; *p; p++) {
57 			if(*p >= 'a' && *p <= 'z') {
58 				has_lowercase = 1;
59 				break;
60 			}
61 		}
62 
63 		if(has_lowercase) {
64 			lex_type = RLT_Uppercase;
65 		} else {
66 			lex_type = RLT_CAPITALS;
67 		}
68 	} else if(*name == '@') {
69 		if(name[1] == '.')
70 			lex_type = RLT_AtDotlowercase;
71 		else
72 			lex_type = RLT_Atlowercase;
73 	} else {
74 		lex_type = RLT_lowercase;
75 	}
76 
77 	return lex_type;
78 }
79 
80 int
asn1p_ref_add_component(asn1p_ref_t * ref,char * name,enum asn1p_ref_lex_type_e lex_type)81 asn1p_ref_add_component(asn1p_ref_t *ref, char *name, enum asn1p_ref_lex_type_e lex_type) {
82 
83 	if(!ref || !name
84 	|| (int)lex_type < RLT_UNKNOWN || lex_type >= RLT_MAX) {
85 		errno = EINVAL;
86 		return -1;
87 	}
88 
89 	if(ref->comp_count == ref->comp_size) {
90 		int newsize = ref->comp_size?(ref->comp_size<<2):4;
91 		void *p = realloc(ref->components,
92 			newsize * sizeof(ref->components[0]));
93 		if(p) {
94 			ref->components = p;
95 			ref->comp_size = newsize;
96 		} else {
97 			return -1;
98 		}
99 
100 	}
101 
102 	if(lex_type == RLT_UNKNOWN) {
103 		lex_type = asn1p_ref_name2lextype(name);
104 	} else {
105 		assert(lex_type == asn1p_ref_name2lextype(name));
106 	}
107 
108 	ref->components[ref->comp_count].name = strdup(name);
109 	ref->components[ref->comp_count].lex_type = lex_type;
110 	if(ref->components[ref->comp_count].name) {
111 		ref->comp_count++;
112 		return 0;
113 	} else {
114 		return -1;
115 	}
116 }
117 
118 asn1p_ref_t *
asn1p_ref_clone(asn1p_ref_t * ref)119 asn1p_ref_clone(asn1p_ref_t *ref) {
120 	asn1p_ref_t *newref;
121 
122 	newref = asn1p_ref_new(ref->_lineno);
123 	if(newref) {
124 		int i;
125 		for(i = 0; i < ref->comp_count; i++) {
126 			if(asn1p_ref_add_component(newref,
127 				ref->components[i].name,
128 				ref->components[i].lex_type
129 			)) {
130 				asn1p_ref_free(newref);
131 				newref = NULL;
132 				break;
133 			}
134 		}
135 	}
136 
137 	return newref;
138 }
139