* @author Sebastian Hack
* @date 4.12.2005
*/
+#include "config.h"
#include <stdlib.h>
#include <stdio.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. */
static lc_arg_env_t *default_env = NULL;
-static INLINE lc_arg_env_t *_lc_arg_get_default_env(void)
+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;
static int lc_arg_cmp(const void *p1, const void *p2, UNUSED(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;
return strcmp(a1->name, a2->name);
}
arg.letter = letter;
arg.handler = handler;
- if(isupper(letter)) {
+ if (isupper(letter)) {
map = env->upper;
base = 'A';
}
- else if(islower(letter)) {
+ else if (islower(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;
/* 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);
{
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
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 ? "#" : "",
*/
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
TYPE_CASE('j', intmax_t);
TYPE_CASE('z', size_t);
TYPE_CASE('t', ptrdiff_t);
-#endif
TYPE_CASE('L', long_double);
#undef TYPE_CASE
}
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;
* 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;
/* 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;
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;
occ.precision = -1;
/* read the precision if given */
- if(*s == '.') {
+ if (*s == '.') {
int val;
s = read_int(s + 1, &val);
* - or some other character, which ends this format invalidly
*/
ch = *s;
- switch(ch) {
+ switch (ch) {
case '%':
s++;
res += lc_appendable_chadd(app, '%');
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++;
}
}
const char *mod = s;
/* Read, as long there are letters */
- while(isalpha(ch) && !arg) {
+ while (isalpha(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(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;
}
/* 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
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
}