cast ctype functions input to unsigned char
[libfirm] / ir / libcore / lc_printf.c
index 458d3dc..2e6cedf 100644 (file)
@@ -33,7 +33,6 @@
 #include <assert.h>
 #include <ctype.h>
 
-#include "lc_common_t.h"
 #include "xmalloc.h"
 #include "lc_printf.h"
 #include "lc_defines.h"
 
 /* printf implementation */
 
-typedef struct _lc_arg_t {
-       struct _lc_arg_t *next;
+typedef struct lc_arg_t {
+       struct lc_arg_t *next;
        const char *name;
        char letter;
        int lc_arg_type;
        const lc_arg_handler_t *handler;
 } lc_arg_t;
 
-struct _lc_arg_env_t {
-       set *args;                                      /**< Map for named arguments. */
-       lc_arg_t *lower[26];            /**< Map for lower conversion specifiers. */
-       lc_arg_t *upper[26];            /**< Map for upper conversion specifiers. */
+struct lc_arg_env_t {
+       set *args;                  /**< Map for named arguments. */
+       lc_arg_t *lower[26];        /**< Map for lower conversion specifiers. */
+       lc_arg_t *upper[26];        /**< Map for upper conversion specifiers. */
 };
 
 /** The default argument environment. */
@@ -61,7 +60,7 @@ static lc_arg_env_t *default_env = NULL;
 
 static inline lc_arg_env_t *_lc_arg_get_default_env(void)
 {
-       if(!default_env)
+       if (!default_env)
                default_env = lc_arg_add_std(lc_arg_new_env());
 
        return default_env;
@@ -72,10 +71,11 @@ lc_arg_env_t *lc_arg_get_default_env(void)
        return _lc_arg_get_default_env();
 }
 
-static int lc_arg_cmp(const void *p1, const void *p2, UNUSED(size_t size))
+static int lc_arg_cmp(const void *p1, const void *p2, size_t size)
 {
-       const lc_arg_t *a1 = p1;
-       const lc_arg_t *a2 = p2;
+       const lc_arg_t *a1 = (const lc_arg_t*)p1;
+       const lc_arg_t *a2 = (const lc_arg_t*)p2;
+       (void) size;
        return strcmp(a1->name, a2->name);
 }
 
@@ -104,25 +104,27 @@ int lc_arg_register(lc_arg_env_t *env, const char *name, char letter, const lc_a
        arg.letter = letter;
        arg.handler = handler;
 
-       if(isupper(letter)) {
+       if (isupper((unsigned char)letter)) {
                map = env->upper;
                base = 'A';
        }
-       else if(islower(letter)) {
+       else if (islower((unsigned char)letter)) {
                map = env->lower;
                base = 'a';
        }
 
-       ent = set_insert(env->args, &arg, sizeof(arg), HASH_STR(name, strlen(name)));
+       ent = (lc_arg_t*)set_insert(env->args, &arg, sizeof(arg), HASH_STR(name, strlen(name)));
 
-       if(ent && base != 0)
+       if (ent && base != 0)
                map[letter - base] = ent;
 
        return ent != NULL;
 }
 
-void lc_arg_unregister(UNUSED(lc_arg_env_t *env), UNUSED(const char *name))
+void lc_arg_unregister(lc_arg_env_t *env, const char *name)
 {
+       (void) env;
+       (void) name;
 }
 
 int lc_arg_append(lc_appendable_t *app, const lc_arg_occ_t *occ, const char *str, size_t len)
@@ -131,7 +133,7 @@ int lc_arg_append(lc_appendable_t *app, const lc_arg_occ_t *occ, const char *str
 
        /* Set the padding to zero, if the zero is given and we are not left
         * justified. (A minus overrides the zero). See printf(3). */
-       if(!occ->flag_minus && occ->flag_zero)
+       if (!occ->flag_minus && occ->flag_zero)
                pad = '0';
 
        return lc_appendable_snwadd(app, str, len, LC_MAX(0, occ->width), occ->flag_minus, pad);
@@ -143,8 +145,8 @@ static int dispatch_snprintf(char *buf, size_t len, const char *fmt,
 {
        int res = 0;
 
-       switch(lc_arg_type) {
-#define LC_ARG_TYPE(type,name) \
+       switch (lc_arg_type) {
+#define LC_ARG_TYPE(type,name,va_type) \
                case lc_arg_type_ ## name: res = snprintf(buf, len, fmt, val->v_ ## name); break;
 #include "lc_printf_arg_types.def"
 #undef LC_ARG_TYPE
@@ -162,16 +164,55 @@ static char *make_fmt(char *buf, size_t len, const lc_arg_occ_t *occ)
        prec[0] = '\0';
        width[0] = '\0';
 
-       if(occ->precision > 0)
+       if (occ->precision > 0)
                snprintf(prec, sizeof(prec), ".%d", occ->precision);
 
-       if(occ->width > 0)
+       if (occ->width > 0)
                snprintf(width, sizeof(width), "%d", occ->width);
 
        assert(occ->modifier && "modifier must not be NULL");
        strncpy(mod, occ->modifier, sizeof(mod) - 1);
        mod[LC_MIN(sizeof(mod) - 1, occ->modifier_length)] = '\0';
 
+#ifdef _MSC_VER
+       /* work-around for buggy mscrt not supporting z, j,  and t modifier */
+       if (occ->modifier_length == 1) {
+               if (mod[0] == 'z') {
+                       if (sizeof(size_t) == sizeof(int))
+                               mod[0] = '\0';
+                       if (sizeof(size_t) == sizeof(__int64)) {
+                               mod[0] = 'I';
+                               mod[1] = '6';
+                               mod[2] = '4';
+                               mod[3] = '\0';
+                       }
+               } else if (mod[0] == 't') {
+                       if (sizeof(ptrdiff_t) == sizeof(int))
+                               mod[0] = '\0';
+                       if (sizeof(ptrdiff_t) == sizeof(__int64)) {
+                               mod[0] = 'I';
+                               mod[1] = '6';
+                               mod[2] = '4';
+                               mod[3] = '\0';
+                       }
+               } else if (mod[0] == 'j') {
+                       if (sizeof(intmax_t) == sizeof(int))
+                               mod[0] = '\0';
+                       if (sizeof(intmax_t) == sizeof(__int64)) {
+                               mod[0] = 'I';
+                               mod[1] = '6';
+                               mod[2] = '4';
+                               mod[3] = '\0';
+                       }
+               }
+       } else if (occ->modifier_length == 2) {
+               if (mod[0] == 'h' && mod[1] == 'h') {
+                       /* no support for char in mscrt, but we can safely ignore it
+                        * because the size is handled by the argument reader code */
+                       mod[0] = '\0';
+               }
+       }
+#endif
        snprintf(buf, len, "%%%s%s%s%s%s%s%s%s%c",
                        occ->flag_space ? "#" : "",
                        occ->flag_hash ? "#" : "",
@@ -189,20 +230,20 @@ static char *make_fmt(char *buf, size_t len, const lc_arg_occ_t *occ)
  */
 static int std_get_lc_arg_type(const lc_arg_occ_t *occ)
 {
-       int modlen = occ->modifier_length;
+       size_t modlen = occ->modifier_length;
 
        /* check, if the type can be derived from the modifier */
        if (modlen > 0) {
                const char *mod = occ->modifier;
                switch (mod[0]) {
+                       case 'h':
+                               return modlen > 1 && mod[1] == 'h' ? lc_arg_type_char : lc_arg_type_short;
                        case 'l':
                                return modlen > 1 && mod[1] == 'l' ? lc_arg_type_long_long : lc_arg_type_long;
-#define TYPE_CASE(letter,type) case letter: return lc_arg_type_ ## type;
-#if 0
+#define TYPE_CASE(letter,type) case letter: return lc_arg_type_ ## type
                        TYPE_CASE('j', intmax_t);
                        TYPE_CASE('z', size_t);
                        TYPE_CASE('t', ptrdiff_t);
-#endif
                        TYPE_CASE('L', long_double);
 #undef TYPE_CASE
                }
@@ -234,14 +275,14 @@ static int std_emit(lc_appendable_t *app, const lc_arg_occ_t *occ, const lc_arg_
 
        make_fmt(fmt, sizeof(fmt), occ);
 
-       switch(occ->conversion) {
+       switch (occ->conversion) {
 
                /* Store the number of written characters in the given
                 * int pointer location */
                case 'n':
                        {
-                               int *num = val->v_ptr;
-                               *num = app->written;
+                               int *num = (int*)val->v_ptr;
+                               *num = (int)app->written;
                        }
                        break;
 
@@ -249,7 +290,7 @@ static int std_emit(lc_appendable_t *app, const lc_arg_occ_t *occ, const lc_arg_
                 * buffer of 128 letters for all other types should be enough. */
                case 's':
                        {
-                               const char *str = val->v_ptr;
+                               const char *str = (const char*)val->v_ptr;
                                res = lc_arg_append(app, occ, str, strlen(str));
                        }
                        break;
@@ -318,7 +359,7 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
        /* Emit the text before the first % was found */
        lc_appendable_snadd(app, fmt, (s ? s : last) - fmt);
 
-       while(s != NULL) {
+       while (s != NULL) {
                lc_arg_occ_t occ;
                lc_arg_value_t val;
                const lc_arg_t *arg = NULL;
@@ -332,8 +373,8 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
                memset(&occ, 0, sizeof(occ));
 
                /* Eat all flags and set the corresponding flags in the occ struct */
-               for(++s; strchr("#0-+", *s); ++s) {
-                       switch(*s) {
+               for (++s; strchr("#0-+", *s); ++s) {
+                       switch (*s) {
                                case '#':
                                        occ.flag_hash = 1;
                                        break;
@@ -358,13 +399,13 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
                occ.precision = -1;
 
                /* read the precision if given */
-               if(*s == '.') {
-                       int val;
-                       s = read_int(s + 1, &val);
+               if (*s == '.') {
+                       int precision;
+                       s = read_int(s + 1, &precision);
 
                        /* Negative or lacking precision after a '.' is treated as
                         * precision 0. */
-                       occ.precision = LC_MAX(0, val);
+                       occ.precision = LC_MAX(0, precision);
                }
 
                /*
@@ -374,7 +415,7 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
                 * - or some other character, which ends this format invalidly
                 */
                ch = *s;
-               switch(ch) {
+               switch (ch) {
                        case '%':
                                s++;
                                res += lc_appendable_chadd(app, '%');
@@ -384,32 +425,33 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
                                        const char *named = ++s;
 
                                        /* Read until the closing brace or end of the string. */
-                                       for(ch = *s; ch != '}' && ch != '\0'; ch = *++s);
+                                       for (ch = *s; ch != '}' && ch != '\0'; ch = *++s) {
+                                       }
 
-                                       if(s - named) {
-                                               int n = s - named;
+                                       if (s - named) {
+                                               size_t n = s - named;
                                                char *name;
                                                lc_arg_t tmp;
 
-                                               name = malloc(sizeof(char) * (n + 1));
+                                               name = (char*) malloc(sizeof(char) * (n + 1));
                                                memcpy(name, named, sizeof(char) * n);
                                                name[n] = '\0';
                                                tmp.name = name;
 
-                                               arg = set_find(env->args, &tmp, sizeof(tmp), HASH_STR(named, n));
+                                               arg = (lc_arg_t*)set_find(env->args, &tmp, sizeof(tmp), HASH_STR(named, n));
                                                occ.modifier = "";
                                                occ.modifier_length = 0;
 
                                                /* Set the conversion specifier of the occurrence to the
                                                 * letter specified in the argument description. */
-                                               if(arg)
+                                               if (arg)
                                                        occ.conversion = arg->letter;
 
                                                free(name);
 
                                                /* If we ended with a closing brace, move the current
                                                 * pointer after it, since it is not to be dumped. */
-                                               if(ch == '}')
+                                               if (ch == '}')
                                                        s++;
                                        }
                                }
@@ -420,17 +462,17 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
                                        const char *mod = s;
 
                                        /* Read, as long there are letters */
-                                       while(isalpha(ch) && !arg) {
+                                       while (isalpha((unsigned char)ch) && !arg) {
                                                int base = 'a';
                                                lc_arg_t * const *map = env->lower;
 
                                                /* If uppercase, select the uppercase map from the environment */
-                                               if(isupper(ch)) {
+                                               if (isupper((unsigned char)ch)) {
                                                        base = 'A';
                                                        map = env->upper;
                                                }
 
-                                               if(map[ch - base] != NULL) {
+                                               if (map[ch - base] != NULL) {
                                                        occ.modifier = mod;
                                                        occ.modifier_length = s - mod;
                                                        occ.conversion = ch;
@@ -443,7 +485,7 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
                }
 
                /* Call the handler if an argument was determined */
-               if(arg != NULL && arg->handler != NULL) {
+               if (arg != NULL && arg->handler != NULL) {
                        const lc_arg_handler_t *handler = arg->handler;
 
                        /* Let the handler determine the type of the argument based on the
@@ -451,8 +493,9 @@ int lc_evpprintf(const lc_arg_env_t *env, lc_appendable_t *app, const char *fmt,
                        occ.lc_arg_type = handler->get_lc_arg_type(&occ);
 
                        /* Store the value according to argument information */
-                       switch(occ.lc_arg_type) {
-#define LC_ARG_TYPE(type,name) case lc_arg_type_ ## name: val.v_ ## name = va_arg(args, type); break;
+                       switch (occ.lc_arg_type) {
+#define LC_ARG_TYPE(type,name,va_type) \
+                       case lc_arg_type_ ## name: val.v_ ## name = va_arg(args, va_type); break;
 #include "lc_printf_arg_types.def"
 #undef LC_ARG_TYPE
                        }