checking reserved keywords and double identifiers
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@618 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1compiler/asn1c_misc.c b/libasn1compiler/asn1c_misc.c
index a1dbbd8..90377bf 100644
--- a/libasn1compiler/asn1c_misc.c
+++ b/libasn1compiler/asn1c_misc.c
@@ -4,16 +4,34 @@
#include <asn1fix_export.h>
/*
+ * Checks that the given string is not a reserved C/C++ keyword.
+ */
+static char *res_kwd[] = {
+ "char", "int", "long",
+ "float", "double",
+ "struct", "typedef", "class" };
+static int
+reserved_keyword(const char *str) {
+ int i;
+ for(i = 0 ; i < sizeof(res_kwd)/sizeof(res_kwd[0]); i++) {
+ if(strcmp(str, res_kwd[i]) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/*
* Construct identifier from multiple parts.
* Convert unsafe characters to underscores.
*/
char *
-asn1c_make_identifier(int unsafe_only_spaces, char *arg1, ...) {
+asn1c_make_identifier(enum ami_flags_e flags, char *arg1, ...) {
static char *storage;
static int storage_size;
int nodelimiter = 0;
va_list ap;
char *str;
+ char *nextstr;
int size;
char *p;
@@ -49,8 +67,9 @@
va_start(ap, arg1);
str = arg1;
p = storage;
- for(str = arg1; str; str = va_arg(ap, char *)) {
+ for(str = arg1; str; str = nextstr) {
int subst_made = 0;
+ nextstr = va_arg(ap, char *);
if(str[0] == ' ' && str[1] == '\0') {
*p++ = ' ';
@@ -62,12 +81,23 @@
*p++ = '_'; /* Delimiter between tokens */
nodelimiter = 0;
+ /*
+ * If it is a single argument, check that it does not clash
+ * with C/C++ language keywords.
+ */
+ if((flags & AMI_CHECK_RESERVED)
+ && str == arg1 && !nextstr && reserved_keyword(str)) {
+ *p++ = toupper(*str++);
+ /* Fall through */
+ }
+
for(; *str; str++) {
if(isalnum(*str)) {
*p++ = *str;
subst_made = 0;
} else if(!subst_made++) {
- if(unsafe_only_spaces && !isspace(*str)) {
+ if((flags & AMI_MASK_ONLY_SPACES)
+ && !isspace(*str)) {
*p ++ = *str;
} else {
*p++ = '_';
@@ -87,6 +117,9 @@
asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
asn1p_expr_t *top_parent;
char *typename;
+ enum ami_flags_e ami_flags = (_format & TNF_CHECK)
+ ? AMI_CHECK_RESERVED : 0;
+ _format &= ~TNF_CHECK;
/* Rewind to the topmost parent expression */
if((top_parent = expr->parent_expr))
@@ -180,13 +213,19 @@
switch(_format) {
case TNF_UNMODIFIED:
case TNF_INCLUDE:
- return asn1c_make_identifier(1, typename, 0);
+ assert(ami_flags == 0); /* (TNF_INCLUDE | TNF_CHECK)?! */
+ ami_flags |= AMI_MASK_ONLY_SPACES;
+ return asn1c_make_identifier(ami_flags, typename, 0);
case TNF_SAFE:
- return asn1c_make_identifier(0, typename, 0);
+ return asn1c_make_identifier(ami_flags, typename, 0);
case TNF_CTYPE:
- return asn1c_make_identifier(0, typename, "t", 0);
+ return asn1c_make_identifier(ami_flags, typename, "t", 0);
case TNF_RSAFE:
- return asn1c_make_identifier(0, "struct", " ", typename, 0);
+ return asn1c_make_identifier(ami_flags, "struct", " ", typename, 0);
+ case TNF_NORCHECK:
+ case TNF_CHECK:
+ assert(_format != TNF_NORCHECK);
+ assert(_format != TNF_CHECK);
}
assert(!"unreachable");