blob: 94e4a639b0e2ed25ca4ef8329429dac4f5f15d45 [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;
vlmaf841972005-01-28 12:18:50 +0000127 enum ami_flags_e ami_flags = (_format & TNF_CHECK)
128 ? AMI_CHECK_RESERVED : 0;
129 _format &= ~TNF_CHECK;
vlmfa67ddc2004-06-03 03:38:44 +0000130
vlmfb41dbb2004-09-08 00:28:57 +0000131 /* Rewind to the topmost parent expression */
132 if((top_parent = expr->parent_expr))
133 while(top_parent->parent_expr)
134 top_parent = top_parent->parent_expr;
135
vlmfa67ddc2004-06-03 03:38:44 +0000136 switch(expr->expr_type) {
137 case A1TC_REFERENCE:
138 typename = expr->reference->components[
139 expr->reference->comp_count-1].name;
140 if(typename[0] == '&') {
141 arg_t tmp = *arg;
142
143 /*
144 * This is a reference to a type defined in a class.
145 * Resolve it and use instead.
146 */
147 tmp.expr = asn1f_class_access_ex(arg->asn, arg->mod,
vlmb179d312004-08-22 03:23:15 +0000148 arg->expr, expr->reference);
vlmfa67ddc2004-06-03 03:38:44 +0000149 if(tmp.expr) return NULL;
150
vlmb179d312004-08-22 03:23:15 +0000151 tmp.mod = tmp.expr->module;
vlmfa67ddc2004-06-03 03:38:44 +0000152 return asn1c_type_name(&tmp, tmp.expr, _format);
vlmfb41dbb2004-09-08 00:28:57 +0000153 }
154
vlmb47f48e2004-09-17 06:32:12 +0000155 if(_format == TNF_CTYPE) {
vlmfa67ddc2004-06-03 03:38:44 +0000156 /*
vlmb47f48e2004-09-17 06:32:12 +0000157 * If the component references the type itself,
158 * switch to a recursion safe type representation
159 * ("struct foo" instead of "foo_t").
vlmfa67ddc2004-06-03 03:38:44 +0000160 */
161 asn1p_expr_t *terminal;
vlmcbebb812004-09-22 16:05:13 +0000162 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
vlmb47f48e2004-09-17 06:32:12 +0000163 if(terminal && terminal == top_parent) {
164 _format = TNF_RSAFE;
vlmfb41dbb2004-09-08 00:28:57 +0000165 }
vlmfa67ddc2004-06-03 03:38:44 +0000166 }
167 break;
vlmc161f0c2004-08-25 02:03:26 +0000168#if 0
vlmfa67ddc2004-06-03 03:38:44 +0000169 case ASN_CONSTR_SEQUENCE_OF:
170 case ASN_CONSTR_SET_OF:
171 if(expr->Identifier) {
172 typename = expr->Identifier;
173 } else {
174 asn1p_expr_t *child;
175 child = TQ_FIRST(&(expr->members));
176 typename = asn1c_type_name(arg, child, _format);
177 if(typename)
178 return typename;
179 _format = TNF_SAFE;
180 typename = child->Identifier;
181 }
182 break;
vlmc161f0c2004-08-25 02:03:26 +0000183#endif
vlmfa67ddc2004-06-03 03:38:44 +0000184 case ASN_BASIC_INTEGER:
185 case ASN_BASIC_ENUMERATED:
vlmf9d178d2004-09-14 12:47:45 +0000186 case ASN_BASIC_REAL:
187 if((arg->flags & A1C_USE_NATIVE_TYPES)) {
vlmfa67ddc2004-06-03 03:38:44 +0000188 switch(_format) {
189 case TNF_CTYPE:
190 case TNF_RSAFE:
vlmf9d178d2004-09-14 12:47:45 +0000191 if(expr->expr_type == ASN_BASIC_REAL)
192 return "double";
vlmfa67ddc2004-06-03 03:38:44 +0000193 else
vlm909b6c62005-02-25 12:09:55 +0000194 return "long";
vlmf9d178d2004-09-14 12:47:45 +0000195 default: break;
196 }
197 switch(expr->expr_type) {
198 case ASN_BASIC_INTEGER:
199 return "NativeInteger";
200 case ASN_BASIC_ENUMERATED:
201 return "NativeEnumerated";
202 case ASN_BASIC_REAL:
203 return "NativeReal";
204 default: break;
vlmfa67ddc2004-06-03 03:38:44 +0000205 }
206 }
207 /* Fall through */
208 default:
vlmc161f0c2004-08-25 02:03:26 +0000209 if(expr->expr_type
210 & (ASN_CONSTR_MASK | ASN_BASIC_MASK | ASN_STRING_MASK)) {
vlmfa67ddc2004-06-03 03:38:44 +0000211 if(_format == TNF_RSAFE)
212 _format = TNF_CTYPE;
213 typename = ASN_EXPR_TYPE2STR(expr->expr_type);
214 } else {
vlmb47f48e2004-09-17 06:32:12 +0000215 _format = TNF_RSAFE;
vlmfa67ddc2004-06-03 03:38:44 +0000216 typename = expr->Identifier;
217 }
218 }
219
220 switch(_format) {
221 case TNF_UNMODIFIED:
222 case TNF_INCLUDE:
vlmaf841972005-01-28 12:18:50 +0000223 assert(ami_flags == 0); /* (TNF_INCLUDE | TNF_CHECK)?! */
224 ami_flags |= AMI_MASK_ONLY_SPACES;
225 return asn1c_make_identifier(ami_flags, typename, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000226 case TNF_SAFE:
vlmaf841972005-01-28 12:18:50 +0000227 return asn1c_make_identifier(ami_flags, typename, 0);
vlmfa67ddc2004-06-03 03:38:44 +0000228 case TNF_CTYPE:
vlmaf841972005-01-28 12:18:50 +0000229 return asn1c_make_identifier(ami_flags, typename, "t", 0);
vlmfa67ddc2004-06-03 03:38:44 +0000230 case TNF_RSAFE:
vlmaf841972005-01-28 12:18:50 +0000231 return asn1c_make_identifier(ami_flags, "struct", " ", typename, 0);
232 case TNF_NORCHECK:
233 case TNF_CHECK:
234 assert(_format != TNF_NORCHECK);
235 assert(_format != TNF_CHECK);
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