blob: 3ceab9787197c7b502137882106cef5b8c8ee21d [file] [log] [blame]
// checking for struct lconv in <locale.h>
/***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the License); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1999-2007 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <locale.h> // for lconv
#include <stddef.h> // for offsetof, size_t
#include <stdio.h> // for printf
#include <string.h> // for strlen
#include "config.h"
#ifndef _RWSTD_NO_OFFSETOF
# define OFF(T, m) offsetof (T, m)
#else
// provide own equivalent when offsetof() macro doesn't work
// (e.g., when using the EDG eccp front end with an incompatible
// version of gcc)
# define OFF(T, m) (((const char*)&((T*)0)->m) - ((const char*)(T*)0))
#endif // _RWSTD_NO_OFFSETOF
// prevent IBM xlC 5.0 errors caused by using /usr/include/string.h
// which #defines this (and other) names to undeclared symbols
#undef strlen
int main ()
{
struct {
size_t offset;
size_t size;
const char *type;
const char *name;
const char *comment;
} lconv_info[] = {
#define ENTRY(type, member, comment) { \
OFF (lconv, member), \
sizeof ((lconv*)0)->member, \
type, \
# member, \
"/* " comment " */" \
}
// C90 and POSIX.1 members
ENTRY ("char*", decimal_point, ""),
ENTRY ("char*", thousands_sep, ""),
ENTRY ("char*", grouping, ""),
ENTRY ("char*", int_curr_symbol, ""),
ENTRY ("char*", currency_symbol, ""),
ENTRY ("char*", mon_decimal_point, ""),
ENTRY ("char*", mon_thousands_sep, ""),
ENTRY ("char*", mon_grouping, ""),
ENTRY ("char*", positive_sign, ""),
ENTRY ("char*", negative_sign, ""),
ENTRY ("char", int_frac_digits, ""),
ENTRY ("char", frac_digits, ""),
ENTRY ("char", p_cs_precedes, ""),
ENTRY ("char", p_sep_by_space, ""),
ENTRY ("char", n_cs_precedes, ""),
ENTRY ("char", n_sep_by_space, ""),
ENTRY ("char", p_sign_posn, ""),
ENTRY ("char", n_sign_posn, "")
#ifndef _RWSTD_NO_LCONV_INT_FMAT
// C99 and POSIX.2 members
, ENTRY ("char", int_p_cs_precedes, ""),
ENTRY ("char", int_n_cs_precedes, ""),
ENTRY ("char", int_p_sep_by_space, ""),
ENTRY ("char", int_n_sep_by_space, ""),
ENTRY ("char", int_p_sign_posn, ""),
ENTRY ("char", int_n_sign_posn, "")
#endif // _RWSTD_NO_LCONV_INT_FMAT
};
const size_t N = sizeof lconv_info / sizeof *lconv_info;
char def [4096] = "";
size_t curoff = 0; // current offset
size_t size = 0; // cumulative size
for (size_t i = 0; i != N; ++i) {
for (size_t j = 0; j != N; ++j) {
if (curoff == lconv_info [j].offset) {
sprintf (def + strlen (def),
" %s %s; \\\n",
lconv_info [j].type,
lconv_info [j].name);
// invalidate offset
lconv_info [j].offset = size_t (-1);
curoff += lconv_info [j].size;
size += lconv_info [j].size;
break;
}
}
}
printf ("#define _RWSTD_LCONV { "
"/* sizeof (lconv) == %u */ \\\n%s",
sizeof (lconv), def);
if (size != sizeof (lconv)) {
printf (" char _C_fill [%u]; /* fill to size */ \\\n",
sizeof (lconv) - size);
}
printf (" }\n");
return 0;
}