Remove all
[com/asn1c.git] / libasn1compiler / asn1c_misc.c
diff --git a/libasn1compiler/asn1c_misc.c b/libasn1compiler/asn1c_misc.c
deleted file mode 100644 (file)
index efadd28..0000000
+++ /dev/null
@@ -1,529 +0,0 @@
-#include "asn1c_internal.h"
-#include "asn1c_misc.h"
-
-#include <asn1fix_crange.h>    /* constraint groker from libasn1fix */
-#include <asn1fix_export.h>    /* other exportable stuff from libasn1fix */
-
-/*
- * Checks that the given string is not a reserved C/C++ keyword [1],[2].
- * _* keywords not included, since asn1 identifiers cannot begin with hyphen [3]
- * [1] ISO/IEC 9899:2011 (C11), 6.4.1
- * [2] ISO/IEC 14882:2014 (C++14), 2.12
- * [3] ISO/IEC 8824-1:2003 (asn1) 11.3
- */
-static char *res_kwd[] = {
-               /* C */
-       "auto", "break", "case", "char", "const", "continue", "default", "do",
-       "double", "else", "enum", "extern", "float", "for", "goto", "if",
-       "inline", "int", "long", "register", "restrict", "return", "short",
-       "signed", "sizeof", "static", "struct", "switch", "typedef", "union",
-       "unsigned", "void", "volatile", "while",
-               /* C++ */
-       "alignas", "alignof", "and", "and_eq", "asm", "bitand", "bitor", "bool",
-       "catch", "char16_t", "char32_t", "class", "compl", "const_cast",
-       "constexpr", "decltype", "delete", "delete", "dynamic_cast",
-       "explicit", "export", "false", "friend", "mutable", "namespace", "new",
-       "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq",
-       "private", "protected", "public", "reinterpret_cast", "static_assert",
-       "static_cast", "template", "this", "thread_local", "throw", "true", "try",
-       "typeid", "typename", "using", "virtual", "wchar_t", "xor", "xor_eq"
-};
-static int
-reserved_keyword(const char *str) {
-       size_t i;
-       for(i = 0 ; i < sizeof(res_kwd)/sizeof(res_kwd[0]); i++) {
-               if(strcmp(str, res_kwd[i]) == 0)
-                       return 1;
-       }
-       return 0;
-}
-
-const char *
-asn1c_prefix()
-{
-       const char *prefix = getenv("ASN1C_PREFIX");
-
-       if(!prefix) prefix = "";
-
-       return prefix;
-}
-
-/*
- * Construct identifier from multiple parts.
- * Convert unsafe characters to underscores.
- */
-const char *
-asn1c_make_identifier(enum ami_flags_e flags, asn1p_expr_t *expr, ...) {
-       static char *storage;
-       static int storage_size;
-       int nodelimiter = 0;
-       va_list ap;
-       char *str;
-       char *nextstr;
-       char *first = 0;
-       ssize_t size = 0;
-       char *p;
-       const char *prefix = NULL;
-       char *sptr[4], **psptr = &sptr[0];
-       int sptr_cnt = 0;
-
-       if(flags & AMI_USE_PREFIX)
-               prefix = asn1c_prefix();
-
-       if(expr) {
-               /*
-                * Estimate the necessary storage size
-                */
-               if(expr->Identifier == NULL)
-                       return "Member";
-               /*
-                * Add MODULE name to resolve clash
-                */
-               if(expr->_mark & TM_NAMECLASH) {
-                       size += strlen(expr->module->ModuleName) + 2;
-                       sptr[sptr_cnt++] = expr->module->ModuleName;
-               }
-               sptr[sptr_cnt++] = expr->Identifier;
-
-               size += strlen(expr->Identifier);
-               if(expr->spec_index != -1 && expr->_lineno) {
-                       static char buf[32];
-                       size += 1 + snprintf(buf, sizeof buf, "%dP%d",
-                               expr->_lineno, expr->spec_index);
-                       sptr[sptr_cnt++] = (char *)&buf;
-               }
-       } else {
-               size = -1;
-       }
-       sptr[sptr_cnt++] = (char *)0;
-
-       va_start(ap, expr);
-       while((str = va_arg(ap, char *)))
-               size += 1 + strlen(str);
-       va_end(ap);
-       if(size == -1) return NULL;
-
-       if(prefix)
-               size += 1 + strlen(prefix);
-       /*
-        * Make sure we have the required amount of storage.
-        */
-       if(storage_size <= size) {
-        char *tmp = malloc(size + 1);
-        if(tmp) {
-            free(storage);
-            storage = tmp;
-            storage_size = size + 1;
-        } else {
-            return NULL;
-        }
-       }
-
-       /*
-        * Fill-in the storage.
-        */
-       va_start(ap, expr);
-       p = storage;
-       if(prefix) {
-               strcpy(storage, prefix);
-               p += strlen(prefix);
-               nodelimiter = 1;
-       }
-       nextstr = "";
-       for(str = 0; str || nextstr; str = nextstr) {
-               int subst_made = 0;
-               nextstr = *(psptr) ? *(psptr++) : va_arg(ap, char *);
-
-               if(str == 0) {
-                       str = first = nextstr;
-                       nextstr = *(psptr) ? *(psptr++) : va_arg(ap, char *);
-                       if (!first) continue;
-               }
-
-               if(str[0] == '\0') {
-                       nodelimiter = 1;        /* No delimiter */
-                       continue;
-               }
-
-               if(str[0] == ' ' && str[1] == '\0') {
-                       *p++ = ' ';
-                       nodelimiter = 1;        /* No delimiter */
-                       continue;
-               }
-
-               if(str != first && !nodelimiter && !(flags & AMI_NODELIMITER))
-                       *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 == first && !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((flags & AMI_MASK_ONLY_SPACES)
-                                               && !isspace(*str)) {
-                                       *p ++ = *str;
-                               } else {
-                                       *p++ = '_';
-                               }
-                       }
-               }
-       }
-       va_end(ap);
-       *p = '\0';
-
-       assert((p - storage) <= storage_size);
-
-       return storage;
-}
-
-const char *
-asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
-       asn1p_expr_t *exprid = 0;
-       asn1p_expr_t *top_parent;
-       asn1p_expr_t *terminal = 0;
-       int stdname = 0;
-       const char *typename;
-       const char *prefix;
-
-       /* Rewind to the topmost parent expression */
-       if((top_parent = expr->parent_expr))
-               while(top_parent->parent_expr)
-                       top_parent = top_parent->parent_expr;
-
-       if(0) DEBUG("asn1c_type_name(%s: 0x%x)",
-               expr->Identifier, expr->expr_type);
-
-       switch(expr->expr_type) {
-       case A1TC_REFERENCE:
-               typename = expr->reference->components[
-                       expr->reference->comp_count-1].name;
-               if(typename[0] == '&') {
-                       arg_t tmp = *arg;
-
-                       /*
-                        * This is a reference to a type defined in a class.
-                        * Resolve it and use instead.
-                        */
-            tmp.expr = WITH_MODULE_NAMESPACE(
-                arg->expr->module, expr_ns,
-                asn1f_class_access_ex(arg->asn, arg->expr->module, expr_ns,
-                                      arg->expr, expr->rhs_pspecs,
-                                      expr->reference));
-            if(!tmp.expr) return NULL;
-
-                       return asn1c_type_name(&tmp, tmp.expr, _format);
-               }
-
-        terminal = WITH_MODULE_NAMESPACE(
-            expr->module, expr_ns,
-            (expr->meta_type == AMT_TYPEREF) ? 
-                asn1f_lookup_symbol_ex(arg->asn, expr_ns, expr, expr->reference) :
-                asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
-
-        if(_format == TNF_RSAFE) {
-                       if(terminal && terminal->expr_type & ASN_CONSTR_MASK) {
-                               typename = terminal->Identifier;
-                       }
-               }
-
-               if(_format == TNF_CTYPE || _format == TNF_CONSTYPE) {
-                       /*
-                        * If the component references the type itself,
-                        * switch to a recursion-safe type naming
-                        * ("struct foo" instead of "foo_t").
-                        */
-                       if(terminal && terminal == top_parent) {
-                               _format = TNF_RSAFE;
-                       }
-               }
-
-               if(_format != TNF_RSAFE  && terminal && ((terminal->spec_index != -1) || (terminal->_mark & TM_NAMECLASH))) {
-                       exprid = terminal;
-                       typename = 0;
-               }
-
-               break;
-       case ASN_BASIC_INTEGER:
-       case ASN_BASIC_ENUMERATED:
-       case ASN_BASIC_REAL:
-        if((expr->expr_type == ASN_BASIC_REAL
-            && (_format == TNF_CONSTYPE || !(arg->flags & A1C_USE_WIDE_TYPES)
-                || asn1c_REAL_fits(arg, expr) != RL_NOTFIT))
-           || asn1c_type_fits_long(arg, expr)) {
-            switch(_format) {
-                       case TNF_CONSTYPE:
-                               if(expr->expr_type == ASN_BASIC_REAL) {
-                    return "double";
-                } else if(asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
-                    return "unsigned long";
-                } else {
-                    return "long";
-                }
-            case TNF_CTYPE:
-            case TNF_RSAFE:
-                if(expr->expr_type == ASN_BASIC_REAL) {
-                    asn1cnst_range_t *range = asn1constraint_compute_OER_range(
-                        expr->Identifier, ASN_BASIC_REAL,
-                        expr->combined_constraints, ACT_EL_RANGE, 0, 0, 0);
-                    if(range->narrowing == NARROW_FLOAT32) {
-                        asn1constraint_range_free(range);
-                        return "float";
-                    } else {
-                        asn1constraint_range_free(range);
-                        return "double";
-                    }
-                } else if(asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
-                    return "unsigned long";
-                } else {
-                    return "long";
-                }
-            default:
-                               typename = 0;
-                               switch(expr->expr_type) {
-                               case ASN_BASIC_INTEGER:
-                                       typename = "NativeInteger"; break;
-                               case ASN_BASIC_ENUMERATED:
-                                       typename = "NativeEnumerated"; break;
-                               case ASN_BASIC_REAL:
-                                       typename = "NativeReal"; break;
-                               default:
-                                       break;
-                               }
-                               break;
-                       }
-                       if(typename) {
-                               if(_format != TNF_INCLUDE)
-                                       return typename;
-                               stdname = 1;
-                               break;
-                       }
-               }
-               /* Fall through */
-       default:
-               if(expr->expr_type
-               & (ASN_CONSTR_MASK | ASN_BASIC_MASK | ASN_STRING_MASK)) {
-                       if(_format == TNF_RSAFE)
-                               _format = TNF_CTYPE;
-                       stdname = 1;
-                       typename = ASN_EXPR_TYPE2STR(expr->expr_type);
-                       if(_format == TNF_INCLUDE) {
-                               if(expr->expr_type == ASN_CONSTR_SEQUENCE)
-                                       typename = "constr_SEQUENCE";
-                               else if(expr->expr_type == ASN_CONSTR_CHOICE)
-                                       typename = "constr_CHOICE";
-                               else if(expr->expr_type == ASN_CONSTR_SET)
-                                       typename = "constr_SET";
-                               else if(expr->expr_type == ASN_CONSTR_SEQUENCE_OF)
-                                       typename = "constr_SEQUENCE_OF";
-                               else if(expr->expr_type == ASN_CONSTR_SET_OF)
-                                       typename = "constr_SET_OF";
-                               else if(expr->expr_type == ASN_CONSTR_OPEN_TYPE)
-                                       typename = "OPEN_TYPE";
-                       }
-               } else {
-                       _format = TNF_RSAFE;
-                       typename = expr->Identifier;
-               }
-       }
-
-       prefix = stdname ? "" : asn1c_prefix();
-
-       switch(_format) {
-       case TNF_UNMODIFIED:
-               return asn1c_make_identifier(AMI_MASK_ONLY_SPACES | AMI_NODELIMITER | (stdname ? 0 : AMI_USE_PREFIX),
-                       0, prefix, MODULE_NAME_OF(exprid), exprid ? exprid->Identifier : typename, (char*)0);
-       case TNF_INCLUDE:
-               return asn1c_make_identifier(
-                       AMI_MASK_ONLY_SPACES | AMI_NODELIMITER,
-                       0, ((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
-                               ? "\"" : "<"),
-                       prefix, MODULE_NAME_OF(exprid),
-                       exprid ? exprid->Identifier : typename,
-                       ((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
-                               ? ".h\"" : ".h>"), (char*)0);
-       case TNF_SAFE:
-               return asn1c_make_identifier(stdname ? 0 : AMI_USE_PREFIX, exprid, typename, (char*)0);
-       case TNF_CTYPE: /* C type */
-       case TNF_CONSTYPE:      /* C type */
-               return asn1c_make_identifier(stdname ? 0 : AMI_USE_PREFIX, exprid,
-                               exprid?"t":typename, exprid?0:"t", (char*)0);
-       case TNF_RSAFE: /* Recursion-safe type */
-               return asn1c_make_identifier(AMI_CHECK_RESERVED | AMI_NODELIMITER, 0,
-                       "struct", " ", prefix, MODULE_NAME_OF(exprid), typename, (char*)0);
-       }
-
-       assert(!"unreachable");
-       return typename;
-}
-
-static asn1p_expr_type_e
-expr_get_type(arg_t *arg, asn1p_expr_t *expr) {
-        asn1p_expr_t *terminal;
-        terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
-        if(terminal) return terminal->expr_type;
-        return A1TC_INVALID;
-}
-
-enum asn1c_fitsfloat_e
-asn1c_REAL_fits(arg_t *arg, asn1p_expr_t *expr) {
-    asn1p_expr_type_e etype = expr_get_type(arg, arg->expr);
-    if(etype == ASN_BASIC_REAL) {
-        asn1cnst_range_t *range = asn1constraint_compute_OER_range(
-            expr->Identifier, etype, expr->combined_constraints, ACT_EL_RANGE,
-            0, 0, 0);
-        enum asn1c_fitsfloat_e fits;
-        switch(range->narrowing) {
-        case NARROW_FLOAT32:
-            fits = RL_FITS_FLOAT32;
-            break;
-        case NARROW_DOUBLE64:
-            fits = RL_FITS_DOUBLE64;
-            break;
-        default:
-            fits = RL_NOTFIT;
-            break;
-        }
-        asn1constraint_range_free(range);
-        return fits;
-    } else {
-        return 0;
-    }
-}
-
-/*
- * Check whether the specified INTEGER or ENUMERATED type can be represented
- * using the generic 'long' or 'unsigned long' type.
- */
-enum asn1c_fitslong_e
-asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr) {
-       asn1cnst_range_t *range = 0;
-       asn1cnst_edge_t left;
-       asn1cnst_edge_t right;
-       asn1p_expr_t *v;
-
-/*
- * Since we don't know the sizeof(long) on the possible target platform
- * which will be compiling the code generated by asn1c, let's play it
- * simple: long's range is equal to or greater than int32_t.
- * NOTE: the most negative integer cannot be written in C, as the C99
- * standard will give it an unsigned type.
- * It is defined here as a constant expression.
- */
-#define        RIGHTMAX        2147483647      /* of 32-bit integer type */
-#define        LEFTMIN         (-RIGHTMAX-1)   /* of 32-bit integer type */
-
-       /* Descend to the terminal type */
-    expr = WITH_MODULE_NAMESPACE(
-        expr->module, expr_ns,
-        asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
-    if(expr == 0) return FL_NOTFIT;
-
-       /* The "fits into long" operation is relevant only for integer types */
-       switch(expr->expr_type) {
-       case ASN_BASIC_INTEGER:
-       case ASN_BASIC_ENUMERATED:
-               break;
-       default:
-               return FL_NOTFIT;
-       }
-
-       /*
-        * First, evaluate the range of explicitly given identifiers.
-        */
-       TQ_FOR(v, &(expr->members), next) {
-               if(v->expr_type != A1TC_UNIVERVAL)
-                       continue;
-               if(v->value->value.v_integer < LEFTMIN
-               || v->value->value.v_integer > RIGHTMAX)
-                       return FL_NOTFIT;
-       }
-
-       if(!expr->combined_constraints) 
-               return (arg->flags & A1C_USE_WIDE_TYPES)
-                       ? FL_NOTFIT : FL_PRESUMED;
-
-       /*
-        * Second, if -fbless-SIZE is given, the (SIZE()) constraint may be
-        * applied (non-standard! but we can deal with this) to the type.
-        * Check the range.
-        */
-       range = asn1constraint_compute_constraint_range(expr->Identifier,
-               expr->expr_type,
-               expr->combined_constraints, ACT_CT_SIZE, 0, 0,
-               CPR_simulate_fbless_SIZE);
-       if(range) {
-               if(!range->incompatible) {
-                       right = range->right;
-                       /* Use 4 instead of sizeof(long) is justified! */
-                       if(right.type == ARE_VALUE && right.value <= 4)
-                               return FL_FITS_SIGNED;
-               }
-               asn1constraint_range_free(range);
-       }
-
-       /*
-        * Third, pull up the PER visible range of the INTEGER.
-        */
-       range = asn1constraint_compute_PER_range(expr->Identifier, expr->expr_type,
-               expr->combined_constraints, ACT_EL_RANGE, 0, 0, 0);
-
-       if(!range
-       /* Commenting out
-    || range->extensible
-     * because this may or may not indicate wide type.
-     */
-    || (range->extensible && (arg->flags & A1C_USE_WIDE_TYPES))
-       || range->empty_constraint
-       || range->incompatible
-       || range->not_PER_visible
-       ) {
-               asn1constraint_range_free(range);
-               return (arg->flags & A1C_USE_WIDE_TYPES)
-                       ? FL_NOTFIT : FL_PRESUMED;
-       }
-
-       left = range->left;
-       right = range->right;
-       asn1constraint_range_free(range);
-
-       /* Special case for unsigned */
-    if(!(arg->flags & A1C_USE_WIDE_TYPES) && left.type == ARE_VALUE
-       && left.value >= 0 && left.value <= 2147483647
-       && right.type == ARE_MAX) {
-        return FL_FITS_UNSIGN;
-    }
-    if(left.type == ARE_VALUE
-               && left.value >= 0
-       && right.type == ARE_VALUE
-               && right.value > 2147483647
-               && right.value <= (asn1c_integer_t)(4294967295UL))
-               return FL_FITS_UNSIGN;
-               
-
-       /* If some fixed value is outside of target range, not fit */
-       if(left.type == ARE_VALUE
-                       && (left.value < LEFTMIN || left.value > RIGHTMAX))
-               return FL_NOTFIT;
-       if(right.type == ARE_VALUE
-                       && (right.value > RIGHTMAX || right.value < LEFTMIN))
-               return FL_NOTFIT;
-
-       /* If the range is open, fits only unless -fwide-types is given */
-       if(left.type != ARE_VALUE || right.type != ARE_VALUE) {
-               return (arg->flags & A1C_USE_WIDE_TYPES)
-                       ? FL_NOTFIT : FL_PRESUMED;
-       }
-
-       return FL_FITS_SIGNED;
-}