blob: af6f6bb2627d84bc1d1c86a551337e6a7bf8b8c7 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#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 */
12asn1p_ref_t *
13asn1p_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
24void
25asn1p_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
42static enum asn1p_ref_lex_type_e
43asn1p_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
80int
81asn1p_ref_add_component(asn1p_ref_t *ref, char *name, enum asn1p_ref_lex_type_e lex_type) {
82
Lev Walkind9bd7752004-06-05 08:17:50 +000083 if(!ref || !name
84 || (int)lex_type < RLT_UNKNOWN || lex_type >= RLT_MAX) {
Lev Walkinf15320b2004-06-03 03:38:44 +000085 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
118asn1p_ref_t *
119asn1p_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}