#include <assert.h>
#include <ctype.h>
-#include "lc_common_t.h"
#include "xmalloc.h"
#include "lc_printf.h"
-#include "lc_defines.h"
#include "hashptr.h"
+#include "util.h"
#include "set.h"
/* printf implementation */
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 = (const lc_arg_t*)p1;
const lc_arg_t *a2 = (const lc_arg_t*)p2;
+ (void) size;
return strcmp(a1->name, a2->name);
}
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 = (lc_arg_t*)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));
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)
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);
+ return lc_appendable_snwadd(app, str, len, MAX(0, occ->width), occ->flag_minus, pad);
}
int res = 0;
switch (lc_arg_type) {
-#define LC_ARG_TYPE(type,name) \
+#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
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';
-
+ mod[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
+#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
}
case 'n':
{
int *num = (int*)val->v_ptr;
- *num = app->written;
+ *num = (int)app->written;
}
break;
default:
{
- int len = LC_MAX(128, occ->width + 1);
+ int len = MAX(128, occ->width + 1);
char *buf = XMALLOCN(char, len);
res = dispatch_snprintf(buf, len, fmt, occ->lc_arg_type, val);
res = lc_appendable_snadd(app, buf, res);
/* read the precision if given */
if (*s == '.') {
- int val;
- s = read_int(s + 1, &val);
+ 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 = MAX(0, precision);
}
/*
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) {
size_t n = s - named;
name[n] = '\0';
tmp.name = name;
- arg = (lc_arg_t*)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));
occ.modifier = "";
occ.modifier_length = 0;
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;
}
/* 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;
+#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
}