fcc59b19d015a6ad7e237a08d12669d6342a8128
[com/asn1c.git] / libasn1parser / asn1parser.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #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
12 int asn1p_parse(void **param);
13
14 void *asn1p__scan_bytes(const char *, int len);
15 void *asn1p__delete_buffer(void *);
16 void *asn1p_restart(FILE *);
17
18 extern int asn1p_lineno;
19
20 static int _asn1p_set_flags(enum asn1p_flags flags);
21 static int _asn1p_fix_modules(asn1p_t *a, const char *fname);
22
23 /*
24  * Parse the given buffer.
25  */
26 asn1p_t *
27 asn1p_parse_buffer(const char *buffer, int size /* = -1 */, const char *debug_filename, int initial_lineno, 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)
39                 size = (int)strlen(buffer);
40
41         ybuf = asn1p__scan_bytes(buffer, size);
42         if(!ybuf) {
43                 assert(ybuf);
44                 return 0;
45         }
46
47         asn1p_lineno = initial_lineno;
48
49         ap = (void *)&a;
50         asn1p_parse_debug_filename = debug_filename;
51         ret = asn1p_parse(ap);
52         asn1p_parse_debug_filename = NULL;
53
54         asn1p__delete_buffer(ybuf);
55
56         if(ret == 0) {
57                 assert(a);
58                 if(_asn1p_fix_modules(a, "-")) {
59                         asn1p_delete(a);
60                         return NULL;    /* FIXME: destroy (a) */
61                 }
62         } else if(a) {
63                 asn1p_delete(a);
64                 a = NULL;
65         }
66
67         return a;
68 }
69
70
71 /*
72  * Parse the file identified by its name.
73  */
74 asn1p_t *
75 asn1p_parse_file(const char *filename, enum asn1p_flags flags) {
76 #ifndef _WIN32
77         struct stat sb;
78 #endif
79         asn1p_t *a = 0;
80         void *ap;
81         FILE *fp;
82         int ret;
83
84         if(_asn1p_set_flags(flags)) {
85                 /* EINVAL */
86                 return 0;
87         }
88
89         fp = fopen(filename, "r");
90         if(fp == NULL) {
91                 perror(filename);
92                 return NULL;
93         }
94
95 #ifndef _WIN32
96         if(fstat(fileno(fp), &sb)
97         || !S_ISREG(sb.st_mode)) {
98                 fclose(fp);
99                 fprintf(stderr, "%s file not recognized: Bad file format\n",
100                         filename);
101                 errno = EINVAL;
102                 return NULL;
103         }
104 #endif  /* _WIN32 */
105
106         asn1p_lineno = 1;
107
108         asn1p_restart(fp);
109
110         ap = (void *)&a;
111         asn1p_parse_debug_filename = filename;
112         ret = asn1p_parse(ap);
113         asn1p_parse_debug_filename = NULL;
114
115         fclose(fp);
116
117         if(ret == 0) {
118                 assert(a);
119                 if(_asn1p_fix_modules(a, filename)) {
120                         asn1p_delete(a);
121                         return NULL;    /* FIXME: destroy (a) */
122                 }
123         } else if(a) {
124                 asn1p_delete(a);
125                 a = NULL;
126         }
127
128         return a;
129 }
130
131 extern int asn1p_lexer_types_year;
132 extern int asn1p_lexer_constructs_year;
133 extern int asn1p_lexer_extended_values;
134 extern int asn1p__flex_debug;
135 extern int asn1p_debug;
136
137 static int
138 _asn1p_set_flags(enum asn1p_flags flags) {
139
140         asn1p_lexer_types_year = 0;
141         asn1p_lexer_constructs_year = 0;
142         asn1p__flex_debug = 0;
143         asn1p_debug = 0;
144
145         if(flags & A1P_DEBUG_LEXER) {
146                 flags &= ~A1P_DEBUG_LEXER;
147                 asn1p__flex_debug = 1;
148     }
149
150         if(flags & A1P_DEBUG_PARSER) {
151                 flags &= ~A1P_DEBUG_PARSER;
152                 asn1p_debug = 1;
153     }
154
155     if(flags & A1P_EXTENDED_VALUES) {
156         flags &= ~A1P_EXTENDED_VALUES;
157         asn1p_lexer_extended_values = 1;
158     } else {
159         asn1p_lexer_extended_values = 0;
160     }
161
162     /*
163          * Check that we haven't missed an unknown flag.
164          */
165         if(flags) {
166                 errno = EINVAL;
167                 return -1;
168         }
169
170         return 0;
171 }
172
173 static int
174 _asn1p_fix_modules(asn1p_t *a, const char *fname) {
175         asn1p_module_t *mod;
176         TQ_FOR(mod, &(a->modules), mod_next) {
177                 mod->source_file_name = strdup(fname);
178                 if(mod->source_file_name == NULL)
179                         return -1;
180                 mod->asn1p = a;
181         }
182         return 0;
183 }