blob: 8c5bb628729ec3d2ec034651ad0ae20b1fc3cb03 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1c_internal.h"
vlmb2839012004-08-20 13:37:01 +00002#include "asn1c_misc.h"
3
vlmfa67ddc2004-06-03 03:38:44 +00004#include <asn1fix_export.h>
5
vlmfa67ddc2004-06-03 03:38:44 +00006/*
vlmaf841972005-01-28 12:18:50 +00007 * Checks that the given string is not a reserved C/C++ keyword.
vlm4bf55512005-03-03 21:29:27 +00008 * ISO/IEC 9899:1999 (C99), A.1.2
vlmaf841972005-01-28 12:18:50 +00009 */
10static char *res_kwd[] = {
vlm4bf55512005-03-03 21:29:27 +000011 "const", "auto", "register", "volatile", "restrict", "extern",
12 "static", "inline",
13 "signed", "unsigned",
14 "void", "char", "short", "int", "long", "float", "double",
15 "enum", "union", "struct", "typedef", "class",
16 "switch", "case", "default", "break", "continue",
17 "if", "else", "do", "for", "while", "goto",
18 "sizeof", "return"
19};
vlmaf841972005-01-28 12:18:50 +000020static int
21reserved_keyword(const char *str) {
22 int i;
23 for(i = 0 ; i < sizeof(res_kwd)/sizeof(res_kwd[0]); i++) {
24 if(strcmp(str, res_kwd[i]) == 0)
25 return 1;
26 }
27 return 0;
28}
29
30/*
vlmfa67ddc2004-06-03 03:38:44 +000031 * Construct identifier from multiple parts.
32 * Convert unsafe characters to underscores.
33 */
34char *
vlmaf841972005-01-28 12:18:50 +000035asn1c_make_identifier(enum ami_flags_e flags, char *arg1, ...) {
vlmfa67ddc2004-06-03 03:38:44 +000036 static char *storage;
37 static int storage_size;
38 int nodelimiter = 0;
39 va_list ap;
40 char *str;
vlmaf841972005-01-28 12:18:50 +000041 char *nextstr;
vlm8a09e0f2005-02-25 14:20:30 +000042 size_t size;
vlmfa67ddc2004-06-03 03:38:44 +000043 char *p;
44
45 if(arg1 == NULL)
46 return NULL;
47
48 /*
49 * Estimate the necessary storage size
50 */
51 size = strlen(arg1);
52 va_start(ap, arg1);
53 while((str = va_arg(ap, char *)))
54 size += 1 + strlen(str);
55 va_end(ap);
56
57 /*
58 * Make sure we have this amount of storage.
59 */
60 if(storage_size <= size) {
61 if(storage) free(storage);
62 storage = malloc(size + 1);
63 if(storage) {
64 storage_size = size;
65 } else {
66 storage_size = 0;
67 return NULL;
68 }
69 }
70
71 /*
72 * Fill-in the storage.
73 */
74 va_start(ap, arg1);
75 str = arg1;
76 p = storage;
vlmaf841972005-01-28 12:18:50 +000077 for(str = arg1; str; str = nextstr) {
vlmfa67ddc2004-06-03 03:38:44 +000078 int subst_made = 0;
vlmaf841972005-01-28 12:18:50 +000079 nextstr = va_arg(ap, char *);
vlmfa67ddc2004-06-03 03:38:44 +000080
81 if(str[0] == ' ' && str[1] == '\0') {
82 *p++ = ' ';
83 nodelimiter = 1; /* No delimiter */
84 continue;
85 }
86
87 if(str != arg1 && !nodelimiter)
88 *p++ = '_'; /* Delimiter between tokens */
89 nodelimiter = 0;
90
vlmaf841972005-01-28 12:18:50 +000091 /*
92 * If it is a single argument, check that it does not clash
93 * with C/C++ language keywords.
94 */
95 if((flags & AMI_CHECK_RESERVED)
96 && str == arg1 && !nextstr && reserved_keyword(str)) {
97 *p++ = toupper(*str++);
98 /* Fall through */
99 }
100
vlmfa67ddc2004-06-03 03:38:44 +0000101 for(; *str; str++) {
102 if(isalnum(*str)) {
103 *p++ = *str;
104 subst_made = 0;
105 } else if(!subst_made++) {
vlmaf841972005-01-28 12:18:50 +0000106 if((flags & AMI_MASK_ONLY_SPACES)
107 && !isspace(*str)) {
vlmfa67ddc2004-06-03 03:38:44 +0000108 *p ++ = *str;
109 } else {
110 *p++ = '_';
111 }
112 }
113 }
114 }
115 va_end(ap);
116 *p = '\0';
117
118 assert((p - storage) <= storage_size);
119
120 return storage;
121}
122
vlmfa67ddc2004-06-03 03:38:44 +0000123char *
124asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
vlmfb41dbb2004-09-08 00:28:57 +0000125 asn1p_expr_t *top_parent;
vlmfa67ddc2004-06-03 03:38:44 +0000126 char *typename;
127
vlmfb41dbb2004-09-08 00:28:57 +0000128 /* Rewind to the topmost parent expression */
129 if((top_parent = expr->parent_expr))
130 while(top_parent->parent_expr)
131 top_parent = top_parent->parent_expr;
132
vlmfa67ddc2004-06-03 03:38:44 +0000133 switch(expr->expr_type) {
134 case A1TC_REFERENCE:
135 typename = expr->reference->components[
136 expr->reference->comp_count-1].name;
137 if(typename[0] == '&') {
138 arg_t tmp = *arg;
139
140 /*
141 * This is a reference to a type defined in a class.
142 * Resolve it and use instead.
143 */
144 tmp.expr = asn1f_class_access_ex(arg->asn, arg->mod,
vlmb179d312004-08-22 03:23:15 +0000145 arg->expr, expr->reference);
vlmfa67ddc2004-06-03 03:38:44 +0000146 if(tmp.expr) return NULL;
147
vlmb179d312004-08-22 03:23:15 +0000148 tmp.mod = tmp.expr->module;
vlmfa67ddc2004-06-03 03:38:44 +0000149 return asn1c_type_name(&tmp, tmp.expr, _format);
vlmfb41dbb2004-09-08 00:28:57 +0000150 }
151
vlm0b567bf2005-03-04 22:18:20 +0000152 if(_format == TNF_RSAFE) {
153 asn1p_expr_t *terminal;
154 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
155 if(terminal && terminal->expr_type & ASN_CONSTR_MASK) {
156 typename = terminal->Identifier;
157 }
158 }
159
vlmb47f48e2004-09-17 06:32:12 +0000160 if(_format == TNF_CTYPE) {
vlmfa67ddc2004-06-03 03:38:44 +0000161 /*
vlmb47f48e2004-09-17 06:32:12 +0000162 * If the component references the type itself,
vlm0b567bf2005-03-04 22:18:20 +0000163 * switch to a recursion-safe type naming
vlmb47f48e2004-09-17 06:32:12 +0000164 * ("struct foo" instead of "foo_t").
vlmfa67ddc2004-06-03 03:38:44 +0000165 */
166 asn1p_expr_t *terminal;
vlmcbebb812004-09-22 16:05:13 +0000167 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb47f48e2004-09-17 06:32:12 +0000168 if(terminal && terminal == top_parent) {
169 _format = TNF_RSAFE;
vlmfb41dbb2004-09-08 00:28:57 +0000170 }
vlmfa67ddc2004-06-03 03:38:44 +0000171 }
172 break;
vlmc161f0c2004-08-25 02:03:26 +0000173#if 0
vlmfa67ddc2004-06-03 03:38:44 +0000174 case ASN_CONSTR_SEQUENCE_OF:
175 case ASN_CONSTR_SET_OF:
176 if(expr->Identifier) {
177 typename = expr->Identifier;
178 } else {
179 asn1p_expr_t *child;
180 child = TQ_FIRST(&(expr->members));
181 typename = asn1c_type_name(arg, child, _format);
182 if(typename)
183 return typename;
184 _format = TNF_SAFE;
185 typename = child->Identifier;
186 }
187 break;
vlmc161f0c2004-08-25 02:03:26 +0000188#endif
vlmfa67ddc2004-06-03 03:38:44 +0000189 case ASN_BASIC_INTEGER:
190 case ASN_BASIC_ENUMERATED:
vlmf9d178d2004-09-14 12:47:45 +0000191 case ASN_BASIC_REAL:
192 if((arg->flags & A1C_USE_NATIVE_TYPES)) {
vlmfa67ddc2004-06-03 03:38:44 +0000193 switch(_format) {
194 case TNF_CTYPE:
195 case TNF_RSAFE:
vlmf9d178d2004-09-14 12:47:45 +0000196 if(expr->expr_type == ASN_BASIC_REAL)
197 return "double";
vlmfa67ddc2004-06-03 03:38:44 +0000198 else
vlm909b6c62005-02-25 12:09:55 +0000199 return "long";
vlmf9d178d2004-09-14 12:47:45 +0000200 default: break;
201 }
202 switch(expr->expr_type) {
203 case ASN_BASIC_INTEGER:
204 return "NativeInteger";
205 case ASN_BASIC_ENUMERATED:
206 return "NativeEnumerated";
207 case ASN_BASIC_REAL:
208 return "NativeReal";
209 default: break;
vlmfa67ddc2004-06-03 03:38:44 +0000210 }
211 }
212 /* Fall through */
213 default:
vlmc161f0c2004-08-25 02:03:26 +0000214 if(expr->expr_type
215 & (ASN_CONSTR_MASK | ASN_BASIC_MASK | ASN_STRING_MASK)) {
vlmfa67ddc2004-06-03 03:38:44 +0000216 if(_format == TNF_RSAFE)
217 _format = TNF_CTYPE;
218 typename = ASN_EXPR_TYPE2STR(expr->expr_type);
219 } else {
vlmb47f48e2004-09-17 06:32:12 +0000220 _format = TNF_RSAFE;
vlmfa67ddc2004-06-03 03:38:44 +0000221 typename = expr->Identifier;
222 }
223 }
224
225 switch(_format) {
226 case TNF_UNMODIFIED:
227 case TNF_INCLUDE:
vlm0b567bf2005-03-04 22:18:20 +0000228 return asn1c_make_identifier(AMI_MASK_ONLY_SPACES, typename, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000229 case TNF_SAFE:
vlm0b567bf2005-03-04 22:18:20 +0000230 return asn1c_make_identifier(0, typename, 0);
231 case TNF_CTYPE: /* C type */
232 return asn1c_make_identifier(0, typename, "t", 0);
233 case TNF_RSAFE: /* Recursion-safe type */
234 return asn1c_make_identifier(AMI_CHECK_RESERVED,
235 "struct", " ", typename, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000236 }
237
vlmb47f48e2004-09-17 06:32:12 +0000238 assert(!"unreachable");
vlmfa67ddc2004-06-03 03:38:44 +0000239 return typename;
240}
241