blob: c820cc4aead52144296d4b470b55307f24e8096e [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include <stdio.h>
Lev Walkinb1107e62004-09-27 20:54:44 +00002#include <string.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00003#include <sys/types.h>
4#include <sys/stat.h>
5#include <assert.h>
6#include <errno.h>
7
8#include "asn1parser.h"
9#include "asn1p_list.h"
10
11int asn1p_parse(void **param);
12
13void *asn1p__scan_bytes(const char *, int len);
14void *asn1p__delete_buffer(void *);
15void *asn1p_restart(FILE *);
16
17extern int asn1p_lineno;
18
19static int _asn1p_set_flags(enum asn1p_flags flags);
Lev Walkin070a52d2004-08-22 03:19:54 +000020static int _asn1p_fix_modules(asn1p_t *a, const char *fname);
Lev Walkinf15320b2004-06-03 03:38:44 +000021
22/*
23 * Parse the given buffer.
24 */
25asn1p_t *
26asn1p_parse_buffer(const char *buffer, int size /* = -1 */, enum asn1p_flags flags) {
27 asn1p_t *a = 0;
28 void *ap;
29 void *ybuf;
30 int ret;
31
32 if(_asn1p_set_flags(flags)) {
33 /* EINVAL */
34 return 0;
35 }
36
37 if(size < 0)
Lev Walkin4efbfb72005-02-25 14:20:30 +000038 size = (int)strlen(buffer);
Lev Walkinf15320b2004-06-03 03:38:44 +000039
40 ybuf = asn1p__scan_bytes(buffer, size);
41 if(!ybuf) {
42 assert(ybuf);
43 return 0;
44 }
45
46 asn1p_lineno = 1;
47
48 ap = (void *)&a;
49 ret = asn1p_parse(ap);
50
51 asn1p__delete_buffer(ybuf);
52
53 if(ret == 0) {
54 assert(a);
Lev Walkin070a52d2004-08-22 03:19:54 +000055 if(_asn1p_fix_modules(a, "-"))
Lev Walkinf15320b2004-06-03 03:38:44 +000056 return NULL; /* FIXME: destroy (a) */
57 } else {
58 assert(a == NULL);
59 }
60
61 return a;
62}
63
64
65/*
66 * Parse the file identified by its name.
67 */
68asn1p_t *
69asn1p_parse_file(const char *filename, enum asn1p_flags flags) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000070#ifndef WIN32
Lev Walkinf15320b2004-06-03 03:38:44 +000071 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000072#endif
Lev Walkinf15320b2004-06-03 03:38:44 +000073 asn1p_t *a = 0;
74 void *ap;
75 FILE *fp;
76 int ret;
77
78 if(_asn1p_set_flags(flags)) {
79 /* EINVAL */
80 return 0;
81 }
82
83 fp = fopen(filename, "r");
84 if(fp == NULL) {
85 perror(filename);
86 return NULL;
87 }
88
Lev Walkin4efbfb72005-02-25 14:20:30 +000089#ifndef WIN32
Lev Walkinf15320b2004-06-03 03:38:44 +000090 if(fstat(fileno(fp), &sb)
91 || !S_ISREG(sb.st_mode)) {
92 fclose(fp);
93 fprintf(stderr, "%s file not recognized: Bad file format\n",
94 filename);
95 errno = EINVAL;
96 return NULL;
97 }
Lev Walkin4efbfb72005-02-25 14:20:30 +000098#endif /* WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +000099
100 asn1p_lineno = 1;
101
102 asn1p_restart(fp);
103
104 ap = (void *)&a;
105 ret = asn1p_parse(ap);
106
107 fclose(fp);
108
109 if(ret == 0) {
110 assert(a);
Lev Walkin070a52d2004-08-22 03:19:54 +0000111 if(_asn1p_fix_modules(a, filename))
Lev Walkinf15320b2004-06-03 03:38:44 +0000112 return NULL; /* FIXME: destroy (a) */
113 } else {
114 assert(a == NULL);
115 }
116
117 return a;
118}
119
120extern int asn1p_lexer_types_year;
121extern int asn1p_lexer_constructs_year;
122extern int asn1p__flex_debug;
123
124static int
125_asn1p_set_flags(enum asn1p_flags flags) {
126
127 asn1p_lexer_types_year = 0;
128 asn1p_lexer_constructs_year = 0;
129 asn1p__flex_debug = 0;
130
131 /*
132 * Enable debugging in lexer.
133 */
134 if(flags & A1P_LEXER_DEBUG) {
135 flags &= ~A1P_LEXER_DEBUG;
136 asn1p__flex_debug = 1;
137 }
138
139 /*
140 * Restrict embedded types to ASN.1:1988 version of standard.
141 */
142 if(flags & A1P_TYPES_RESTRICT_TO_1988) {
143 flags &= ~A1P_TYPES_RESTRICT_TO_1988;
144 asn1p_lexer_types_year = 1988;
145 }
146
147 /*
148 * Restrict embedded types to ASN.1:1988 version of standard.
149 */
150 if(flags & A1P_TYPES_RESTRICT_TO_1988) {
151 flags &= ~A1P_TYPES_RESTRICT_TO_1988;
152 asn1p_lexer_types_year = 1988;
153 }
154
155 /*
156 * Check that we haven't missed an unknown flag.
157 */
158 if(flags) {
159 errno = EINVAL;
160 return -1;
161 }
162
163 return 0;
164}
165
Lev Walkin070a52d2004-08-22 03:19:54 +0000166/*
167 * Perform last touches.
168 */
169static void
170_asn1p_apply_module2expr(asn1p_expr_t *expr, asn1p_module_t *mod) {
171 asn1p_expr_t *e;
172
173 expr->module = mod; /* This is a useful thing */
174
175 /*
176 * Do it to children also.
177 */
178 TQ_FOR(e, &(expr->members), next) {
179 _asn1p_apply_module2expr(e, mod);
180 }
181}
182
Lev Walkinf15320b2004-06-03 03:38:44 +0000183static int
Lev Walkin070a52d2004-08-22 03:19:54 +0000184_asn1p_fix_modules(asn1p_t *a, const char *fname) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000185 asn1p_module_t *mod;
186 TQ_FOR(mod, &(a->modules), mod_next) {
Lev Walkin070a52d2004-08-22 03:19:54 +0000187 asn1p_expr_t *expr;
188
Lev Walkinb1107e62004-09-27 20:54:44 +0000189 mod->source_file_name = strdup(fname);
Lev Walkinf15320b2004-06-03 03:38:44 +0000190 if(mod->source_file_name == NULL)
191 return -1;
Lev Walkin070a52d2004-08-22 03:19:54 +0000192
193 TQ_FOR(expr, &(mod->members), next) {
194 _asn1p_apply_module2expr(expr, mod);
195 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000196 }
197 return 0;
198}
Lev Walkin070a52d2004-08-22 03:19:54 +0000199
200