blob: 257e02c5c29e739a83020cbf0293bf3601450ea8 [file] [log] [blame]
Lev Walkinf15320b2004-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
Lev Walkind9bd7752004-06-05 08:17:50 +000097 (void)arg; /* Unused argument */
98
Lev Walkinf15320b2004-06-03 03:38:44 +000099 /*
100 * Compute filenames.
101 */
102 len = strlen(name) + strlen(ext) + 1;
103 fname = alloca(len);
104 snprintf(fname, len, "%s%s", name, ext);
105
106 /*
107 * Create files.
108 */
109 fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE);
110 if(fd == -1 && errno == EEXIST) {
111 fd = open(fname, O_WRONLY, DEFFILEMODE);
112 created = 0;
113 }
114 if(fd == -1) {
115 perror(fname);
116 return NULL;
117 }
118
119 /*
120 * Check sanity.
121 */
122 if(fstat(fd, &sb) || !S_ISREG(sb.st_mode)) {
123 fprintf(stderr, "%s: Not a regular file\n", fname);
124 if(created) unlink(fname);
125 close(fd);
126 return NULL;
127 }
128
129 (void)ftruncate(fd, 0);
130
131 /*
132 * Convert file descriptor into file pointer.
133 */
134 fp = fdopen(fd, "w");
135 if(fp == NULL) {
136 if(created) unlink(fname);
137 close(fd);
138 }
139 return fp;
140}
141
142char *
143asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
144 char *typename;
145
146 switch(expr->expr_type) {
147 case A1TC_REFERENCE:
148 typename = expr->reference->components[
149 expr->reference->comp_count-1].name;
150 if(typename[0] == '&') {
151 arg_t tmp = *arg;
152
153 /*
154 * This is a reference to a type defined in a class.
155 * Resolve it and use instead.
156 */
157 tmp.expr = asn1f_class_access_ex(arg->asn, arg->mod,
158 arg->expr, expr->reference, &tmp.mod);
159 if(tmp.expr) return NULL;
160
161 return asn1c_type_name(&tmp, tmp.expr, _format);
162 } else if(_format == TNF_RSAFE) {
163 /*
164 * The recursion-safe format is requested.
165 * The problem here is that only constructed types
166 * might be referenced with "struct".
167 * Change RSAFE to CTYPE if the terminal type
168 * is primitive.
169 */
170 asn1p_expr_t *terminal;
171 terminal = asn1f_find_terminal_type_ex(
172 arg->asn, arg->mod, arg->expr, NULL);
173 if(terminal
174 && (terminal->expr_type
175 & (ASN_BASIC_MASK | ASN_STRING_MASK)))
176 _format = TNF_CTYPE;
177 }
178 break;
179 case ASN_CONSTR_SEQUENCE_OF:
180 case ASN_CONSTR_SET_OF:
181 if(expr->Identifier) {
182 typename = expr->Identifier;
183 } else {
184 asn1p_expr_t *child;
185 child = TQ_FIRST(&(expr->members));
186 typename = asn1c_type_name(arg, child, _format);
187 if(typename)
188 return typename;
189 _format = TNF_SAFE;
190 typename = child->Identifier;
191 }
192 break;
193 case ASN_BASIC_INTEGER:
194 case ASN_BASIC_ENUMERATED:
195 if((arg->flags & A1C_USE_NATIVE_INTEGERS)) {
196 switch(_format) {
197 case TNF_CTYPE:
198 case TNF_RSAFE:
199 return "int";
200 default:
201 if(expr->expr_type == ASN_BASIC_INTEGER)
202 return "NativeInteger";
203 else
204 return "NativeEnumerated";
205 }
206 }
207 /* Fall through */
208 default:
209 if(expr->expr_type & (ASN_BASIC_MASK | ASN_STRING_MASK)) {
210 if(_format == TNF_RSAFE)
211 _format = TNF_CTYPE;
212 typename = ASN_EXPR_TYPE2STR(expr->expr_type);
213 } else {
214 _format = TNF_SAFE;
215 typename = expr->Identifier;
216 }
217 }
218
219 switch(_format) {
220 case TNF_UNMODIFIED:
221 case TNF_INCLUDE:
222 return asn1c_make_identifier(1, typename, 0);
223 case TNF_SAFE:
224 return asn1c_make_identifier(0, typename, 0);
225 case TNF_CTYPE:
226 return asn1c_make_identifier(0, typename, "t", 0);
227 case TNF_RSAFE:
228 return asn1c_make_identifier(0, "struct", " ", typename, 0);
229 }
230
231 assert("!unreachable");
232 return typename;
233}
234