blob: 90377bf6ff49797a9398f1b4031df95a1e2fdb91 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1c_internal.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00002#include "asn1c_misc.h"
3
Lev Walkinf15320b2004-06-03 03:38:44 +00004#include <asn1fix_export.h>
5
Lev Walkinf15320b2004-06-03 03:38:44 +00006/*
Lev Walkin801fabc2005-01-28 12:18:50 +00007 * Checks that the given string is not a reserved C/C++ keyword.
8 */
9static char *res_kwd[] = {
10 "char", "int", "long",
11 "float", "double",
12 "struct", "typedef", "class" };
13static int
14reserved_keyword(const char *str) {
15 int i;
16 for(i = 0 ; i < sizeof(res_kwd)/sizeof(res_kwd[0]); i++) {
17 if(strcmp(str, res_kwd[i]) == 0)
18 return 1;
19 }
20 return 0;
21}
22
23/*
Lev Walkinf15320b2004-06-03 03:38:44 +000024 * Construct identifier from multiple parts.
25 * Convert unsafe characters to underscores.
26 */
27char *
Lev Walkin801fabc2005-01-28 12:18:50 +000028asn1c_make_identifier(enum ami_flags_e flags, char *arg1, ...) {
Lev Walkinf15320b2004-06-03 03:38:44 +000029 static char *storage;
30 static int storage_size;
31 int nodelimiter = 0;
32 va_list ap;
33 char *str;
Lev Walkin801fabc2005-01-28 12:18:50 +000034 char *nextstr;
Lev Walkinf15320b2004-06-03 03:38:44 +000035 int size;
36 char *p;
37
38 if(arg1 == NULL)
39 return NULL;
40
41 /*
42 * Estimate the necessary storage size
43 */
44 size = strlen(arg1);
45 va_start(ap, arg1);
46 while((str = va_arg(ap, char *)))
47 size += 1 + strlen(str);
48 va_end(ap);
49
50 /*
51 * Make sure we have this amount of storage.
52 */
53 if(storage_size <= size) {
54 if(storage) free(storage);
55 storage = malloc(size + 1);
56 if(storage) {
57 storage_size = size;
58 } else {
59 storage_size = 0;
60 return NULL;
61 }
62 }
63
64 /*
65 * Fill-in the storage.
66 */
67 va_start(ap, arg1);
68 str = arg1;
69 p = storage;
Lev Walkin801fabc2005-01-28 12:18:50 +000070 for(str = arg1; str; str = nextstr) {
Lev Walkinf15320b2004-06-03 03:38:44 +000071 int subst_made = 0;
Lev Walkin801fabc2005-01-28 12:18:50 +000072 nextstr = va_arg(ap, char *);
Lev Walkinf15320b2004-06-03 03:38:44 +000073
74 if(str[0] == ' ' && str[1] == '\0') {
75 *p++ = ' ';
76 nodelimiter = 1; /* No delimiter */
77 continue;
78 }
79
80 if(str != arg1 && !nodelimiter)
81 *p++ = '_'; /* Delimiter between tokens */
82 nodelimiter = 0;
83
Lev Walkin801fabc2005-01-28 12:18:50 +000084 /*
85 * If it is a single argument, check that it does not clash
86 * with C/C++ language keywords.
87 */
88 if((flags & AMI_CHECK_RESERVED)
89 && str == arg1 && !nextstr && reserved_keyword(str)) {
90 *p++ = toupper(*str++);
91 /* Fall through */
92 }
93
Lev Walkinf15320b2004-06-03 03:38:44 +000094 for(; *str; str++) {
95 if(isalnum(*str)) {
96 *p++ = *str;
97 subst_made = 0;
98 } else if(!subst_made++) {
Lev Walkin801fabc2005-01-28 12:18:50 +000099 if((flags & AMI_MASK_ONLY_SPACES)
100 && !isspace(*str)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000101 *p ++ = *str;
102 } else {
103 *p++ = '_';
104 }
105 }
106 }
107 }
108 va_end(ap);
109 *p = '\0';
110
111 assert((p - storage) <= storage_size);
112
113 return storage;
114}
115
Lev Walkinf15320b2004-06-03 03:38:44 +0000116char *
117asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
Lev Walkin5a8219a2004-09-08 00:28:57 +0000118 asn1p_expr_t *top_parent;
Lev Walkinf15320b2004-06-03 03:38:44 +0000119 char *typename;
Lev Walkin801fabc2005-01-28 12:18:50 +0000120 enum ami_flags_e ami_flags = (_format & TNF_CHECK)
121 ? AMI_CHECK_RESERVED : 0;
122 _format &= ~TNF_CHECK;
Lev Walkinf15320b2004-06-03 03:38:44 +0000123
Lev Walkin5a8219a2004-09-08 00:28:57 +0000124 /* Rewind to the topmost parent expression */
125 if((top_parent = expr->parent_expr))
126 while(top_parent->parent_expr)
127 top_parent = top_parent->parent_expr;
128
Lev Walkinf15320b2004-06-03 03:38:44 +0000129 switch(expr->expr_type) {
130 case A1TC_REFERENCE:
131 typename = expr->reference->components[
132 expr->reference->comp_count-1].name;
133 if(typename[0] == '&') {
134 arg_t tmp = *arg;
135
136 /*
137 * This is a reference to a type defined in a class.
138 * Resolve it and use instead.
139 */
140 tmp.expr = asn1f_class_access_ex(arg->asn, arg->mod,
Lev Walkin065a74b2004-08-22 03:23:15 +0000141 arg->expr, expr->reference);
Lev Walkinf15320b2004-06-03 03:38:44 +0000142 if(tmp.expr) return NULL;
143
Lev Walkin065a74b2004-08-22 03:23:15 +0000144 tmp.mod = tmp.expr->module;
Lev Walkinf15320b2004-06-03 03:38:44 +0000145 return asn1c_type_name(&tmp, tmp.expr, _format);
Lev Walkin5a8219a2004-09-08 00:28:57 +0000146 }
147
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000148 if(_format == TNF_CTYPE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 /*
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000150 * If the component references the type itself,
151 * switch to a recursion safe type representation
152 * ("struct foo" instead of "foo_t").
Lev Walkinf15320b2004-06-03 03:38:44 +0000153 */
154 asn1p_expr_t *terminal;
Lev Walkine4d6ab82004-09-22 16:05:13 +0000155 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000156 if(terminal && terminal == top_parent) {
157 _format = TNF_RSAFE;
Lev Walkin5a8219a2004-09-08 00:28:57 +0000158 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000159 }
160 break;
Lev Walkin0e22b982004-08-25 02:03:26 +0000161#if 0
Lev Walkinf15320b2004-06-03 03:38:44 +0000162 case ASN_CONSTR_SEQUENCE_OF:
163 case ASN_CONSTR_SET_OF:
164 if(expr->Identifier) {
165 typename = expr->Identifier;
166 } else {
167 asn1p_expr_t *child;
168 child = TQ_FIRST(&(expr->members));
169 typename = asn1c_type_name(arg, child, _format);
170 if(typename)
171 return typename;
172 _format = TNF_SAFE;
173 typename = child->Identifier;
174 }
175 break;
Lev Walkin0e22b982004-08-25 02:03:26 +0000176#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000177 case ASN_BASIC_INTEGER:
178 case ASN_BASIC_ENUMERATED:
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000179 case ASN_BASIC_REAL:
180 if((arg->flags & A1C_USE_NATIVE_TYPES)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000181 switch(_format) {
182 case TNF_CTYPE:
183 case TNF_RSAFE:
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000184 if(expr->expr_type == ASN_BASIC_REAL)
185 return "double";
Lev Walkinf15320b2004-06-03 03:38:44 +0000186 else
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000187 return "int";
188 default: break;
189 }
190 switch(expr->expr_type) {
191 case ASN_BASIC_INTEGER:
192 return "NativeInteger";
193 case ASN_BASIC_ENUMERATED:
194 return "NativeEnumerated";
195 case ASN_BASIC_REAL:
196 return "NativeReal";
197 default: break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000198 }
199 }
200 /* Fall through */
201 default:
Lev Walkin0e22b982004-08-25 02:03:26 +0000202 if(expr->expr_type
203 & (ASN_CONSTR_MASK | ASN_BASIC_MASK | ASN_STRING_MASK)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000204 if(_format == TNF_RSAFE)
205 _format = TNF_CTYPE;
206 typename = ASN_EXPR_TYPE2STR(expr->expr_type);
207 } else {
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000208 _format = TNF_RSAFE;
Lev Walkinf15320b2004-06-03 03:38:44 +0000209 typename = expr->Identifier;
210 }
211 }
212
213 switch(_format) {
214 case TNF_UNMODIFIED:
215 case TNF_INCLUDE:
Lev Walkin801fabc2005-01-28 12:18:50 +0000216 assert(ami_flags == 0); /* (TNF_INCLUDE | TNF_CHECK)?! */
217 ami_flags |= AMI_MASK_ONLY_SPACES;
218 return asn1c_make_identifier(ami_flags, typename, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000219 case TNF_SAFE:
Lev Walkin801fabc2005-01-28 12:18:50 +0000220 return asn1c_make_identifier(ami_flags, typename, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000221 case TNF_CTYPE:
Lev Walkin801fabc2005-01-28 12:18:50 +0000222 return asn1c_make_identifier(ami_flags, typename, "t", 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000223 case TNF_RSAFE:
Lev Walkin801fabc2005-01-28 12:18:50 +0000224 return asn1c_make_identifier(ami_flags, "struct", " ", typename, 0);
225 case TNF_NORCHECK:
226 case TNF_CHECK:
227 assert(_format != TNF_NORCHECK);
228 assert(_format != TNF_CHECK);
Lev Walkinf15320b2004-06-03 03:38:44 +0000229 }
230
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000231 assert(!"unreachable");
Lev Walkinf15320b2004-06-03 03:38:44 +0000232 return typename;
233}
234