blob: bd712b3c505216b0321b3e349941040d2249a0af [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 Walkind370e9f2006-03-16 10:03:35 +00003#include <stdlib.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00004#include <sys/types.h>
5#include <sys/stat.h>
6#include <assert.h>
7#include <errno.h>
8
9#include "asn1parser.h"
10#include "asn1p_list.h"
11
12int asn1p_parse(void **param);
13
14void *asn1p__scan_bytes(const char *, int len);
15void *asn1p__delete_buffer(void *);
16void *asn1p_restart(FILE *);
17
18extern int asn1p_lineno;
19
20static int _asn1p_set_flags(enum asn1p_flags flags);
Lev Walkin070a52d2004-08-22 03:19:54 +000021static int _asn1p_fix_modules(asn1p_t *a, const char *fname);
Lev Walkinf15320b2004-06-03 03:38:44 +000022
23/*
24 * Parse the given buffer.
25 */
26asn1p_t *
27asn1p_parse_buffer(const char *buffer, int size /* = -1 */, enum asn1p_flags flags) {
28 asn1p_t *a = 0;
29 void *ap;
30 void *ybuf;
31 int ret;
32
33 if(_asn1p_set_flags(flags)) {
34 /* EINVAL */
35 return 0;
36 }
37
38 if(size < 0)
Lev Walkin4efbfb72005-02-25 14:20:30 +000039 size = (int)strlen(buffer);
Lev Walkinf15320b2004-06-03 03:38:44 +000040
41 ybuf = asn1p__scan_bytes(buffer, size);
42 if(!ybuf) {
43 assert(ybuf);
44 return 0;
45 }
46
47 asn1p_lineno = 1;
48
49 ap = (void *)&a;
50 ret = asn1p_parse(ap);
51
52 asn1p__delete_buffer(ybuf);
53
54 if(ret == 0) {
55 assert(a);
Lev Walkin070a52d2004-08-22 03:19:54 +000056 if(_asn1p_fix_modules(a, "-"))
Lev Walkinf15320b2004-06-03 03:38:44 +000057 return NULL; /* FIXME: destroy (a) */
Lev Walkin4cd43042005-04-08 10:14:30 +000058 } else if(a) {
59 asn1p_free(a);
60 a = NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +000061 }
62
63 return a;
64}
65
66
67/*
68 * Parse the file identified by its name.
69 */
70asn1p_t *
71asn1p_parse_file(const char *filename, enum asn1p_flags flags) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000072#ifndef WIN32
Lev Walkinf15320b2004-06-03 03:38:44 +000073 struct stat sb;
Lev Walkin4efbfb72005-02-25 14:20:30 +000074#endif
Lev Walkinf15320b2004-06-03 03:38:44 +000075 asn1p_t *a = 0;
76 void *ap;
77 FILE *fp;
78 int ret;
79
80 if(_asn1p_set_flags(flags)) {
81 /* EINVAL */
82 return 0;
83 }
84
85 fp = fopen(filename, "r");
86 if(fp == NULL) {
87 perror(filename);
88 return NULL;
89 }
90
Lev Walkin4efbfb72005-02-25 14:20:30 +000091#ifndef WIN32
Lev Walkinf15320b2004-06-03 03:38:44 +000092 if(fstat(fileno(fp), &sb)
93 || !S_ISREG(sb.st_mode)) {
94 fclose(fp);
95 fprintf(stderr, "%s file not recognized: Bad file format\n",
96 filename);
97 errno = EINVAL;
98 return NULL;
99 }
Lev Walkin4efbfb72005-02-25 14:20:30 +0000100#endif /* WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000101
102 asn1p_lineno = 1;
103
104 asn1p_restart(fp);
105
106 ap = (void *)&a;
107 ret = asn1p_parse(ap);
108
109 fclose(fp);
110
111 if(ret == 0) {
112 assert(a);
Lev Walkin070a52d2004-08-22 03:19:54 +0000113 if(_asn1p_fix_modules(a, filename))
Lev Walkinf15320b2004-06-03 03:38:44 +0000114 return NULL; /* FIXME: destroy (a) */
Lev Walkin4cd43042005-04-08 10:14:30 +0000115 } else if(a) {
116 asn1p_free(a);
Lev Walkinc16cf432005-04-08 10:12:40 +0000117 a = NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000118 }
119
120 return a;
121}
122
123extern int asn1p_lexer_types_year;
124extern int asn1p_lexer_constructs_year;
125extern int asn1p__flex_debug;
126
127static int
128_asn1p_set_flags(enum asn1p_flags flags) {
129
130 asn1p_lexer_types_year = 0;
131 asn1p_lexer_constructs_year = 0;
132 asn1p__flex_debug = 0;
133
134 /*
135 * Enable debugging in lexer.
136 */
137 if(flags & A1P_LEXER_DEBUG) {
138 flags &= ~A1P_LEXER_DEBUG;
139 asn1p__flex_debug = 1;
140 }
141
142 /*
Lev Walkinf15320b2004-06-03 03:38:44 +0000143 * Check that we haven't missed an unknown flag.
144 */
145 if(flags) {
146 errno = EINVAL;
147 return -1;
148 }
149
150 return 0;
151}
152
Lev Walkin070a52d2004-08-22 03:19:54 +0000153/*
154 * Perform last touches.
155 */
156static void
157_asn1p_apply_module2expr(asn1p_expr_t *expr, asn1p_module_t *mod) {
158 asn1p_expr_t *e;
159
160 expr->module = mod; /* This is a useful thing */
161
162 /*
163 * Do it to children also.
164 */
165 TQ_FOR(e, &(expr->members), next) {
166 _asn1p_apply_module2expr(e, mod);
167 }
168}
169
Lev Walkinf15320b2004-06-03 03:38:44 +0000170static int
Lev Walkin070a52d2004-08-22 03:19:54 +0000171_asn1p_fix_modules(asn1p_t *a, const char *fname) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000172 asn1p_module_t *mod;
173 TQ_FOR(mod, &(a->modules), mod_next) {
Lev Walkin070a52d2004-08-22 03:19:54 +0000174 asn1p_expr_t *expr;
175
Lev Walkinb1107e62004-09-27 20:54:44 +0000176 mod->source_file_name = strdup(fname);
Lev Walkinf15320b2004-06-03 03:38:44 +0000177 if(mod->source_file_name == NULL)
178 return -1;
Lev Walkin070a52d2004-08-22 03:19:54 +0000179
180 TQ_FOR(expr, &(mod->members), next) {
181 _asn1p_apply_module2expr(expr, mod);
182 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000183 }
184 return 0;
185}
Lev Walkin070a52d2004-08-22 03:19:54 +0000186
187
Lev Walkind370e9f2006-03-16 10:03:35 +0000188int
189asn1p_atoi(const char *ptr, asn1c_integer_t *value) {
190 errno = 0; /* Clear the error code */
191
192 if(sizeof(*value) <= sizeof(int)) {
193 *value = strtol(ptr, 0, 10);
194 } else {
195#ifdef HAVE_STRTOIMAX
196 *value = strtoimax(ptr, 0, 10);
197#elif HAVE_STRTOLL
198 *value = strtoll(ptr, 0, 10);
199#else
200 *value = strtol(ptr, 0, 10);
201#endif
202 }
203
204 return errno == 0 ? 0 : -1;
205}