#include #include #include #include #include #include "asn1parser.h" /* * Construct a new empty reference. */ asn1p_ref_t * asn1p_ref_new(int _lineno, asn1p_module_t *mod) { asn1p_ref_t *ref; ref = calloc(1, sizeof *ref); assert(ref); asn1p_ref_set_source(ref, mod, _lineno); return ref; } void asn1p_ref_free(asn1p_ref_t *ref) { if(ref) { if(ref->components) { size_t i = ref->comp_count; while(i--) { free(ref->components[i].name); ref->components[i].name = 0; } free(ref->components); ref->components = 0; } free(ref); } } void asn1p_ref_set_source(asn1p_ref_t *ref, asn1p_module_t *module, int lineno) { if(ref) { ref->module = module; ref->_lineno = lineno; } } static enum asn1p_ref_lex_type_e asn1p_ref_name2lextype(const 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') { const 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, const 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, ref->module); if(newref) { for(size_t 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; } int asn1p_ref_compare(const asn1p_ref_t *a, const asn1p_ref_t *b) { if(a->comp_count != b->comp_count) return -1; if(a->module != b->module) return -1; for(size_t i = 0; i < a->comp_count; i++) { if(a->components[i].lex_type != b->components[i].lex_type || strcmp(a->components[i].name, b->components[i].name) != 0) { return -1; } } return 0; } const char * asn1p_ref_string(const asn1p_ref_t *ref) { static char static_buf[32]; static char *buf = static_buf; static size_t buf_size = sizeof(static_buf); char *p = buf; for(size_t i = 0; i < ref->comp_count; i++) { size_t space = buf_size - (p - buf); int ret = snprintf(p, space, "%s%s", i ? "." : "", ref->components[i].name); if(ret < 0 || (size_t)ret >= space) { i--; char *tmp = malloc(buf_size * 2 + 1); assert(tmp); size_t p_offset = p - buf; memcpy(tmp, buf, (p - buf)); if(buf != static_buf) free(buf); buf_size *= 2; buf = tmp; p = tmp + p_offset; } else { p += ret; } } *p = '\0'; return buf; }