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