blob: b464b64cdf236c523e6bcf2239c3489f5d5baffd [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1c_internal.h"
2#include <asn1fix_export.h>
3
4#ifndef DEFFILEMODE /* Normally in <sys/stat.h> */
5#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
6#endif
7
8/*
9 * Construct identifier from multiple parts.
10 * Convert unsafe characters to underscores.
11 */
12char *
13asn1c_make_identifier(int unsafe_only_spaces, char *arg1, ...) {
14 static char *storage;
15 static int storage_size;
16 int nodelimiter = 0;
17 va_list ap;
18 char *str;
19 int size;
20 char *p;
21
22 if(arg1 == NULL)
23 return NULL;
24
25 /*
26 * Estimate the necessary storage size
27 */
28 size = strlen(arg1);
29 va_start(ap, arg1);
30 while((str = va_arg(ap, char *)))
31 size += 1 + strlen(str);
32 va_end(ap);
33
34 /*
35 * Make sure we have this amount of storage.
36 */
37 if(storage_size <= size) {
38 if(storage) free(storage);
39 storage = malloc(size + 1);
40 if(storage) {
41 storage_size = size;
42 } else {
43 storage_size = 0;
44 return NULL;
45 }
46 }
47
48 /*
49 * Fill-in the storage.
50 */
51 va_start(ap, arg1);
52 str = arg1;
53 p = storage;
54 for(str = arg1; str; str = va_arg(ap, char *)) {
55 int subst_made = 0;
56
57 if(str[0] == ' ' && str[1] == '\0') {
58 *p++ = ' ';
59 nodelimiter = 1; /* No delimiter */
60 continue;
61 }
62
63 if(str != arg1 && !nodelimiter)
64 *p++ = '_'; /* Delimiter between tokens */
65 nodelimiter = 0;
66
67 for(; *str; str++) {
68 if(isalnum(*str)) {
69 *p++ = *str;
70 subst_made = 0;
71 } else if(!subst_made++) {
72 if(unsafe_only_spaces && !isspace(*str)) {
73 *p ++ = *str;
74 } else {
75 *p++ = '_';
76 }
77 }
78 }
79 }
80 va_end(ap);
81 *p = '\0';
82
83 assert((p - storage) <= storage_size);
84
85 return storage;
86}
87
88FILE *
89asn1c_open_file(arg_t *arg, const char *name, const char *ext) {
90 int created = 1;
91 struct stat sb;
92 char *fname;
93 int len;
94 FILE *fp;
95 int fd;
96
97 /*
98 * Compute filenames.
99 */
100 len = strlen(name) + strlen(ext) + 1;
101 fname = alloca(len);
102 snprintf(fname, len, "%s%s", name, ext);
103
104 /*
105 * Create files.
106 */
107 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
108 if(fd == -1 && errno == EEXIST) {
109 fd = open(fname, O_WRONLY, DEFFILEMODE);
110 created = 0;
111 }
112 if(fd == -1) {
113 perror(fname);
114 return NULL;
115 }
116
117 /*
118 * Check sanity.
119 */
120 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
121 fprintf(stderr, "%s: Not a regular file\n", fname);
122 if(created) unlink(fname);
123 close(fd);
124 return NULL;
125 }
126
127 (void)ftruncate(fd, 0);
128
129 /*
130 * Convert file descriptor into file pointer.
131 */
132 fp = fdopen(fd, "w");
133 if(fp == NULL) {
134 if(created) unlink(fname);
135 close(fd);
136 }
137 return fp;
138}
139
140char *
141asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
142 char *typename;
143
144 switch(expr->expr_type) {
145 case A1TC_REFERENCE:
146 typename = expr->reference->components[
147 expr->reference->comp_count-1].name;
148 if(typename[0] == '&') {
149 arg_t tmp = *arg;
150
151 /*
152 * This is a reference to a type defined in a class.
153 * Resolve it and use instead.
154 */
155 tmp.expr = asn1f_class_access_ex(arg->asn, arg->mod,
156 arg->expr, expr->reference, &tmp.mod);
157 if(tmp.expr) return NULL;
158
159 return asn1c_type_name(&tmp, tmp.expr, _format);
160 } else if(_format == TNF_RSAFE) {
161 /*
162 * The recursion-safe format is requested.
163 * The problem here is that only constructed types
164 * might be referenced with "struct".
165 * Change RSAFE to CTYPE if the terminal type
166 * is primitive.
167 */
168 asn1p_expr_t *terminal;
169 terminal = asn1f_find_terminal_type_ex(
170 arg->asn, arg->mod, arg->expr, NULL);
171 if(terminal
172 && (terminal->expr_type
173 & (ASN_BASIC_MASK | ASN_STRING_MASK)))
174 _format = TNF_CTYPE;
175 }
176 break;
177 case ASN_CONSTR_SEQUENCE_OF:
178 case ASN_CONSTR_SET_OF:
179 if(expr->Identifier) {
180 typename = expr->Identifier;
181 } else {
182 asn1p_expr_t *child;
183 child = TQ_FIRST(&(expr->members));
184 typename = asn1c_type_name(arg, child, _format);
185 if(typename)
186 return typename;
187 _format = TNF_SAFE;
188 typename = child->Identifier;
189 }
190 break;
191 case ASN_BASIC_INTEGER:
192 case ASN_BASIC_ENUMERATED:
193 if((arg->flags & A1C_USE_NATIVE_INTEGERS)) {
194 switch(_format) {
195 case TNF_CTYPE:
196 case TNF_RSAFE:
197 return "int";
198 default:
199 if(expr->expr_type == ASN_BASIC_INTEGER)
200 return "NativeInteger";
201 else
202 return "NativeEnumerated";
203 }
204 }
205 /* Fall through */
206 default:
207 if(expr->expr_type & (ASN_BASIC_MASK | ASN_STRING_MASK)) {
208 if(_format == TNF_RSAFE)
209 _format = TNF_CTYPE;
210 typename = ASN_EXPR_TYPE2STR(expr->expr_type);
211 } else {
212 _format = TNF_SAFE;
213 typename = expr->Identifier;
214 }
215 }
216
217 switch(_format) {
218 case TNF_UNMODIFIED:
219 case TNF_INCLUDE:
220 return asn1c_make_identifier(1, typename, 0);
221 case TNF_SAFE:
222 return asn1c_make_identifier(0, typename, 0);
223 case TNF_CTYPE:
224 return asn1c_make_identifier(0, typename, "t", 0);
225 case TNF_RSAFE:
226 return asn1c_make_identifier(0, "struct", " ", typename, 0);
227 }
228
229 assert("!unreachable");
230 return typename;
231}
232