blob: 45f60c31725a756ec8f68029eb6e09f9c2df6e2b [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 {
Lev Walkinc16cf432005-04-08 10:12:40 +0000114 /* Not always true: assert(a == NULL); */
115 a = NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000116 }
117
118 return a;
119}
120
121extern int asn1p_lexer_types_year;
122extern int asn1p_lexer_constructs_year;
123extern int asn1p__flex_debug;
124
125static int
126_asn1p_set_flags(enum asn1p_flags flags) {
127
128 asn1p_lexer_types_year = 0;
129 asn1p_lexer_constructs_year = 0;
130 asn1p__flex_debug = 0;
131
132 /*
133 * Enable debugging in lexer.
134 */
135 if(flags & A1P_LEXER_DEBUG) {
136 flags &= ~A1P_LEXER_DEBUG;
137 asn1p__flex_debug = 1;
138 }
139
140 /*
141 * Restrict embedded types to ASN.1:1988 version of standard.
142 */
143 if(flags & A1P_TYPES_RESTRICT_TO_1988) {
144 flags &= ~A1P_TYPES_RESTRICT_TO_1988;
145 asn1p_lexer_types_year = 1988;
146 }
147
148 /*
149 * Restrict embedded types to ASN.1:1988 version of standard.
150 */
151 if(flags & A1P_TYPES_RESTRICT_TO_1988) {
152 flags &= ~A1P_TYPES_RESTRICT_TO_1988;
153 asn1p_lexer_types_year = 1988;
154 }
155
156 /*
157 * Check that we haven't missed an unknown flag.
158 */
159 if(flags) {
160 errno = EINVAL;
161 return -1;
162 }
163
164 return 0;
165}
166
Lev Walkin070a52d2004-08-22 03:19:54 +0000167/*
168 * Perform last touches.
169 */
170static void
171_asn1p_apply_module2expr(asn1p_expr_t *expr, asn1p_module_t *mod) {
172 asn1p_expr_t *e;
173
174 expr->module = mod; /* This is a useful thing */
175
176 /*
177 * Do it to children also.
178 */
179 TQ_FOR(e, &(expr->members), next) {
180 _asn1p_apply_module2expr(e, mod);
181 }
182}
183
Lev Walkinf15320b2004-06-03 03:38:44 +0000184static int
Lev Walkin070a52d2004-08-22 03:19:54 +0000185_asn1p_fix_modules(asn1p_t *a, const char *fname) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000186 asn1p_module_t *mod;
187 TQ_FOR(mod, &(a->modules), mod_next) {
Lev Walkin070a52d2004-08-22 03:19:54 +0000188 asn1p_expr_t *expr;
189
Lev Walkinb1107e62004-09-27 20:54:44 +0000190 mod->source_file_name = strdup(fname);
Lev Walkinf15320b2004-06-03 03:38:44 +0000191 if(mod->source_file_name == NULL)
192 return -1;
Lev Walkin070a52d2004-08-22 03:19:54 +0000193
194 TQ_FOR(expr, &(mod->members), next) {
195 _asn1p_apply_module2expr(expr, mod);
196 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000197 }
198 return 0;
199}
Lev Walkin070a52d2004-08-22 03:19:54 +0000200
201