mirror of https://gerrit.osmocom.org/asn1c
184 lines
3.2 KiB
C
184 lines
3.2 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
|
|
#include "asn1parser.h"
|
|
#include "asn1p_list.h"
|
|
|
|
int asn1p_parse(void **param);
|
|
|
|
void *asn1p__scan_bytes(const char *, int len);
|
|
void *asn1p__delete_buffer(void *);
|
|
void *asn1p_restart(FILE *);
|
|
|
|
extern int asn1p_lineno;
|
|
|
|
static int _asn1p_set_flags(enum asn1p_flags flags);
|
|
static int _asn1p_fix_modules(asn1p_t *a, const char *fname);
|
|
|
|
/*
|
|
* Parse the given buffer.
|
|
*/
|
|
asn1p_t *
|
|
asn1p_parse_buffer(const char *buffer, int size /* = -1 */, const char *debug_filename, int initial_lineno, enum asn1p_flags flags) {
|
|
asn1p_t *a = 0;
|
|
void *ap;
|
|
void *ybuf;
|
|
int ret;
|
|
|
|
if(_asn1p_set_flags(flags)) {
|
|
/* EINVAL */
|
|
return 0;
|
|
}
|
|
|
|
if(size < 0)
|
|
size = (int)strlen(buffer);
|
|
|
|
ybuf = asn1p__scan_bytes(buffer, size);
|
|
if(!ybuf) {
|
|
assert(ybuf);
|
|
return 0;
|
|
}
|
|
|
|
asn1p_lineno = initial_lineno;
|
|
|
|
ap = (void *)&a;
|
|
asn1p_parse_debug_filename = debug_filename;
|
|
ret = asn1p_parse(ap);
|
|
asn1p_parse_debug_filename = NULL;
|
|
|
|
asn1p__delete_buffer(ybuf);
|
|
|
|
if(ret == 0) {
|
|
assert(a);
|
|
if(_asn1p_fix_modules(a, "-")) {
|
|
asn1p_delete(a);
|
|
return NULL; /* FIXME: destroy (a) */
|
|
}
|
|
} else if(a) {
|
|
asn1p_delete(a);
|
|
a = NULL;
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
|
|
/*
|
|
* Parse the file identified by its name.
|
|
*/
|
|
asn1p_t *
|
|
asn1p_parse_file(const char *filename, enum asn1p_flags flags) {
|
|
#ifndef _WIN32
|
|
struct stat sb;
|
|
#endif
|
|
asn1p_t *a = 0;
|
|
void *ap;
|
|
FILE *fp;
|
|
int ret;
|
|
|
|
if(_asn1p_set_flags(flags)) {
|
|
/* EINVAL */
|
|
return 0;
|
|
}
|
|
|
|
fp = fopen(filename, "r");
|
|
if(fp == NULL) {
|
|
perror(filename);
|
|
return NULL;
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
if(fstat(fileno(fp), &sb)
|
|
|| !S_ISREG(sb.st_mode)) {
|
|
fclose(fp);
|
|
fprintf(stderr, "%s file not recognized: Bad file format\n",
|
|
filename);
|
|
errno = EINVAL;
|
|
return NULL;
|
|
}
|
|
#endif /* _WIN32 */
|
|
|
|
asn1p_lineno = 1;
|
|
|
|
asn1p_restart(fp);
|
|
|
|
ap = (void *)&a;
|
|
asn1p_parse_debug_filename = filename;
|
|
ret = asn1p_parse(ap);
|
|
asn1p_parse_debug_filename = NULL;
|
|
|
|
fclose(fp);
|
|
|
|
if(ret == 0) {
|
|
assert(a);
|
|
if(_asn1p_fix_modules(a, filename)) {
|
|
asn1p_delete(a);
|
|
return NULL; /* FIXME: destroy (a) */
|
|
}
|
|
} else if(a) {
|
|
asn1p_delete(a);
|
|
a = NULL;
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
extern int asn1p_lexer_types_year;
|
|
extern int asn1p_lexer_constructs_year;
|
|
extern int asn1p_lexer_extended_values;
|
|
extern int asn1p__flex_debug;
|
|
extern int asn1p_debug;
|
|
|
|
static int
|
|
_asn1p_set_flags(enum asn1p_flags flags) {
|
|
|
|
asn1p_lexer_types_year = 0;
|
|
asn1p_lexer_constructs_year = 0;
|
|
asn1p__flex_debug = 0;
|
|
asn1p_debug = 0;
|
|
|
|
if(flags & A1P_DEBUG_LEXER) {
|
|
flags &= ~A1P_DEBUG_LEXER;
|
|
asn1p__flex_debug = 1;
|
|
}
|
|
|
|
if(flags & A1P_DEBUG_PARSER) {
|
|
flags &= ~A1P_DEBUG_PARSER;
|
|
asn1p_debug = 1;
|
|
}
|
|
|
|
if(flags & A1P_EXTENDED_VALUES) {
|
|
flags &= ~A1P_EXTENDED_VALUES;
|
|
asn1p_lexer_extended_values = 1;
|
|
} else {
|
|
asn1p_lexer_extended_values = 0;
|
|
}
|
|
|
|
/*
|
|
* Check that we haven't missed an unknown flag.
|
|
*/
|
|
if(flags) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_asn1p_fix_modules(asn1p_t *a, const char *fname) {
|
|
asn1p_module_t *mod;
|
|
TQ_FOR(mod, &(a->modules), mod_next) {
|
|
mod->source_file_name = strdup(fname);
|
|
if(mod->source_file_name == NULL)
|
|
return -1;
|
|
mod->asn1p = a;
|
|
}
|
|
return 0;
|
|
}
|