blob: 8c5bb628729ec3d2ec034651ad0ae20b1fc3cb03 [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.
Lev Walkin3fe2e122005-03-03 21:29:27 +00008 * ISO/IEC 9899:1999 (C99), A.1.2
Lev Walkin801fabc2005-01-28 12:18:50 +00009 */
10static char *res_kwd[] = {
Lev Walkin3fe2e122005-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};
Lev Walkin801fabc2005-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/*
Lev Walkinf15320b2004-06-03 03:38:44 +000031 * Construct identifier from multiple parts.
32 * Convert unsafe characters to underscores.
33 */
34char *
Lev Walkin801fabc2005-01-28 12:18:50 +000035asn1c_make_identifier(enum ami_flags_e flags, char *arg1, ...) {
Lev Walkinf15320b2004-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;
Lev Walkin801fabc2005-01-28 12:18:50 +000041 char *nextstr;
Lev Walkin4efbfb72005-02-25 14:20:30 +000042 size_t size;
Lev Walkinf15320b2004-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;
Lev Walkin801fabc2005-01-28 12:18:50 +000077 for(str = arg1; str; str = nextstr) {
Lev Walkinf15320b2004-06-03 03:38:44 +000078 int subst_made = 0;
Lev Walkin801fabc2005-01-28 12:18:50 +000079 nextstr = va_arg(ap, char *);
Lev Walkinf15320b2004-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
Lev Walkin801fabc2005-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
Lev Walkinf15320b2004-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++) {
Lev Walkin801fabc2005-01-28 12:18:50 +0000106 if((flags & AMI_MASK_ONLY_SPACES)
107 && !isspace(*str)) {
Lev Walkinf15320b2004-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
Lev Walkinf15320b2004-06-03 03:38:44 +0000123char *
124asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
Lev Walkin5a8219a2004-09-08 00:28:57 +0000125 asn1p_expr_t *top_parent;
Lev Walkinf15320b2004-06-03 03:38:44 +0000126 char *typename;
127
Lev Walkin5a8219a2004-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
Lev Walkinf15320b2004-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,
Lev Walkin065a74b2004-08-22 03:23:15 +0000145 arg->expr, expr->reference);
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 if(tmp.expr) return NULL;
147
Lev Walkin065a74b2004-08-22 03:23:15 +0000148 tmp.mod = tmp.expr->module;
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 return asn1c_type_name(&tmp, tmp.expr, _format);
Lev Walkin5a8219a2004-09-08 00:28:57 +0000150 }
151
Lev Walkinc8285712005-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
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000160 if(_format == TNF_CTYPE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000161 /*
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000162 * If the component references the type itself,
Lev Walkinc8285712005-03-04 22:18:20 +0000163 * switch to a recursion-safe type naming
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000164 * ("struct foo" instead of "foo_t").
Lev Walkinf15320b2004-06-03 03:38:44 +0000165 */
166 asn1p_expr_t *terminal;
Lev Walkine4d6ab82004-09-22 16:05:13 +0000167 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000168 if(terminal && terminal == top_parent) {
169 _format = TNF_RSAFE;
Lev Walkin5a8219a2004-09-08 00:28:57 +0000170 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000171 }
172 break;
Lev Walkin0e22b982004-08-25 02:03:26 +0000173#if 0
Lev Walkinf15320b2004-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;
Lev Walkin0e22b982004-08-25 02:03:26 +0000188#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000189 case ASN_BASIC_INTEGER:
190 case ASN_BASIC_ENUMERATED:
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000191 case ASN_BASIC_REAL:
192 if((arg->flags & A1C_USE_NATIVE_TYPES)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000193 switch(_format) {
194 case TNF_CTYPE:
195 case TNF_RSAFE:
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000196 if(expr->expr_type == ASN_BASIC_REAL)
197 return "double";
Lev Walkinf15320b2004-06-03 03:38:44 +0000198 else
Lev Walkin475d91f2005-02-25 12:09:55 +0000199 return "long";
Lev Walkinc78cbfb2004-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;
Lev Walkinf15320b2004-06-03 03:38:44 +0000210 }
211 }
212 /* Fall through */
213 default:
Lev Walkin0e22b982004-08-25 02:03:26 +0000214 if(expr->expr_type
215 & (ASN_CONSTR_MASK | ASN_BASIC_MASK | ASN_STRING_MASK)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000216 if(_format == TNF_RSAFE)
217 _format = TNF_CTYPE;
218 typename = ASN_EXPR_TYPE2STR(expr->expr_type);
219 } else {
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000220 _format = TNF_RSAFE;
Lev Walkinf15320b2004-06-03 03:38:44 +0000221 typename = expr->Identifier;
222 }
223 }
224
225 switch(_format) {
226 case TNF_UNMODIFIED:
227 case TNF_INCLUDE:
Lev Walkinc8285712005-03-04 22:18:20 +0000228 return asn1c_make_identifier(AMI_MASK_ONLY_SPACES, typename, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000229 case TNF_SAFE:
Lev Walkinc8285712005-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);
Lev Walkinf15320b2004-06-03 03:38:44 +0000236 }
237
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000238 assert(!"unreachable");
Lev Walkinf15320b2004-06-03 03:38:44 +0000239 return typename;
240}
241