Преглед изворни кода

- fix locale dependencies and make default locale generation less verbose.
The verbosity can be set to the previous level by passing V=2 to make.

Bernhard Reutner-Fischer пре 16 година
родитељ
комит
b46830f8b2
7 измењених фајлова са 402 додато и 289 уклоњено
  1. 0 5
      Makefile.in
  2. 12 2
      Makerules
  3. 1 1
      extra/Configs/Config.in
  4. 71 47
      extra/locale/Makefile.in
  5. 148 86
      extra/locale/gen_collate.c
  6. 120 104
      extra/locale/gen_locale.c
  7. 50 44
      extra/locale/gen_wctype.c

+ 0 - 5
Makefile.in

@@ -20,10 +20,6 @@ sub_headers := headers
 ifeq ($(HAVE_DOT_CONFIG),y)
 
 all: pregen libs
-
-# To be able to build the libs rule, we must first have the generated headers.
-# This is needed when locale support is enabled, but also ensures that the
-# build process is parallel safe.
 libs: pregen
 
 # In this section, we need .config
@@ -61,7 +57,6 @@ ifeq ($(HAVE_DOT_CONFIG),y)
 # on spot to save us from alot of hazzle.
 include/bits/uClibc_config.h: extra/config/conf .config $(top_srcdir)extra/scripts/conf-header.sh | include/bits
 	@$(disp_gen)
-	@#superfluous: $(Q)$(INSTALL) -d $(dir $@)
 	$(Q)@$< -s $(top_srcdir)extra/Configs/Config.in
 	$(Q)$(top_srcdir)extra/scripts/conf-header.sh .config > $@
 	$(Q)$(MAKE) headers-y

+ 12 - 2
Makerules

@@ -91,6 +91,7 @@ pur_disp_ln        = echo "  "LN $@
 pur_disp_mkdir     = echo "  "MKDIR $@
 pur_disp_gen       = echo "  "GEN $@
 pur_disp_unifdef   = echo "  "UNIFDEF $@
+pur_disp_rm        = echo "  "CLEAN $($@)
 
 sil_disp_compile.c = true
 sil_disp_compile.i = true
@@ -109,6 +110,7 @@ sil_disp_ln        = true
 sil_disp_mkdir     = true
 sil_disp_gen       = true
 sil_disp_unifdef   = true
+sil_disp_rm        = true
 
 ver_disp_compile.c = echo $(cmd_compile.c)
 ver_disp_compile.i = echo $(cmd_compile.i)
@@ -127,6 +129,7 @@ ver_disp_ln        =
 ver_disp_mkdir     =
 ver_disp_gen       =
 ver_disp_unifdef   = echo $(cmd_unifdef)
+ver_disp_rm        = echo $(cmd_rm)
 
 disp_compile.c = $($(DISP)_disp_compile.c)
 disp_compile.i = $($(DISP)_disp_compile.i)
@@ -145,6 +148,7 @@ disp_ln        = $($(DISP)_disp_ln)
 disp_mkdir     = $($(DISP)_disp_mkdir)
 disp_gen       = $($(DISP)_disp_gen)
 disp_unifdef   = $($(DISP)_disp_unifdef)
+disp_rm        = $($(DISP)_disp_rm)
 
 any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
 
@@ -196,6 +200,12 @@ define do_ln
 	$(Q)$(LN) -fs
 endef
 
+
+#define RM
+#	@$(disp_rm)
+#	$(RM_COMMAND)
+#endef
+
 compile.c = @$(call maybe_exec,compile.c)
 compile.i =  $(call maybe_exec,compile.i)
 compile.s =  $(call maybe_exec,compile.s)
@@ -205,8 +215,8 @@ compile-m = @$(disp_compile-m) ; $(cmd_compile-m) ; $(cmd_t_strip)
 do_strip  = @$(disp_strip)     ; $(cmd_strip)
 do_t_strip= @$(disp_t_strip)   ; $(cmd_t_strip)
 do_unifdef= @$(disp_unifdef)   ; $(cmd_unifdef)
-hcompile.u= @$(call maybe_exec,hcompile.u)
-hcompile.o= @$(call maybe_exec,hcompile.o)
+hcompile.u= @$(disp_hcompile.u); $(cmd_hcompile.u)
+hcompile.o= @$(disp_hcompile.o); $(cmd_hcompile.o)
 
 define do_ar
 	@$(disp_ar) ; $(cmd_ar)

+ 1 - 1
extra/Configs/Config.in

@@ -730,7 +730,7 @@ config UCLIBC_LINUX_SPECIFIC
 	default y
 	help
 	  fstatfs(), inotify_*(), ioperm(), iopl(), madvise(), modify_ldt(),
-	  personality(), ppoll(), setresuid()
+	  personality(), ppoll(), setresuid(), signalfd()
 
 config UCLIBC_HAS_GNU_ERROR
 	bool "Support GNU extensions for error-reporting"

+ 71 - 47
extra/locale/Makefile.in

@@ -19,24 +19,24 @@ BUILD_CFLAGS-locale-common := \
 	-DUCLIBC_CTYPE_HEADER='"include/bits/uClibc_ctype.h"'
 
 BUILD_CFLAGS-gen_wc8bit := $(BUILD_CFLAGS-locale-common) -DCTYPE_PACKED=1
-
 BUILD_CFLAGS-gen_wctype := $(BUILD_CFLAGS-locale-common)
-
 BUILD_CFLAGS-gen_ldc :=
 ifeq ($(UCLIBC_HAS_WCHAR),y)
 BUILD_CFLAGS-gen_wc8bit += -DDO_WIDE_CHAR=1
 BUILD_CFLAGS-gen_ldc += -D__WCHAR_ENABLED=1
 endif
-
 BUILD_CFLAGS-gen_locale := -D_GNU_SOURCE -I$(locale_OUT)
 BUILD_CFLAGS-gen_collate := -D_GNU_SOURCE
 
-DEPH-locale := $(top_builddir)include/bits/sysnum.h
-DEPH-gen_locale := $(addprefix $(locale_OUT)/,c8tables.h) $(DEPH-locale)
+locale_headers-$(UCLIBC_HAS_LOCALE) := $(top_builddir)include/bits/uClibc_locale_data.h
+
+#DEPH-locale := $(top_builddir)include/bits/sysnum.h
+DEPH-locale := $(top_builddir)include/bits/uClibc_config.h
+DEPH-gen_collate := $(DEPH-locale)
 DEPH-gen_ldc := $(addprefix $(locale_OUT)/,c8tables.h wctables.h locale_tables.h locale_collate.h) $(DEPH-locale)
+DEPH-gen_locale := $(addprefix $(locale_OUT)/,c8tables.h) $(DEPH-locale)
 DEPH-gen_wc8bit := $(top_builddir)/include/bits/uClibc_ctype.h $(DEPH-locale)
 DEPH-gen_wctype := $(top_builddir)/include/bits/uClibc_ctype.h $(DEPH-locale)
-DEPH-gen_collate := $(DEPH-locale)
 
 locale_HOBJ := gen_collate gen_ldc gen_locale gen_wc8bit gen_wctype
 locale_HOBJ := $(addprefix $(locale_OUT)/,$(locale_HOBJ))
@@ -46,13 +46,14 @@ locale_OBJ := $(locale_OUT)/locale_data.o
 
 CFLAGS-locale_data.c := -D__WCHAR_ENABLED -I$(locale_OUT) -I$(locale_DIR)
 
-headers-$(UCLIBC_HAS_LOCALE) += $(top_builddir)include/bits/uClibc_locale_data.h
+#headers-$(UCLIBC_HAS_LOCALE) += $(locale_headers-y)
+headers: $(locale_headers-y)
 
 libc-$(UCLIBC_HAS_LOCALE) += $(locale_OBJ)
 
 libc-nomulti-$(UCLIBC_HAS_LOCALE) += $(locale_OBJ)
 
-locale_headers: $(top_builddir)include/bits/uClibc_locale_data.h
+locale_headers: headers $(top_builddir)include/bits/uClibc_locale_data.h
 
 # make sure that the host system has locales (this check is ok for uClibc/glibc)
 # we do not know though which locales were really enabled for libc at build time
@@ -64,7 +65,7 @@ $(locale_OUT)/codesets.txt:
 	    echo " "; \
 	    echo "You do not have a codesets.txt file.  Please create this "; \
 	    echo "file in the $(locale_OUT) directory by running something like: "; \
-	    echo "  cd $(locale_DIR) && find charmaps -name \"*.pairs\" > \\"; \
+	    echo "  cd $(locale_DIR)/ && find charmaps -name \"*.pairs\" > \\"; \
 	    echo "        $@"; \
 	    echo "and then edit that file to disable/enable the codesets you wish to support. "; \
 	    echo " "; \
@@ -89,70 +90,88 @@ $(locale_OUT)/locales.txt:
 else
 
 $(locale_OUT)/codesets.txt:
+	@$(disp_gen)
 ifeq ($(UCLIBC_BUILD_MINIMAL_LOCALE),y)
-	echo "charmaps/ASCII.pairs" > $@ ; \
-	echo "charmaps/ISO-8859-1.pairs" >> $@
+	$(Q)echo "charmaps/ASCII.pairs" > $@ ; \
+	$(Q)echo "charmaps/ISO-8859-1.pairs" >> $@
 else
-	(cd $(locale_DIR)/ && find charmaps/ -name '*.pairs' | sort ) > $@
+	$(Q)(cd $(locale_DIR)/ && find charmaps/ -name '*.pairs' | sort ) > $@
 endif
 
 # the lines beginning w/ '#-' are mandatory
 # at least one conversion is needed (euro/cyrillic)
 $(locale_OUT)/locales.txt: $(locale_DIR)/LOCALES
+	@$(disp_gen)
 ifeq ($(UCLIBC_BUILD_MINIMAL_LOCALE),y)
-	echo "@euro e" > $@ ; \
-	echo "#-" >> $@ ; \
-	echo "UTF-8 yes" >> $@ ; \
-	echo "8-BIT yes" >> $@ ; \
-	echo "#-" >> $@ ; \
-	echo "en_US.UTF-8 UTF-8" >> $@ ; \
-	echo "en_US ISO-8859-1" >> $@
+	$(Q)echo "@euro e" > $@ ; \
+	$(Q)echo "#-" >> $@ ; \
+	$(Q)echo "UTF-8 yes" >> $@ ; \
+	$(Q)echo "8-BIT yes" >> $@ ; \
+	$(Q)echo "#-" >> $@ ; \
+	$(Q)echo "en_US.UTF-8 UTF-8" >> $@ ; \
+	$(Q)echo "en_US ISO-8859-1" >> $@
 else
-	cp $< $@
+	$(Q)cat $< > $@
 endif
 
 endif
 
-# FIXME: Perhaps this would work with secondary expansion like approximately
-#$(locale_HOBJ): $(locale_OUT)/% : $(locale_DIR)/%.c | $$(DEPH-%)
-#	$(hcompile.u)
-
-$(locale_OUT)/gen_collate : $(locale_DIR)/gen_collate.c | $(DEPH-gen_collate)
+$(locale_DIR)/gen_collate.c: $(DEPH-gen_collate)
+$(locale_OUT)/gen_collate : $(locale_DIR)/gen_collate.c
 	$(hcompile.u)
-
-$(locale_OUT)/gen_ldc : $(locale_DIR)/gen_ldc.c | $(DEPH-gen_ldc)
+$(locale_DIR)/gen_ldc.c: $(DEPH-gen_ldc)
+$(locale_OUT)/gen_ldc : $(locale_DIR)/gen_ldc.c
 	$(hcompile.u)
-
-$(locale_OUT)/gen_locale : $(locale_DIR)/gen_locale.c | $(DEPH-gen_locale)
+$(locale_DIR)/gen_locale.c: $(DEPH-gen_locale)
+$(locale_OUT)/gen_locale : $(locale_DIR)/gen_locale.c
 	$(hcompile.u)
-
-$(locale_OUT)/gen_wc8bit : $(locale_DIR)/gen_wc8bit.c | $(DEPH-gen_wc8bit)
+$(locale_DIR)/gen_wc8bit.c: $(DEPH-gen_wc8bit)
+$(locale_OUT)/gen_wc8bit : $(locale_DIR)/gen_wc8bit.c
 	$(hcompile.u)
-
-$(locale_OUT)/gen_wctype : $(locale_DIR)/gen_wctype.c | $(DEPH-gen_wctype)
+$(locale_DIR)/gen_wctype.c: $(DEPH-gen_wctype)
+$(locale_OUT)/gen_wctype : $(locale_DIR)/gen_wctype.c
 	$(hcompile.u)
 
+ifneq ($(V),)
+ifeq ($(V),1)
+FLAG-locale-verbose := -v
+endif
+ifeq ($(V),2)
+FLAG-locale-verbose := -v -v
+endif
+endif
+
 # code needs to be modified to support top_builddir in almost all apps that write directly to a file
 # grep fopen *.c
 $(locale_OUT)/c8tables.h: $(locale_OUT)/gen_wc8bit $(locale_OUT)/codesets.txt
-	(cd $(<D) && ./$(<F) `cat $(word 2,$(^F))`)
+	@$(disp_gen)
+	$(Q)(cd $(<D) && ./$(<F) `cat $(word 2,$(^F))`)
 
 # Warning! Beware tr_TR toupper/tolower exceptions!
 $(locale_OUT)/wctables.h: $(locale_OUT)/gen_wctype
-	(cd $(<D) ; ./$(<F) en_US || ./$(<F) en_US.UTF-8 \
-	|| ./$(<F) en_US.iso8859-1 \
-	|| ./$(<F) en_GB || ./$(<F) en_GB.UTF-8)
+	@$(disp_gen)
+	$(Q)(cd $(<D) || exit 1 ; \
+		./$(<F) $(FLAG-locale-verbose) en_US || \
+		./$(<F) $(FLAG-locale-verbose) en_US.UTF-8 || \
+		./$(<F) $(FLAG-locale-verbose) en_US.iso8859-1 || \
+		./$(<F) $(FLAG-locale-verbose) en_GB || \
+		./$(<F) $(FLAG-locale-verbose) en_GB.UTF-8 \
+	)
 
 $(locale_OUT)/locale_tables.h: $(locale_OUT)/gen_locale $(locale_OUT)/locales.txt
-	$< $(word 2,$^) $@
+	@$(disp_gen)
+	$(Q)$< $(FLAG-locale-verbose) -o $@ $(word 2,$^)
 
 $(locale_OUT)/lt_defines.h: $(locale_OUT)/locale_tables.h $(locale_OUT)/locale_collate.h
-	grep "^#define" $< > $@
-	grep "^#define __lc" $(word 2,$^) >> $@
+	@$(disp_gen)
+	$(Q)grep "^#define" $< > $@
+	$(Q)grep "^#define __lc" $(word 2,$^) >> $@
 
 $(locale_OUT)/locale_collate.h: $(locale_OUT)/gen_collate $(locale_OUT)/locale_tables.h
-	grep COL_IDX_ $(word 2,$^) | $(SED) -e "s/^.*COL_IDX_\([^, ]*\).*$$/\1/" | \
-		sort | uniq | (cd $(<D) && xargs ./$(<F))
+	@$(disp_gen)
+	$(Q)grep COL_IDX_ $(word 2,$^) | \
+		$(SED) -e "s/^.*COL_IDX_\([^, ]*\).*$$/\1/" | sort | uniq | \
+		xargs $< $(locale_DIR)/collation $(FLAG-locale-verbose) -o $@
 
 $(locale_OUT)/$(LOCALE_DATA_FILENAME):
 ifeq ($(UCLIBC_DOWNLOAD_PREGENERATED_LOCALE_DATA),y)
@@ -167,23 +186,28 @@ $(locale_SRC): $(locale_OUT)/$(LOCALE_DATA_FILENAME)
 	# we use the one in locale_DIR
 	#$(RM) $(locale_OUT)/locale_mmap.h
 
-# for arch specific versions we have to at least overwrite lt_defines.h/locale_data.c/uClibc_locale_data.h
+# for arch specific versions we have to at least overwrite
+# lt_defines.h/locale_data.c/uClibc_locale_data.h
 
 $(locale_OUT)/uClibc_locale_data.h: $(locale_SRC)
 
 else
 
 $(locale_SRC): $(locale_OUT)/gen_ldc $(locale_OUT)/lt_defines.h
-	$< $@
+	@$(disp_gen)
+	$(Q)$< $@
 
 $(locale_OUT)/uClibc_locale_data.h: $(locale_OUT)/lt_defines.h $(locale_OUT)/c8tables.h $(locale_OUT)/wctables.h $(locale_DIR)/locale_mmap.h | $(locale_SRC)
-	grep -v "define __LC" $< > $@
-	cat $(wordlist 2,4,$^) >> $@
+	@$(disp_gen)
+	$(Q)grep -v "define __LC" $< > $@
+	$(Q)cat $(wordlist 2,4,$^) >> $@
 
 endif
 
 $(top_builddir)include/bits/uClibc_locale_data.h: $(locale_OUT)/uClibc_locale_data.h | $(top_builddir)include/bits/uClibc_config.h
-	cat $< | $(AWK) 'BEGIN{i=1}{ if ( /WANT_/ ) i = /endif/ ; else if (i) print $0 }' > $@
+	@$(disp_gen)
+	$(Q)$(AWK) 'BEGIN{i=1}{if (/WANT_/) i=/endif/;else if (i) print $0}' \
+		$< > $@
 
 objclean-y += locale_clean
 

+ 148 - 86
extra/locale/gen_collate.c

@@ -1,3 +1,12 @@
+/*
+ * Usage:
+ * gen_collate <INPUTDIR> [-o OUTPUTFILE] LOCALE ...
+ *
+ * Generate collation data from locales LOCALE.
+ * Reads all LOCALE from INPUTDIR and writes collation data to OUTPUTFILE.
+ *
+ * The output file defaults to "locales_collate.h".
+ */
 /* TODO:
  *
  * add UNDEFINED at end if not specified
@@ -24,6 +33,7 @@
 #include <limits.h>
 #include <ctype.h>
 #include <assert.h>
+#include <errno.h>
 #include <search.h>
 
 typedef struct {
@@ -253,6 +263,14 @@ static void *root_sym = NULL;
 static size_t num_sym = 0;
 static size_t mem_sym = 0;
 
+static const char *inputdir;
+static size_t inputdir_len;
+static unsigned verbose = 0;
+enum {
+	VINFO = (1<<0),
+	VDETAIL = (1<<1),
+};
+
 static void error_msg(const char *fmt, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
 static void *xmalloc(size_t n);
 static char *xsymdup(const char *s); /* only allocate once... store in a tree */
@@ -294,6 +312,18 @@ enum {
 	DT_RANGE = 0x10,
 };
 
+static int verbose_msg(const unsigned lvl, const char *fmt, ...)
+{
+	va_list arg;
+	int ret = 0;
+
+	if (verbose & lvl) {
+		va_start(arg, fmt);
+		ret = vfprintf(stderr, fmt, arg);
+		va_end(arg);
+	}
+	return ret;
+}
 static section_t *new_section(const char *name)
 {
 	section_t *p;
@@ -310,7 +340,7 @@ static section_t *new_section(const char *name)
 		++anonsection;
 	}
 #warning devel code
-/* 	fprintf(stderr, "section %s\n", name); */
+/* 	verbose_msg(VDETAIL, "section %s\n", name); */
 	p->name = xsymdup(name);
 	p->itm_list = NULL;
 	p->num_items = 0;
@@ -328,7 +358,7 @@ static section_t *new_section(const char *name)
 		p->rules[3] |= R_POSITION;
 		cur_rule[3] |= R_POSITION;
 	}
-/* 	fprintf(stderr, "new section %s -- cur_num_weights = %d\n", p->name, cur_num_weights); */
+/* 	verbose_msg(VDETAIL, "new section %s -- cur_num_weights = %d\n", p->name, cur_num_weights); */
 
 	return p;
 }
@@ -379,7 +409,7 @@ static void do_unrecognized(void)
 #if 1
     error_msg("warning: unrecognized: %s", pos);
 #else
-/*     fprintf(stderr, "warning: unrecognized initial keyword \"%s\"\n", pos); */
+/*     verbose_msg(VDETAIL, "warning: unrecognized initial keyword \"%s\"\n", pos); */
 	fprintf(stderr, "warning: unrecognized: %s", pos);
 	if (end_of_token) {
 		fprintf(stderr, "%c%s", end_of_token, pos_e+1);
@@ -587,10 +617,10 @@ static void add_superset_weight(char *t)
 			lli = new_ll_item(DT_REORDER, cur_section);
 			lli->prev = lli->next = lli;
 			insque(lli, comm_prev_ptr);
-/* 			fprintf(stderr, "  subsection -----------------------\n"); */
+/* 			verbose_msg(VDETAIL, "  subsection -----------------------\n"); */
 		}
 
-/* 		fprintf(stderr, "     %s   %s\n", t, ((weighted_item_t *)(comm_cur_ptr->data))->symbol); */
+/* 		verbose_msg(VDETAIL, "     %s   %s\n", t, ((weighted_item_t *)(comm_cur_ptr->data))->symbol); */
 		wi = add_weight(t);
 		lli = new_ll_item(DT_WEIGHTED, wi);
 		mark_reordered(wi->symbol);
@@ -745,7 +775,7 @@ static void processfile(void)
 	}
 
 	if (cur_base == cur_col) {
-		fprintf(stderr, "Base: %15s", cur_col->name);
+		verbose_msg(VDETAIL, "Base: %15s", cur_col->name);
 	} else {
 #if 1
 		if (!cur_col->undefined_idx) {
@@ -794,20 +824,21 @@ static void processfile(void)
 		}
 #endif
 
-		fprintf(stderr, " Der: %15s", cur_col->name);
+		verbose_msg(VDETAIL, " Der: %15s", cur_col->name);
 	}
 	{
+#if 0
 		ll_item_t *p = cur_col->section_list;
-
-		fprintf(stderr, "%6u weights", tnumnodes(cur_col->root_wi_index));
+#endif
+		verbose_msg(VDETAIL, "%6u weights", tnumnodes(cur_col->root_wi_index));
 		if (cur_base) {
-			fprintf(stderr, "  %6u der %6u reor %6u starter - %u new stubs",
+			verbose_msg(VDETAIL, "  %6u der %6u reor %6u starter - %u new stubs",
 					tnumnodes(cur_base->root_derived_wi),
 					tnumnodes(cur_base->root_wi_index_reordered),
 					tnumnodes(cur_base->root_starter_char),
 					ll_count(cur_col->section_list, DT_REORDER));
 		}
-		fprintf(stderr, "\n");
+		verbose_msg(VDETAIL, "\n");
 
 #if 0
 		while (p) {
@@ -826,7 +857,7 @@ static void processfile(void)
 				if ((*((section_t *)(p->data))->name != 'a')
 					|| (((section_t *)(p->data))->num_items > 0)
 					) {
-					fprintf(stderr,
+					verbose_msg(VDETAIL,
 /* 							"\t%-15s %zu\n", */
 							"\t%-15s %6u\n",
 							((section_t *)(p->data))->name,
@@ -1089,18 +1120,35 @@ int main(int argc, char **argv)
 	ll_item_t *lli;
 	int i;
 	int total;
+	char *output_file = "locale_collate.h";
+	unsigned verbosity = 0;
 
-	if (argc < 2) {
+	if (argc < 3) {
 		return EXIT_FAILURE;
 	}
-
+	--argc;
+	inputdir = strdup(*++argv);
+	inputdir_len = strlen(inputdir);
 	init_locale_list();
 
 	while (--argc) {
-		p = (const deps_t *) bsearch(*++argv, deps, sizeof(deps)/sizeof(deps[0]), sizeof(deps[0]), dep_cmp);
+		++argv;
+		if (!strcmp(*argv, "-o")) {
+			--argc;
+			if (*++argv == NULL) {
+				printf("-o <outfile> requires an argument\n");
+				return EXIT_FAILURE;
+			}
+			output_file = strdup(*argv);
+			continue;
+		} else if (!strcmp(*argv, "-v")) {
+			verbosity++;
+			continue;
+		}
+		p = (const deps_t *) bsearch(*argv, deps, sizeof(deps)/sizeof(deps[0]), sizeof(deps[0]), dep_cmp);
 		if (!p) {
 			if (!strcmp("C", *argv)) {
-				printf("ignoring C locale\n");
+				printf("ignoring %s locale\n", *argv);
 				continue;
 			} else {
 				printf("%s not found\n", *argv);
@@ -1125,10 +1173,10 @@ int main(int argc, char **argv)
 
 	total = 0;
 	for (i=0 ; i < BASE_MAX ; i++) {
-/* 		printf("der_count[%2d] = %3d\n", i, der_count[i]); */
+/*		printf("der_count[%2d] = %3d\n", i, der_count[i]); */
 		total += der_count[i];
 	}
-/* 	printf("total = %d\n", total); */
+/*	printf("total = %d\n", total); */
 
 	new_args[new_arg_count++] = "dummyprogramname";
 	for (i=0 ; i < BASE_MAX ; i++) {
@@ -1143,11 +1191,16 @@ int main(int argc, char **argv)
 		} while (lli != locale_list[i]);
 		new_args[new_arg_count++] = "-f";
 	}
+	for (i=0; i < verbosity; i++)
+		new_args[new_arg_count++] = "-v";
 
-/* 	for (i=0 ; i < new_arg_count ; i++) { */
-/* 		printf("%3d: %s\n", i, new_args[i]); */
-/* 	} */
-
+	new_args[new_arg_count++] = "-o";
+	new_args[new_arg_count++] = output_file;
+/*
+	for (i=0 ; i < new_arg_count ; i++) {
+		printf("%3d: %s\n", i, new_args[i]);
+	}
+*/
 	return old_main(new_arg_count, (char **) new_args);
 }
 
@@ -1158,6 +1211,7 @@ static int old_main(int argc, char **argv)
 {
 	int next_is_base = 0;
 	int next_is_subset = 0;
+	char *output_file = NULL;
 
 	superset = 0;
 
@@ -1185,6 +1239,11 @@ static int old_main(int argc, char **argv)
 				next_is_subset = 0;
 				next_is_base = 2;
 				superset = 0;
+			} else if (((*argv)[1] == 'o') && !(*argv)[2]) { /* output file */
+				--argc;
+				output_file = *++argv;
+			} else if (((*argv)[1] == 'v') && !(*argv)[2]) { /* verbose */
+				++verbose;
 			} else {
 				error_msg("unrecognized option %s", *argv);
 			}
@@ -1198,7 +1257,7 @@ static int old_main(int argc, char **argv)
 			cur_derived = cur_col;
 		}
 		pushfile(*argv);
-/* 		fprintf(stderr, "processing file %s\n", *argv); */
+/* 		verbose_msg(VDETAIL, "processing file %s\n", *argv); */
 		processfile();			/* this does a popfile */
 
 /* 		twalk(cur_col->root_colitem, print_colnode); */
@@ -1212,17 +1271,17 @@ static int old_main(int argc, char **argv)
 		}
 	}
 
-	fprintf(stderr, "success!\n");
-	fprintf(stderr,
+	verbose_msg(VINFO, "success!\n");
+	verbose_msg(VINFO,
 /* 			"num_sym=%zu mem_sym=%zu  unique_weights=%zu\n", */
 			"num_sym=%u mem_sym=%u  unique_weights=%u\n",
 			num_sym, mem_sym, unique_weights);
 /* 	twalk(root_weight, print_weight_node); */
 
-	fprintf(stderr, "num base locales = %d    num derived locales = %d\n",
+	verbose_msg(VINFO, "num base locales = %d    num derived locales = %d\n",
 			base_locale_len, der_locale_len);
 
-	fprintf(stderr,
+	verbose_msg(VINFO,
 			"override_len = %d      multistart_len = %d    weightstr_len = %d\n"
 			"wcs2colidt_len = %d    index2weight_len = %d  index2ruleidx_len = %d\n"
 			"ruletable_len = %d\n"
@@ -1250,10 +1309,10 @@ static int old_main(int argc, char **argv)
 #endif
 
 	{
-		FILE *fp = fopen("locale_collate.h", "w");
+		FILE *fp = fopen(output_file, "w");
 
 		if (!fp) {
-			error_msg("cannot open output file!");
+			error_msg("cannot open output file '%s'!", output_file);
 		}
 		dump_collate(fp);
 		if (ferror(fp) || fclose(fp)) {
@@ -1282,20 +1341,23 @@ static void error_msg(const char *fmt, ...)
 
 static void pushfile(char *filename)
 {
-	static char fbuf[PATH_MAX];
-
-	snprintf(fbuf, PATH_MAX, "collation/%s", filename);
+	char *inputfile;
+	size_t inputfile_len;
 
 	if (fno >= MAX_FNO) {
 		error_msg("file stack size exceeded");
 	}
 
-	if (!(fstack[++fno] = fopen(fbuf, "r"))) {
+	inputfile_len = inputdir_len + strlen(filename) + 2;
+	inputfile = xmalloc(inputfile_len);
+	memset(inputfile, 0, inputfile_len);
+	sprintf(inputfile, "%s/%s", inputdir, filename);
+	if (!(fstack[++fno] = fopen(inputfile, "r"))) {
 		--fno;					/* oops */
-		error_msg("cannot open file %s", fbuf);
+		error_msg("cannot open file %s: %s", inputfile, strerror(errno));
 	}
 
-	fname[fno] = xsymdup(filename);
+	fname[fno] = xsymdup(inputfile);
 	lineno[fno] = 0;
 }
 
@@ -1452,11 +1514,11 @@ static void do_copy(void)
 			*e = 0;
 			++s;
 			if (cur_base && !strcmp(cur_base->name,s)) {
-/* 				fprintf(stderr, "skipping copy of base file %s\n", s); */
+/* 				verbose_msg(VDETAIL, "skipping copy of base file %s\n", s); */
 #warning need to update last in order and position or check
 				return;
 			}
-/* 			fprintf(stderr, "full copy of %s\n", s); */
+/* 			verbose_msg(VDETAIL, "full copy of %s\n", s); */
 			pushfile(s);
 			return;
 		}
@@ -1541,7 +1603,7 @@ static ll_item_t *find_section_list_item(const char *name, col_locale_t *loc)
 	while (p) {
 #warning devel code
 /* 		if (!((p->data_type == DT_SECTION) || (p->data_type == DT_REORDER))) { */
-/* 			fprintf(stderr, "fsli = %d\n", p->data_type); */
+/* 			verbose_msg(VDETAIL, "fsli = %d\n", p->data_type); */
 /* 		} */
 		assert((p->data_type == DT_SECTION) || (p->data_type == DT_REORDER));
 		if (!strcmp(name, ((section_t *)(p->data))->name)) {
@@ -1685,11 +1747,11 @@ static void add_colitem(char *item, char *def)
 #warning devel code
 	if (superset) {
 		if (tfind(p, &cur_base->root_colitem, colitem_cmp)) {
-/* 			fprintf(stderr, "skipping superset duplicate collating item \"%s\"\n", p->string); */
+/* 			verbose_msg(VDETAIL, "skipping superset duplicate collating item \"%s\"\n", p->string); */
 			del_colitem(p);
 			return;
 /* 		} else { */
-/* 			fprintf(stderr, "superset: new collating item \"%s\" = %s\n", p->string, p->element); */
+/* 			verbose_msg(VDETAIL, "superset: new collating item \"%s\" = %s\n", p->string, p->element); */
 		}
 	}
 
@@ -1850,7 +1912,7 @@ static void do_order_start(void)
 
 	cur_section = sect;
 
-/* 	fprintf(stderr, "setting cur_num_weights to %d for %s\n", sect->num_rules, sect->name); */
+/* 	verbose_msg(VDETAIL, "setting cur_num_weights to %d for %s\n", sect->num_rules, sect->name); */
 	cur_num_weights = sect->num_rules;
 	memcpy(cur_rule, sect->rules, MAX_COLLATION_WEIGHTS);
 }
@@ -1923,7 +1985,7 @@ static void do_reorder_after(void)
 		insque(l1, l2);
 		l3 = find_ll_last(cur_col->section_list);
 
-		fprintf(stderr, "reorder_after %p %p %p %s\n", l1, l2, l3, cur_section->name);
+		verbose_msg(VDETAIL, "reorder_after %p %p %p %s\n", l1, l2, l3, cur_section->name);
 	}
 #else
 	insque(new_ll_item(DT_REORDER, cur_section), find_ll_last(cur_col->section_list));
@@ -1935,7 +1997,7 @@ static void do_reorder_after(void)
 
 
 #warning devel code
-/* 	fprintf(stderr, "reorder -- %s %d\n", ((weighted_item_t *)(lli->data))->symbol, w->num_weights); */
+/* 	verbose_msg(VDETAIL, "reorder -- %s %d\n", ((weighted_item_t *)(lli->data))->symbol, w->num_weights); */
 
 #warning hack to get around hu_HU reorder-after problem
 /* 	if (!w->num_weights) { */
@@ -1945,7 +2007,7 @@ static void do_reorder_after(void)
 /* 		memcpy(cur_rule, w->rule, MAX_COLLATION_WEIGHTS); */
 /* 	}	 */
 
-/* 	fprintf(stderr, "reorder_after succeeded for %s\n", t); */
+/* 	verbose_msg(VDETAIL, "reorder_after succeeded for %s\n", t); */
 }
 
 static void do_reorder_end(void)
@@ -1986,9 +2048,9 @@ static void do_reorder_sections_after(void)
 
 	lli = cur_base->section_list;
 	do {
-/* 		fprintf(stderr, "hmm -- |%s|%d|\n", ((section_t *)(lli->data))->name, lli->data_type); */
+/* 		verbose_msg(VDETAIL, "hmm -- |%s|%d|\n", ((section_t *)(lli->data))->name, lli->data_type); */
 		if (lli->data_type & DT_SECTION) {
-/* 			fprintf(stderr, "checking |%s|%s|\n", ((section_t *)(lli->data))->name, t); */
+/* 			verbose_msg(VDETAIL, "checking |%s|%s|\n", ((section_t *)(lli->data))->name, t); */
 			if (!strcmp(((section_t *)(lli->data))->name, t)) {
 				reorder_section_ptr = lli;
 				return;
@@ -2025,7 +2087,7 @@ static ll_item_t *new_ll_item(int data_type, void *data)
 
 static int sym_cmp(const void *n1, const void *n2)
 {
-/* 	fprintf(stderr, "sym_cmp: |%s| |%s|\n", (const char *)n1, (const char *)n2); */
+/* 	verbose_msg(VDETAIL, "sym_cmp: |%s| |%s|\n", (const char *)n1, (const char *)n2); */
     return strcmp((const char *) n1, (const char *) n2);
 }
 
@@ -2039,9 +2101,9 @@ static char *xsymdup(const char *s)
 		}
 		++num_sym;
 		mem_sym += strlen(s) + 1;
-/* 		fprintf(stderr, "xsymdup: alloc |%s| %p |%s| %p\n", *(char **)p, p, s, s); */
+/* 		verbose_msg(VDETAIL, "xsymdup: alloc |%s| %p |%s| %p\n", *(char **)p, p, s, s); */
 /* 	} else { */
-/* 		fprintf(stderr, "xsymdup: found |%s| %p\n", *(char **)p, p); */
+/* 		verbose_msg(VDETAIL, "xsymdup: found |%s| %p\n", *(char **)p, p); */
 	}
 	return *(char **) p;
 }
@@ -2079,7 +2141,7 @@ static weight_t *register_weight(weight_t *w)
 		}
 		++unique_weights;
 /* 	} else { */
-/* 		fprintf(stderr, "rw: found\n"); */
+/* 		verbose_msg(VDETAIL, "rw: found\n"); */
 	}
 	return *(weight_t **)p;
 }
@@ -2200,7 +2262,7 @@ static void add_final_col_index(const char *s)
 					ci.element = NULL; /* don't care */
 					v = tfind(&ci, &cur_base->root_colitem, colitem_cmp);
 					if (!v) {
-						fprintf(stderr, "%s  NOT DEFINED!!!\n", s);
+						verbose_msg(VDETAIL, "%s  NOT DEFINED!!!\n", s);
 					} else {
 						p = *((colitem_t **) v);
 						if (p->element != NULL) {
@@ -2347,11 +2409,11 @@ static ll_item_t *init_comm_ptr(void)
 #warning devel code
 /* 	{ */
 /* 		ll_item_t *p = comm_cur_ptr; */
-/* 		fprintf(stderr, "init_comm_ptr\n"); */
+/* 		verbose_msg(VDETAIL, "init_comm_ptr\n"); */
 
 /* 		while (p != comm_cur_ptr) { */
 /* 			if (p->data_type & DT_WEIGHTED) { */
-/* 				fprintf(stderr, "%s", ((weighted_item_t *)p)->symbol); */
+/* 				verbose_msg(VDETAIL, "%s", ((weighted_item_t *)p)->symbol); */
 /* 			} */
 /* 			p = p->next; */
 /* 		} */
@@ -2359,7 +2421,7 @@ static ll_item_t *init_comm_ptr(void)
 
 	assert(comm_cur_ptr);
 
-/* 	fprintf(stderr, "init_comm_ptr -- %s %p %p %p %d\n", */
+/* 	verbose_msg(VDETAIL, "init_comm_ptr -- %s %p %p %p %d\n", */
 /* 			((weighted_item_t *)(comm_cur_ptr->data))->symbol, */
 /* 			comm_cur_ptr, comm_cur_ptr->prev, comm_cur_ptr->next, */
 /* 			ll_len(comm_cur_ptr)); */
@@ -2625,7 +2687,7 @@ static void finalize_base(void)
 	for (s = cur_base->section_list ; s ; s = s->next) {
 #if 1
 		if (s->data_type & DT_REORDER) { /* a reordered section */
-			fprintf(stderr, "pass1: reordered section %s - xxx\n", ((section_t *)(s->data))->name);
+			verbose_msg(VDETAIL, "pass1: reordered section %s - xxx\n", ((section_t *)(s->data))->name);
 			lli = ((section_t *)(s->data))->itm_list;
 			r = 0;
 			if (lli) {
@@ -2635,7 +2697,7 @@ static void finalize_base(void)
 			if (r > mr) {
 				mr = r;
 			}
-			fprintf(stderr, "pass1: reordered section %s - %d\n", ((section_t *)(s->data))->name, r);
+			verbose_msg(VDETAIL, "pass1: reordered section %s - %d\n", ((section_t *)(s->data))->name, r);
 			continue;
 		}
 #endif
@@ -2652,11 +2714,11 @@ static void finalize_base(void)
 				lli->idx = i;
 				assert(!rli);
 				rli = lli;
-				fprintf(stderr, "range pre = %d  after = ", i);
+				verbose_msg(VDETAIL, "range pre = %d  after = ", i);
 				i += ((range_item_t *)(lli->data))->length + 1;
 #warning check ko_kR and 9
 /* 				++i; */
-				fprintf(stderr, "%d\n", i);
+				verbose_msg(VDETAIL, "%d\n", i);
 				if (!index2weight_len_inc) { /* ko_KR hack */
 					final_index += ((range_item_t *)(lli->data))->length + 1;
 				}
@@ -2726,7 +2788,7 @@ static void finalize_base(void)
 /* 						cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */
 
 			} else {
-/* 				fprintf(stderr, "section: %s  %d  %d\n", ((section_t *)(s->data))->name, */
+/* 				verbose_msg(VDETAIL, "section: %s  %d  %d\n", ((section_t *)(s->data))->name, */
 /* 						s->data_type, lli->data_type); */
 /* 					assert(!(s->data_type & DT_REORDER)); */
 /* 				assert(lli->data_type & DT_REORDER); */
@@ -2772,7 +2834,7 @@ static void finalize_base(void)
 	mr = mi;
 	for (cli = cur_base->derived_list ; cli ; cli = cli->next) {
 		cl = (col_locale_t *)(cli->data);
-/* 		fprintf(stderr, "pass3: %d  %s\n", cli->data_type, cl->name); */
+/* 		verbose_msg(VDETAIL, "pass3: %d  %s\n", cli->data_type, cl->name); */
 
 /* 		fprintf(stdout, "pass3: %d  %s\n", cli->data_type, cl->name); */
 
@@ -2790,7 +2852,7 @@ static void finalize_base(void)
 			do {
 				assert(!(lli->data_type & DT_RANGE));
 				if (lli->data_type & DT_WEIGHTED) {
-/* 					fprintf(stderr, "     %d %d %s\n", lli->data_type, lli->idx, ((weighted_item_t *)(lli->data))->symbol); */
+/* 					verbose_msg(VDETAIL, "     %d %d %s\n", lli->data_type, lli->idx, ((weighted_item_t *)(lli->data))->symbol); */
 					add_final_col_index(((weighted_item_t *)(lli->data))->symbol);
 					if (s->data_type & DT_REORDER) {
 						continue;
@@ -2850,10 +2912,10 @@ static void finalize_base(void)
 				++wcs2index_count;
 				if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) {
 					wcs2index[i] = ++starter_index;
-/* 					fprintf(stderr, "wcs2index[ %#06x ] = %d  (starter)\n", i, wcs2index[i]); */
+/* 					verbose_msg(VDETAIL, "wcs2index[ %#06x ] = %d  (starter)\n", i, wcs2index[i]); */
 				} else {
 					wcs2index[i] = (int)(p->data);
-/* 					fprintf(stderr, "wcs2index[ %#06x ] = %d\n", i, wcs2index[i]); */
+/* 					verbose_msg(VDETAIL, "wcs2index[ %#06x ] = %d\n", i, wcs2index[i]); */
 				}
 			} else {
 				if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) {
@@ -2898,7 +2960,7 @@ static void finalize_base(void)
 			smallest = newopt(wcs2index, RANGE, n, &table);
 			assert(t == smallest);
 			wcs2colidt_len += smallest;
-/* 			fprintf(stderr, "smallest = %d   wcs2colidt_len = %d\n", smallest, wcs2colidt_len); */
+/* 			verbose_msg(VDETAIL, "smallest = %d   wcs2colidt_len = %d\n", smallest, wcs2colidt_len); */
 
 #if 0
 			{
@@ -2919,15 +2981,15 @@ static void finalize_base(void)
 				u >>= __LOCALE_DATA_WCctype_II_SHIFT;
 
 				i0 = tbl->ii[u];
-				fprintf(stderr, "i0 = %d\n", i0);
+				verbose_msg(VDETAIL, "i0 = %d\n", i0);
 				i0 <<= __LOCALE_DATA_WCctype_II_SHIFT;
 				i1 = tbl->ii[__LOCALE_DATA_WCctype_II_LEN + i0 + n];
 				/* 	i1 = tbl->ti[i0 + n]; */
-				fprintf(stderr, "i1 = %d\n", i1);
+				verbose_msg(VDETAIL, "i1 = %d\n", i1);
 				i1 <<= __LOCALE_DATA_WCctype_TI_SHIFT;
 				/* 	return *(uint16_t *)(&(tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc])); */
-				fprintf(stderr, "i2 = %d\n", __LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc);
-				fprintf(stderr, "val = %d\n",  tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc]);
+				verbose_msg(VDETAIL, "i2 = %d\n", __LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc);
+				verbose_msg(VDETAIL, "val = %d\n",  tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc]);
 				/* 	return tbl->ut[i1 + sc]; */
 
 
@@ -2944,7 +3006,7 @@ static void finalize_base(void)
 		base_locale_array[base_locale_len].max_col_index = final_index;
 		base_locale_array[base_locale_len].max_weight = max_weight;
 
-		fprintf(stderr, "%s: %6u invariant  %6u varying  %6u derived  %6u total  %6u max weight  %6u wcs2\n",
+		verbose_msg(VDETAIL, "%s: %6u invariant  %6u varying  %6u derived  %6u total  %6u max weight  %6u wcs2\n",
 				cur_base->name, num_invariant, num_varying,
 				tnumnodes(cur_base->root_derived_wi), final_index, max_weight,
 				wcs2index_count);
@@ -2960,7 +3022,7 @@ static void finalize_base(void)
 	for (s = cur_base->section_list ; s ; s = s->next) {
 #if 1
 		if (s->data_type & DT_REORDER) {
-			fprintf(stderr, "1: skipping reordered section %s\n", ((section_t *)(s->data))->name);
+			verbose_msg(VDETAIL, "1: skipping reordered section %s\n", ((section_t *)(s->data))->name);
 			continue;
 		}
 #endif
@@ -2988,7 +3050,7 @@ static void finalize_base(void)
 	for (s = cur_base->section_list ; s ; s = s->next) {
 #if 1
 		if (s->data_type & DT_REORDER) {
-			fprintf(stderr, "2: skipping reordered section %s\n", ((section_t *)(s->data))->name);
+			verbose_msg(VDETAIL, "2: skipping reordered section %s\n", ((section_t *)(s->data))->name);
 			continue;
 		}
 #endif
@@ -3015,7 +3077,7 @@ static void finalize_base(void)
 	do_starter_lists(cur_base);
 
 
-/* 	fprintf(stderr,"updated final_index = %d\n", final_index); */
+/* 	verbose_msg(VDETAIL,"updated final_index = %d\n", final_index); */
 
 	if (rli) {
 		base_locale_array[base_locale_len].range_low
@@ -3042,8 +3104,8 @@ static void finalize_base(void)
 		&& isupper(cur_base->name[4])
 		) {
 
-		fprintf(stderr, "adding special derived for %s\n", cur_base->name);
-/* 	fprintf(stderr,"updated final_index = %d\n", final_index); */
+		verbose_msg(VDETAIL, "adding special derived for %s\n", cur_base->name);
+/* 	verbose_msg(VDETAIL,"updated final_index = %d\n", final_index); */
 
 
 		assert(der_locale_len+1 < DER_LOCALE_LEN);
@@ -3080,7 +3142,7 @@ static void finalize_base(void)
 
 		++der_locale_len;
 	} else {
-		fprintf(stderr, "NOT adding special derived for %s\n", cur_base->name);
+		verbose_msg(VDETAIL, "NOT adding special derived for %s\n", cur_base->name);
 	}
 
 	/* now all the derived... */
@@ -3102,7 +3164,7 @@ static void finalize_base(void)
 			}
 			/* we do this in two passes... first all sequences, then all single reorders */
 			for (s = cl->section_list ; s ; s = s->next) {
-/* 				fprintf(stderr, "doing section %s\n", ((section_t *)(s->data))->name); */
+/* 				verbose_msg(VDETAIL, "doing section %s\n", ((section_t *)(s->data))->name); */
 				h = lli = ((section_t *)(s->data))->itm_list;
 				if (!lli) {
 /* 					fprintf(stdout, "EMPTY ITEM LIST IN SECTION %s\n", ((section_t *)(s->data))->name ); */
@@ -3195,7 +3257,7 @@ static void finalize_base(void)
 	++base_locale_len;
 
 /* 	if (tnumnodes(cur_base->root_starter_char)) { */
-/* 		fprintf(stderr, "starter nodes\n"); */
+/* 		verbose_msg(VDETAIL, "starter nodes\n"); */
 /* 		twalk(cur_base->root_starter_char, print_starter_node); */
 /* 	} */
 }
@@ -3287,7 +3349,7 @@ static void process_starter_node(const void *ptr, VISIT order, int level)
 			if (++u16_starter < base_locale_array[base_locale_len].num_starters) {
 				u16_buf[u16_starter] = u16_buf_len;
 			}
-/* 			fprintf(stderr, "ucode - %d %d\n", u16_buf[u16_starter-1], u16_buf_len); */
+/* 			verbose_msg(VDETAIL, "ucode - %d %d\n", u16_buf[u16_starter-1], u16_buf_len); */
 		} else {
 			x.string = w->symbol;
 			x.element = NULL;
@@ -3299,7 +3361,7 @@ static void process_starter_node(const void *ptr, VISIT order, int level)
 			assert(u16_buf[u16_buf_len-1]);
 			assert(*s == '"');
 			n = is_ucode(++s);
-/* 			fprintf(stderr, "s is |%s| with len %d (%d)\n", s, strlen(s), n); */
+/* 			verbose_msg(VDETAIL, "s is |%s| with len %d (%d)\n", s, strlen(s), n); */
 			assert(n);
 			s += n;
 			while (*s != '"') {
@@ -3307,7 +3369,7 @@ static void process_starter_node(const void *ptr, VISIT order, int level)
 				assert(n);
 				strncpy(buf, s, n+1);
 				buf[n] = 0;
-/* 				fprintf(stderr, "buf is |%s| with len %d (%d)\n", buf, strlen(buf), n); */
+/* 				verbose_msg(VDETAIL, "buf is |%s| with len %d (%d)\n", buf, strlen(buf), n); */
 				u16_buf[u16_buf_len++] = final_index_val(buf);
 				assert(u16_buf[u16_buf_len-1]);
 				s += n;
@@ -3331,7 +3393,7 @@ static void complete_starter_node(const void *ptr, VISIT order, int level)
 			p = xmalloc(sizeof(weighted_item_t));
 			p->symbol = w.symbol;
 			p->weight = NULL;
-/* 			fprintf(stderr, "complete_starter_node: %s\n", *(const char **) ptr); */
+/* 			verbose_msg(VDETAIL, "complete_starter_node: %s\n", *(const char **) ptr); */
 			if (!tsearch(p, p_cl_root_starter_all, starter_all_cmp)) {
 				error_msg("OUT OF MEMORY");
 			}
@@ -3377,7 +3439,7 @@ static void do_starter_lists(col_locale_t *cl)
 					x.element = NULL;
 					p = tfind(&x, &cur_base->root_colitem, colitem_cmp);
 					if (!p) {
-/* 						fprintf(stderr, "Whoa... processing starters for %s and couldn't find %s\n", */
+/* 						verbose_msg(VDETAIL, "Whoa... processing starters for %s and couldn't find %s\n", */
 /* 								cl->name, w->symbol); */
 						continue;
 					}
@@ -3426,13 +3488,13 @@ static void do_starter_lists(col_locale_t *cl)
 	u16_starter = 0;
 	u16_buf[0] = u16_buf_len = base_locale_array[base_locale_len].num_starters;
 	twalk(cl->root_starter_all, process_starter_node);
-/* 	fprintf(stderr, "s=%d n=%d\n", u16_starter,  base_locale_array[base_locale_len].num_starters); */
+/* 	verbose_msg(VDETAIL, "s=%d n=%d\n", u16_starter,  base_locale_array[base_locale_len].num_starters); */
 	assert(u16_starter == base_locale_array[base_locale_len].num_starters);
 
 #if 0
 	{ int i;
 	for (i=0 ; i < u16_buf_len ; i++) {
-		fprintf(stderr, "starter %2d: %d - %#06x\n", i, u16_buf[i], u16_buf[i]);
+		verbose_msg(VDETAIL, "starter %2d: %d - %#06x\n", i, u16_buf[i], u16_buf[i]);
 	}}
 #endif
 
@@ -3451,7 +3513,7 @@ static void do_starter_lists(col_locale_t *cl)
 				der_locale_array[der_locale_len].multistart_offset = multistart_len;
 			}
 			multistart_len += u16_buf_len;
-/* 			fprintf(stderr, "%s: multistart_len = %d   u16_buf_len = %d\n", cl->name, multistart_len, u16_buf_len); */
+/* 			verbose_msg(VDETAIL, "%s: multistart_len = %d   u16_buf_len = %d\n", cl->name, multistart_len, u16_buf_len); */
 		} else if (!(u16_buf_len > multistart_len)) {
 			assert(mm);
 			if (cl == cur_base) {
@@ -3459,7 +3521,7 @@ static void do_starter_lists(col_locale_t *cl)
 			} else {
 				der_locale_array[der_locale_len].multistart_offset = ((uint16_t *)(mm)) - multistart_buffer;
 			}
-/* 			fprintf(stderr, "%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */
+/* 			verbose_msg(VDETAIL, "%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */
 		}
 	} else {
 		assert(!base_locale_array[base_locale_len].num_starters);

+ 120 - 104
extra/locale/gen_locale.c

@@ -4,6 +4,7 @@
 #include <ctype.h>
 #include <limits.h>
 #include <assert.h>
+#include <stdarg.h>
 #include <locale.h>
 #include <langinfo.h>
 #include <nl_types.h>
@@ -15,7 +16,7 @@
 #define __LOCALE_DATA_CATEGORIES 6
 
 /* must agree with ordering of gen_mmap! */
-static const unsigned char *lc_names[] = {
+static const char *lc_names[] = {
 	"LC_CTYPE",
 	"LC_NUMERIC",
 	"LC_MONETARY",
@@ -89,6 +90,41 @@ static int default_8bit;
 static int total_size;
 static int null_count;
 
+static unsigned verbose = 0;
+enum {
+	VINFO = (1<<0),
+	VDETAIL = (1<<1),
+};
+static int verbose_msg(const unsigned lvl, const char *fmt, ...)
+{
+	va_list arg;
+	int ret = 0;
+
+	if (verbose & lvl) {
+		va_start(arg, fmt);
+		ret = vfprintf(stderr, fmt, arg);
+		va_end(arg);
+	}
+	return ret;
+}
+
+static void error_msg(const char *fmt, ...)  __attribute__ ((noreturn, format (printf, 1, 2)));
+static void error_msg(const char *fmt, ...)
+{
+	va_list arg;
+
+	fprintf(stderr, "Error: ");
+/*	if (fno >= 0) {
+	    fprintf(stderr, "file %s (%d): ", fname[fno], lineno[fno]);
+	} */
+	va_start(arg, fmt);
+	vfprintf(stderr, fmt, arg);
+	va_end(arg);
+	fprintf(stderr, "\n");
+
+	exit(EXIT_FAILURE);
+}
+
 static void do_locale_names(void)
 {
 	/* "C" locale name is handled specially by the setlocale code. */
@@ -96,8 +132,7 @@ static void do_locale_names(void)
 	int i;
 
 	if (num_locales <= 1) {
-/*  		printf("error - only C locale?\n"); */
-/*  		exit(EXIT_FAILURE); */
+/*		error_msg("only C locale?"); */
 		fprintf(ofp, "static const unsigned char __locales[%d];\n", (3 + __LOCALE_DATA_CATEGORIES));
 		fprintf(ofp, "static const unsigned char __locale_names5[5];\n");
 	} else {
@@ -131,8 +166,7 @@ static void do_locale_names(void)
 			} else if (!strcmp(locales[i].glibc_name, "C")) {
 			    fprintf(ofp, "COL_IDX_C    , ");
 			} else {
-			    printf("don't know how to handle COL_IDX_ for %s\n", locales[i].glibc_name);
-			    exit(EXIT_FAILURE);
+			    error_msg("don't know how to handle COL_IDX_ for %s", locales[i].glibc_name);
 			}
 #else
 			fprintf(ofp, "%#4x, ", 0); /* place holder for lc_collate */
@@ -196,8 +230,7 @@ static void do_locale_names(void)
 				}
 			}
 			if (pos[__LOCALE_DATA_CATEGORIES-1] > 255) {
-				printf("error - lc_names is too big (%d)\n", pos[__LOCALE_DATA_CATEGORIES-1]);
-				exit(EXIT_FAILURE);
+				error_msg("lc_names is too big (%d)", pos[__LOCALE_DATA_CATEGORIES-1]);
 			}
 			fprintf(ofp, "#define __LC_ALL\t\t%d\n\n", i);
 
@@ -218,7 +251,7 @@ static void do_locale_names(void)
 			fprintf(ofp, ";\n\n");
 		}
 
-		printf("locale data = %d  name data = %d for %d uniq\n",
+		verbose_msg(VDETAIL,"locale data = %d  name data = %d for %d uniq\n",
 			   num_locales * (3 + __LOCALE_DATA_CATEGORIES), uniq * 5, uniq);
 
 		total_size += num_locales * (3 + __LOCALE_DATA_CATEGORIES) + uniq * 5;
@@ -236,8 +269,7 @@ static void read_at_mappings(void)
 		if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) {
 			if (!fgets(line_buf, sizeof(line_buf), fp)) {
 				if (ferror(fp)) {
-					printf("error reading file\n");
-					exit(EXIT_FAILURE);
+					error_msg("reading file");
 				}
 				return;			/* EOF */
 			}
@@ -248,17 +280,14 @@ static void read_at_mappings(void)
 		}
 		if (*p == '@') {
 			if (p[1] == 0) {
-				printf("error: missing @modifier name\n");
-				exit(EXIT_FAILURE);
+				error_msg("missing @modifier name");
 			}
 			m = p;				/* save the modifier name */
 			if (!(p = strtok(NULL, " \t\n")) || p[1] || (((unsigned char) *p) > 0x7f)) {
-				printf("error: missing or illegal @modifier mapping char\n");
-				exit(EXIT_FAILURE);
+				error_msg("missing or illegal @modifier mapping char");
 			}
 			if (at_mappings[(int)((unsigned char) *p)]) {
-				printf("error: reused @modifier mapping char\n");
-				exit(EXIT_FAILURE);
+				error_msg("reused @modifier mapping char");
 			}
 			at_mappings[(int)((unsigned char) *p)] = 1;
 			at_mapto[mc] = *p;
@@ -267,10 +296,10 @@ static void read_at_mappings(void)
 			strcpy(++at_strings_end, m+1);
 			at_strings_end += (unsigned char) at_strings_end[-1];
 
-			printf("@mapping: \"%s\" to '%c'\n", m, *p);
+			verbose_msg(VDETAIL,"@mapping: \"%s\" to '%c'\n", m, *p);
 
 			if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
-				printf("ignoring trailing text: %s...\n", p);
+				fprintf(stderr,"ignoring trailing text: %s...\n", p);
 			}
 			*line_buf = 0;
 			continue;
@@ -283,12 +312,12 @@ static void read_at_mappings(void)
 		p = at_strings;
 
 		if (!*p) {
-			printf("no @ strings\n");
+			verbose_msg(VDETAIL,"no @ strings\n");
 			return;
 		}
 
 		do {
-			printf("%s\n", p+1);
+			verbose_msg(VDETAIL,"%s\n", p+1);
 			p += 1 + (unsigned char) *p;
 		} while (*p);
 	}
@@ -303,8 +332,7 @@ static void read_enable_disable(void)
 		if (!(p = strtok(line_buf, " =\t\n")) || (*p == '#')) {
 			if (!fgets(line_buf, sizeof(line_buf), fp)) {
 				if (ferror(fp)) {
-					printf("error reading file\n");
-					exit(EXIT_FAILURE);
+					error_msg("reading file");
 				}
 				return;			/* EOF */
 			}
@@ -316,25 +344,23 @@ static void read_enable_disable(void)
 		if (!strcmp(p, "UTF-8")) {
 			if (!(p = strtok(NULL, " =\t\n"))
 				|| ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) {
-				printf("error: missing or illegal UTF-8 setting\n");
-				exit(EXIT_FAILURE);
+				error_msg("missing or illegal UTF-8 setting");
 			}
 			default_utf8 = (toupper(*p) == 'Y');
-			printf("UTF-8 locales are %sabled\n", "dis\0en"+ (default_utf8 << 2));
+			verbose_msg(VINFO,"UTF-8 locales are %sabled\n", "dis\0en"+ (default_utf8 << 2));
 		} else if (!strcmp(p, "8-BIT")) {
 			if (!(p = strtok(NULL, " =\t\n"))
 				|| ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) {
-				printf("error: missing or illegal 8-BIT setting\n");
-				exit(EXIT_FAILURE);
+				error_msg("missing or illegal 8-BIT setting");
 			}
 			default_8bit = (toupper(*p) == 'Y');
-			printf("8-BIT locales are %sabled\n", "dis\0en" + (default_8bit << 2));
+			verbose_msg(VINFO,"8-BIT locales are %sabled\n", "dis\0en" + (default_8bit << 2));
 		} else {
 			break;
 		}
 
 		if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
-			printf("ignoring trailing text: %s...\n", p);
+			fprintf(stderr,"ignoring trailing text: %s...\n", p);
 		}
 		*line_buf = 0;
 		continue;
@@ -354,13 +380,12 @@ static int find_codeset_num(const char *cs)
 	if (strcmp(cs, "UTF-8") != 0) {
 		++r;
 		while (*s && strcmp(__LOCALE_DATA_CODESET_LIST+ ((unsigned char) *s), cs)) {
-/*  			printf("tried %s\n", __LOCALE_DATA_CODESET_LIST + ((unsigned char) *s)); */
+/*  			verbose_msg(VDETAIL,"tried %s\n", __LOCALE_DATA_CODESET_LIST + ((unsigned char) *s)); */
 			++r;
 			++s;
 		}
 		if (!*s) {
-			printf("error: unsupported codeset %s\n", cs);
-			exit(EXIT_FAILURE);
+			error_msg("unsupported codeset %s", cs);
 		}
 	}
 	return r;
@@ -375,8 +400,7 @@ static int find_codeset_num(const char *cs)
 	/* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */
 
 	if (strcmp(cs, "UTF-8") != 0) {
-		printf("error: unsupported codeset %s\n", cs);
-		exit(EXIT_FAILURE);
+		error_msg("unsupported codeset %s", cs);
 	}
 	return r;
 }
@@ -396,8 +420,7 @@ static int find_at_string_num(const char *as)
 		p += 1 + (unsigned char) *p;
 	}
 
-	printf("error: unmapped @string %s\n", as);
-	exit(EXIT_FAILURE);
+	error_msg("error: unmapped @string %s", as);
 }
 
 static void read_locale_list(void)
@@ -429,8 +452,7 @@ static void read_locale_list(void)
 		if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) {
 			if (!fgets(line_buf, sizeof(line_buf), fp)) {
 				if (ferror(fp)) {
-					printf("error reading file\n");
-					exit(EXIT_FAILURE);
+					error_msg("reading file");
 				}
 				return;			/* EOF */
 			}
@@ -448,7 +470,7 @@ static void read_locale_list(void)
 			s += 1 + ((unsigned char) *s);
 		}
 		if (i < num_locales) {
-			printf("ignoring dulplicate locale name: %s", p);
+			fprintf(stderr,"ignoring duplicate locale name: %s", p);
 			*line_buf = 0;
 			continue;
 		}
@@ -460,24 +482,23 @@ static void read_locale_list(void)
 		ln = p;					/* save locale name */
 
 		if (!(p = strtok(NULL, " \t\n"))) {
-			printf("error: missing codeset for locale %s\n", ln);
-			exit(EXIT_FAILURE);
+			error_msg("missing codeset for locale %s", ln);
 		}
 		cs = p;
 		i = find_codeset_num(p);
 		if ((i == 2) && !default_utf8) {
-			printf("ignoring UTF-8 locale %s\n", ln);
+			fprintf(stderr,"ignoring UTF-8 locale %s\n", ln);
 			*line_buf = 0;
 			continue;
 		} else if ((i > 2) && !default_8bit) {
-			printf("ignoring 8-bit codeset locale %s\n", ln);
+			fprintf(stderr,"ignoring 8-bit codeset locale %s\n", ln);
 			*line_buf = 0;
 			continue;
 		}
 		locales[num_locales].cs = (char)((unsigned char) i);
 
 		if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) {
-			printf("ignoring trailing text: %s...\n", p);
+			verbose_msg(VINFO,"ignoring trailing text: %s...\n", p);
 		}
 
 		/* Now go back to locale string for .codeset and @modifier */
@@ -492,19 +513,18 @@ static void read_locale_list(void)
 		ls = ln;
 
 		if ((strlen(ls) != 5) || (ls[2] != '_')) {
-			printf("error: illegal locale name %s\n", ls);
-			exit(EXIT_FAILURE);
+			error_msg("illegal locale name %s", ls);
 		}
 
 		i = 0;					/* value for unspecified codeset */
 		if (ds) {
 			i = find_codeset_num(ds);
 			if ((i == 2) && !default_utf8) {
-				printf("ignoring UTF-8 locale %s\n", ln);
+				fprintf(stderr,"ignoring UTF-8 locale %s\n", ln);
 				*line_buf = 0;
 				continue;
 			} else if ((i > 2) && !default_8bit) {
-				printf("ignoring 8-bit codeset locale %s\n", ln);
+				fprintf(stderr,"ignoring 8-bit codeset locale %s\n", ln);
 				*line_buf = 0;
 				continue;
 			}
@@ -516,7 +536,7 @@ static void read_locale_list(void)
 			ls[2] = at_mapto[i];
 		}
 		memcpy(locales[num_locales].name, ls, 5);
-/*  		printf("locale: %5.5s %2d %2d %s\n", */
+/*  		verbose_msg(VDETAIL,"locale: %5.5s %2d %2d %s\n", */
 /*  			   locales[num_locales].name, */
 /*  			   locales[num_locales].cs, */
 /*  			   locales[num_locales].dot_cs, */
@@ -554,11 +574,24 @@ static int le_cmp(const void *a, const void *b)
 
 int main(int argc, char **argv)
 {
-	char *output_file = "locale_tables.h";
-	if ((argc < 2 || argc > 3) || (!(fp = fopen(*++argv, "r")))) {
-		printf("error: missing filename or file!\n");
-		return EXIT_FAILURE;
+	char *output_file = NULL;
+
+	while (--argc) {
+		++argv;
+		if (!strcmp(*argv, "-o")) {
+			--argc;
+			output_file = strdup(*++argv);
+		} else if (!strcmp(*argv, "-v")) {
+			verbose++;
+		} else if (!(fp = fopen(*argv, "r"))) {
+no_inputfile:
+				error_msg("missing filename or file!");
+		}
 	}
+	if (fp == NULL)
+		goto no_inputfile;
+	if (output_file == NULL)
+		output_file = strdup("locale_tables.h");
 
 	at_strings_end = at_strings;
 
@@ -573,7 +606,7 @@ int main(int argc, char **argv)
 
 #if 0
 	for (i=0 ; i < num_locales ; i++) {
-		printf("locale: %5.5s %2d %2d %s\n",
+		verbose_msg(VDETAIL,"locale: %5.5s %2d %2d %s\n",
 			   locales[i].name,
 			   locales[i].cs,
 			   locales[i].dot_cs,
@@ -584,9 +617,7 @@ int main(int argc, char **argv)
 	if (argc == 3)
 		output_file = *++argv;
 	if (output_file == NULL || !(ofp = fopen(output_file, "w"))) {
-		printf("cannot open output file '%s'!\n",
-			output_file);
-		return EXIT_FAILURE;
+		error_msg("cannot open output file '%s'!", output_file);
 	}
 
 	do_lc_time();
@@ -599,8 +630,8 @@ int main(int argc, char **argv)
 
 	fclose(ofp);
 
-	printf("total data size = %d\n", total_size);
-	printf("null count = %d\n", null_count);
+	verbose_msg(VINFO, "total data size = %d\n", total_size);
+	verbose_msg(VDETAIL, "null count = %d\n", null_count);
 
 	return EXIT_SUCCESS;
 }
@@ -625,12 +656,10 @@ static int addblock(const char *s, size_t n) /* l includes nul terminator */
 		}
 	}
 	if (uniq >= sizeof(idx)) {
-		printf("too many uniq strings!\n");
-		exit(EXIT_FAILURE);
+		error_msg("too many uniq strings!");
 	}
 	if (last + n >= buf + sizeof(buf)) {
-		printf("need to increase size of buf!\n");
-		exit(EXIT_FAILURE);
+		error_msg("need to increase size of buf!");
 	}
 
 	idx[uniq] = last;
@@ -656,13 +685,11 @@ static int addstring(const char *s)
 		}
 	}
 	if (uniq >= sizeof(idx)) {
-		printf("too many uniq strings!\n");
-		exit(EXIT_FAILURE);
+		error_msg("too many uniq strings!");
 	}
 	l = strlen(s) + 1;
 	if (last + l >= buf + sizeof(buf)) {
-		printf("need to increase size of buf!\n");
-		exit(EXIT_FAILURE);
+		error_msg("need to increase size of buf!");
 	}
 
 	idx[uniq] = last;
@@ -673,9 +700,9 @@ static int addstring(const char *s)
 }
 
 #define DO_LC_COMMON(CATEGORY) \
-	printf("buf-size=%d  uniq=%d  rows=%d\n", \
+	verbose_msg(VDETAIL, "buf-size=%d  uniq=%d  rows=%d\n", \
 		   (int)(last - buf), uniq, lc_##CATEGORY##_uniq); \
-	printf("total = %d + %d * %d + %d = %d\n", \
+	verbose_msg(VDETAIL, "total = %d + %d * %d + %d = %d\n", \
 		   num_locales, lc_##CATEGORY##_uniq, NUM_NL_##CATEGORY, (int)(last - buf), \
 		   i = num_locales + lc_##CATEGORY##_uniq*NUM_NL_##CATEGORY + (int)(last - buf)); \
 	total_size += i; \
@@ -704,8 +731,7 @@ static int addstring(const char *s)
 
 #define DL_LC_LOOPTAIL(CATEGORY) \
 		if (k > NUM_NL_##CATEGORY) { \
-			printf("error -- lc_" #CATEGORY " nl_item count > %d!\n", NUM_NL_##CATEGORY); \
-			exit(EXIT_FAILURE); \
+			error_msg("lc_" #CATEGORY " nl_item count > %d!", NUM_NL_##CATEGORY); \
 		} \
 		{ \
 			int r; \
@@ -718,8 +744,7 @@ static int addstring(const char *s)
 			if (r == lc_##CATEGORY##_uniq) { /* new locale row */ \
 				++lc_##CATEGORY##_uniq; \
 				if (lc_##CATEGORY##_uniq > 255) { \
-					printf("too many unique lc_" #CATEGORY " rows!\n"); \
-					exit(EXIT_FAILURE); \
+					error_msg("too many unique lc_" #CATEGORY " rows!"); \
 				} \
 			} \
 			locales[i].lc_##CATEGORY##_row = r; \
@@ -784,8 +809,7 @@ static void dump_table16(const char *name, const int *tbl, int len)
 			fprintf(ofp, "\n\t");
 		}
 		if (tbl[i] != (uint16_t) tbl[i]) {
-			printf("error - falls outside uint16 range!\n");
-			exit(EXIT_FAILURE);
+			error_msg("falls outside uint16 range!");
 		}
 		fprintf(ofp, "%#6x, ", tbl[i]);
 	}
@@ -826,7 +850,7 @@ static void lc_time_S(int X, int k)
 			len = p - s;
 		}
 		j = addblock(s, len);
-/* 		if (len > 1) fprintf(stderr, "alt_digit: called addblock with len %zd\n", len); */
+/* 		if (len > 1) verbose_msg(VDETAIL, "alt_digit: called addblock with len %zd\n", len); */
 	} else if (X == ERA) {
 		if (!s) {
 			s = nulbuf;
@@ -840,7 +864,7 @@ static void lc_time_S(int X, int k)
 		}
 		++p;
 		j = addblock(s, p - s);
-/* 		if (p-s > 1) fprintf(stderr, "era: called addblock with len %d\n", p-s); */
+/* 		if (p-s > 1) verbose_msg(VDETAIL, "era: called addblock with len %d\n", p-s); */
 	} else {
 		j = addstring(s);
 	}
@@ -851,8 +875,7 @@ static void lc_time_S(int X, int k)
 	}
 	if (m == lc_time_count[k]) { /* new for this nl_item */
 		if (m > 255) {
-			printf("too many nl_item %d entries in lc_time\n", k);
-			exit(EXIT_FAILURE);
+			error_msg("too many nl_item %d entries in lc_time", k);
 		}
 		lc_time_item[k][m] = j;
 		++lc_time_count[k];
@@ -873,7 +896,7 @@ static void do_lc_time(void)
 		k = 0;
 
 		if (!setlocale(LC_ALL, locales[i].glibc_name)) {
-			printf("setlocale(LC_ALL,%s) failed!\n",
+			verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n",
 				   locales[i].glibc_name);
 		}
 
@@ -976,8 +999,7 @@ static void lc_numeric_S(int X, int k)
 				++e;
 			}
 			if ((e - s) > sizeof(buf)) {
-				printf("grouping specifier too long\n");
-				exit(EXIT_FAILURE);
+				error_msg("grouping specifier too long");
 			}
 			strncpy(buf, s, (e-s));
 			e = buf + (e-s);
@@ -1003,13 +1025,12 @@ static void lc_numeric_S(int X, int k)
 	}
 	if (m == lc_numeric_count[k]) { /* new for this nl_item */
 		if (m > 255) {
-			printf("too many nl_item %d entries in lc_numeric\n", k);
-			exit(EXIT_FAILURE);
+			error_msg("too many nl_item %d entries in lc_numeric", k);
 		}
 		lc_numeric_item[k][m] = j;
 		++lc_numeric_count[k];
 	}
-/*  	printf("\\x%02x", m); */
+/*  	verbose_msg(VDETAIL, "\\x%02x", m); */
 	lc_numeric_uniq_X[lc_numeric_uniq][k] = m;
 }
 
@@ -1026,7 +1047,7 @@ static void do_lc_numeric(void)
 		k = 0;
 
 		if (!setlocale(LC_ALL, locales[i].glibc_name)) {
-			printf("setlocale(LC_ALL,%s) failed!\n",
+			verbose_msg(VDETAIL,"setlocale(LC_ALL,%s) failed!\n",
 				   locales[i].glibc_name);
 		}
 
@@ -1051,7 +1072,7 @@ static int lc_monetary_uniq;
 
 #define DO_NL_S(X)	lc_monetary_S(X, k++)
 
-/*  #define DO_NL_C(X)		printf("%#02x", (int)(unsigned char)(*nl_langinfo(X))); */
+/*  #define DO_NL_C(X)		verbose_msg(VDETAIL,"%#02x", (int)(unsigned char)(*nl_langinfo(X))); */
 #define DO_NL_C(X) lc_monetary_C(X, k++)
 
 static void lc_monetary_C(int X, int k)
@@ -1071,13 +1092,12 @@ static void lc_monetary_C(int X, int k)
 	}
 	if (m == lc_monetary_count[k]) { /* new for this nl_item */
 		if (m > 255) {
-			printf("too many nl_item %d entries in lc_monetary\n", k);
-			exit(EXIT_FAILURE);
+			error_msg("too many nl_item %d entries in lc_monetary", k);
 		}
 		lc_monetary_item[k][m] = j;
 		++lc_monetary_count[k];
 	}
-/*  	printf("\\x%02x", m); */
+/*  	verbose_msg(VDETAIL,"\\x%02x", m); */
 	lc_monetary_uniq_X[lc_monetary_uniq][k] = m;
 }
 
@@ -1107,8 +1127,7 @@ static void lc_monetary_S(int X, int k)
 				++e;
 			}
 			if ((e - s) > sizeof(buf)) {
-				printf("mon_grouping specifier too long\n");
-				exit(EXIT_FAILURE);
+				error_msg("mon_grouping specifier too long");
 			}
 			strncpy(buf, s, (e-s));
 			e = buf + (e-s);
@@ -1134,13 +1153,12 @@ static void lc_monetary_S(int X, int k)
 	}
 	if (m == lc_monetary_count[k]) { /* new for this nl_item */
 		if (m > 255) {
-			printf("too many nl_item %d entries in lc_monetary\n", k);
-			exit(EXIT_FAILURE);
+			error_msg("too many nl_item %d entries in lc_monetary", k);
 		}
 		lc_monetary_item[k][m] = j;
 		++lc_monetary_count[k];
 	}
-/*  	printf("\\x%02x", m); */
+/*  	verbose_msg(VDETAIL,"\\x%02x", m); */
 	lc_monetary_uniq_X[lc_monetary_uniq][k] = m;
 }
 
@@ -1157,7 +1175,7 @@ static void do_lc_monetary(void)
 		k = 0;
 
 		if (!setlocale(LC_ALL, locales[i].glibc_name)) {
-			printf("setlocale(LC_ALL,%s) failed!\n",
+			verbose_msg(VDETAIL,"setlocale(LC_ALL,%s) failed!\n",
 				   locales[i].glibc_name);
 		}
 
@@ -1216,13 +1234,12 @@ static void lc_messages_S(int X, int k)
 	}
 	if (m == lc_messages_count[k]) { /* new for this nl_item */
 		if (m > 255) {
-			printf("too many nl_item %d entries in lc_messages\n", k);
-			exit(EXIT_FAILURE);
+			error_msg("too many nl_item %d entries in lc_messages", k);
 		}
 		lc_messages_item[k][m] = j;
 		++lc_messages_count[k];
 	}
-/*  	printf("\\x%02x", m); */
+/*  	verbose_msg(VDETAIL, "\\x%02x", m); */
 	lc_messages_uniq_X[lc_messages_uniq][k] = m;
 }
 
@@ -1239,7 +1256,7 @@ static void do_lc_messages(void)
 		k = 0;
 
 		if (!setlocale(LC_ALL, locales[i].glibc_name)) {
-			printf("setlocale(LC_ALL,%s) failed!\n",
+			verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n",
 				   locales[i].glibc_name);
 		}
 
@@ -1276,13 +1293,12 @@ static void lc_ctype_S(int X, int k)
 	}
 	if (m == lc_ctype_count[k]) { /* new for this nl_item */
 		if (m > 255) {
-			printf("too many nl_item %d entries in lc_ctype\n", k);
-			exit(EXIT_FAILURE);
+			error_msg("too many nl_item %d entries in lc_ctype", k);
 		}
 		lc_ctype_item[k][m] = j;
 		++lc_ctype_count[k];
 	}
-/*  	printf("\\x%02x", m); */
+/*  	verbose_msg(VDETAIL, "\\x%02x", m); */
 	lc_ctype_uniq_X[lc_ctype_uniq][k] = m;
 }
 
@@ -1299,7 +1315,7 @@ static void do_lc_ctype(void)
 		k = 0;
 
 		if (!setlocale(LC_ALL, locales[i].glibc_name)) {
-			printf("setlocale(LC_ALL,%s) failed!\n",
+			verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n",
 				   locales[i].glibc_name);
 		}
 

+ 50 - 44
extra/locale/gen_wctype.c

@@ -159,6 +159,8 @@ typedef struct {
 	unsigned char *ut;
 } table_data;
 
+static unsigned verbose;
+#define verbose_msg(msg...) if (verbose) fprintf(stderr, msg)
 
 void output_table(FILE *fp, const char *name, table_data *tbl)
 {
@@ -200,7 +202,7 @@ void output_table(FILE *fp, const char *name, table_data *tbl)
 
 static void dump_table_data(table_data *tbl)
 {
-	printf("ii_shift = %d  ti_shift = %d\n"
+	verbose_msg("ii_shift = %d  ti_shift = %d\n"
 		   "ii_len = %d  ti_len = %d  ut_len = %d\n"
 		   "total = %d\n",
 		   tbl->ii_shift, tbl->ti_shift,
@@ -279,19 +281,23 @@ int main(int argc, char **argv)
 	setvbuf(stdout, NULL, _IONBF, 0);
 
 	while (--argc) {
-		if (!setlocale(LC_CTYPE, *++argv)) {
-			printf("setlocale(LC_CTYPE,%s) failed!  Skipping this locale...\n", *argv);
+		++argv;
+		if (!strcmp(*argv, "-v")) {
+			++verbose;
+			continue;
+		} else if (!setlocale(LC_CTYPE, *argv)) {
+			verbose_msg("setlocale(LC_CTYPE,%s) failed!  Skipping this locale...\n", *argv);
 			continue;
 		}
 
 		if (!(totitle = wctrans("totitle"))) {
-			printf("no totitle transformation.\n");
+			verbose_msg("no totitle transformation.\n");
 		}
 		if (!(is_comb = wctype("combining"))) {
-			printf("no combining wctype.\n");
+			verbose_msg("no combining wctype.\n");
 		}
 		if (!(is_comb3 = wctype("combining_level3"))) {
-			printf("no combining_level3 wctype.\n");
+			verbose_msg("no combining_level3 wctype.\n");
 		}
 
 		if (!built) {
@@ -351,9 +357,9 @@ int main(int argc, char **argv)
 #if 0
 			if (iswspace(c)) {
 				if (iswblank(c)) {
-					printf("%#8x : space  blank\n", c);
+					verbose_msg("%#8x : space  blank\n", c);
 				} else {
-					printf("%#8x : space\n", c);
+					verbose_msg("%#8x : space\n", c);
 				}
 			}
 #endif
@@ -375,7 +381,7 @@ int main(int argc, char **argv)
 				if (isspace(c)) ++glibc; glibc <<= 1;
 				if (isupper(c)) ++glibc; glibc <<= 1;
 				if (isxdigit(c)) ++glibc;
-				printf("%#8x : ctype %#4x\n", c, glibc);
+				verbose_msg("%#8x : ctype %#4x\n", c, glibc);
 			}
 #endif
 
@@ -414,14 +420,14 @@ int main(int argc, char **argv)
 				if (mywxdigit(c)) ++mine;
 
 				if (glibc != mine) {
-					printf("%#8x : glibc %#4x != %#4x mine  %u\n", c, glibc, mine, d);
+					verbose_msg("%#8x : glibc %#4x != %#4x mine  %u\n", c, glibc, mine, d);
 					return EXIT_FAILURE;
 				}
 
 #if 0
 				if (iswctype(c,is_comb) || iswctype(c,is_comb3)) {
 /*  					if (!iswpunct(c)) { */
-						printf("%#8x : %d %d %#4x\n",
+						verbose_msg("%#8x : %d %d %#4x\n",
 							   c, iswctype(c,is_comb),iswctype(c,is_comb3), glibc);
 /*  					} */
 				}
@@ -429,10 +435,10 @@ int main(int argc, char **argv)
 #if 0
 				if (iswctype(c,is_comb) || iswctype(c,is_comb3)) {
 					if (!last_comb) {
-						printf("%#8x - ", c);
+						verbose_msg("%#8x - ", c);
 						last_comb = c;
 					} else if (last_comb + 1 < c) {
-						printf("%#8x\n%#8x - ", last_comb, c);
+						verbose_msg("%#8x\n%#8x - ", last_comb, c);
 						last_comb = c;
 					} else {
 						last_comb = c;
@@ -458,7 +464,7 @@ int main(int argc, char **argv)
 			ult[c] = 0;
 			if (l || u) {
 				if ((l != (short)l) || (u != (short)u)) {
-					printf("range assumption error!  %x  %ld  %ld\n", c, l, u);
+					verbose_msg("range assumption error!  %x  %ld  %ld\n", c, l, u);
 					return EXIT_FAILURE;
 				}
 				for (i=0 ; i < ul_count ; i++) {
@@ -470,7 +476,7 @@ int main(int argc, char **argv)
 				uldiff[ul_count].u = u;
 				++ul_count;
 				if (ul_count > MAXTO) {
-					printf("too many touppers/tolowers!\n");
+					verbose_msg("too many touppers/tolowers!\n");
 					return EXIT_FAILURE;
 				}
 			found:
@@ -479,10 +485,10 @@ int main(int argc, char **argv)
 		}
 
 		for (i = 0 ; i < 16 ; i++) {
-			printf("typecount[%2d] = %8ld  %s\n", i, typecount[i], typename[i]);
+			verbose_msg("typecount[%2d] = %8ld  %s\n", i, typecount[i], typename[i]);
 		}
 
-		printf("optimizing is* table..\n");
+		verbose_msg("optimizing is* table..\n");
 		n = -1;
 		smallest = SIZE_MAX;
 		cttable.ii = NULL;
@@ -495,9 +501,9 @@ int main(int argc, char **argv)
 /*  				break; */
 			}
 		}
-		printf("smallest = %zu\n", smallest);
+		verbose_msg("smallest = %zu\n", smallest);
 		if (!(cttable.ii = malloc(smallest))) {
-			printf("couldn't allocate space!\n");
+			verbose_msg("couldn't allocate space!\n");
 			return EXIT_FAILURE;
 		}
 		smallest = SIZE_MAX;
@@ -506,7 +512,7 @@ int main(int argc, char **argv)
 
 
 
-		printf("optimizing u/l-to table..\n");
+		verbose_msg("optimizing u/l-to table..\n");
 		smallest = SIZE_MAX;
 		ultable.ii = NULL;
 		for (i=0 ; i < 14 ; i++) {
@@ -518,11 +524,11 @@ int main(int argc, char **argv)
 /*  				break; */
 			}
 		}
-		printf("%zu (smallest) + %zu (u/l diffs) = %zu\n",
+		verbose_msg("%zu (smallest) + %zu (u/l diffs) = %zu\n",
 			   smallest, 4 * ul_count, smallest + 4 * ul_count);
-		printf("smallest = %zu\n", smallest);
+		verbose_msg("smallest = %zu\n", smallest);
 		if (!(ultable.ii = malloc(smallest))) {
-			printf("couldn't allocate space!\n");
+			verbose_msg("couldn't allocate space!\n");
 			return EXIT_FAILURE;
 		}
 		smallest = SIZE_MAX;
@@ -530,7 +536,7 @@ int main(int argc, char **argv)
 
 
 #if 0
-		printf("optimizing comb table..\n");
+		verbose_msg("optimizing comb table..\n");
 		smallest = SIZE_MAX;
 		combtable.ii = NULL;
 		for (i=0 ; i < 14 ; i++) {
@@ -542,9 +548,9 @@ int main(int argc, char **argv)
 /*  				break; */
 			}
 		}
-		printf("smallest = %zu\n", smallest);
+		verbose_msg("smallest = %zu\n", smallest);
 		if (!(combtable.ii = malloc(smallest))) {
-			printf("couldn't allocate space!\n");
+			verbose_msg("couldn't allocate space!\n");
 			return EXIT_FAILURE;
 		}
 		smallest = SIZE_MAX;
@@ -554,7 +560,7 @@ int main(int argc, char **argv)
 
 
 #if 0
-		printf("optimizing width table..\n");
+		verbose_msg("optimizing width table..\n");
 		smallest = SIZE_MAX;
 		widthtable.ii = NULL;
 		for (i=0 ; i < 14 ; i++) {
@@ -566,9 +572,9 @@ int main(int argc, char **argv)
 /*  				break; */
 			}
 		}
-		printf("smallest = %zu\n", smallest);
+		verbose_msg("smallest = %zu\n", smallest);
 		if (!(widthtable.ii = malloc(smallest))) {
-			printf("couldn't allocate space!\n");
+			verbose_msg("couldn't allocate space!\n");
 			return EXIT_FAILURE;
 		}
 		smallest = SIZE_MAX;
@@ -577,7 +583,7 @@ int main(int argc, char **argv)
 #endif
 
 #if 0
-		printf("optimizing comb3 table..\n");
+		verbose_msg("optimizing comb3 table..\n");
 		smallest = SIZE_MAX;
 		comb3table.ii = NULL;
 		for (i=0 ; i < 14 ; i++) {
@@ -589,9 +595,9 @@ int main(int argc, char **argv)
 /*  				break; */
 			}
 		}
-		printf("smallest = %zu\n", smallest);
+		verbose_msg("smallest = %zu\n", smallest);
 		if (!(comb3table.ii = malloc(smallest))) {
-			printf("couldn't allocate space!\n");
+			verbose_msg("couldn't allocate space!\n");
 			return EXIT_FAILURE;
 		}
 		smallest = SIZE_MAX;
@@ -606,7 +612,7 @@ int main(int argc, char **argv)
 #endif
 		}
 
-		printf("verifying for %s...\n", *argv);
+		verbose_msg("verifying for %s...\n", *argv);
 #if RANGE == 0xffffU
 		for (c=0 ; c <= 0xffffUL ; c++)
 #else
@@ -692,9 +698,9 @@ int main(int argc, char **argv)
 			if (mywxdigit(c)) ++mine;
 
 			if (glibc != mine) {
-				printf("%#8x : glibc %#4x != %#4x mine %d\n", c, glibc, mine, d);
+				verbose_msg("%#8x : glibc %#4x != %#4x mine %d\n", c, glibc, mine, d);
 				if (c < 0x30000UL) {
-					printf("sc=%#x u=%#x n=%#x i0=%#x i1=%#x\n", sc, u, n, i0, i1);
+					verbose_msg("sc=%#x u=%#x n=%#x i0=%#x i1=%#x\n", sc, u, n, i0, i1);
 				}
 			}
 				upper = lower = u = c;
@@ -715,32 +721,32 @@ int main(int argc, char **argv)
 				}
 
 			if (towupper(c) != upper) {
-				printf("%#8x : towupper glibc %#4x != %#4x mine\n",
+				verbose_msg("%#8x : towupper glibc %#4x != %#4x mine\n",
 					   c, towupper(c), upper);
 			}
 
 			if (towlower(c) != lower) {
-				printf("%#8x : towlower glibc %#4x != %#4x mine   i0 = %d\n",
+				verbose_msg("%#8x : towlower glibc %#4x != %#4x mine   i0 = %d\n",
 					   c, towlower(c), lower, i0);
 			}
 
 			if (totitle && ((tt = towctrans(c, totitle)) != upper)) {
-				printf("%#8x : totitle glibc %#4lx != %#4x mine   i0 = %d\n",
+				verbose_msg("%#8x : totitle glibc %#4lx != %#4x mine   i0 = %d\n",
 					   c, tt, upper, i0);
 			}
 			}
 
 
-			if ((c & 0xfff) == 0xfff) printf(".");
+			if ((c & 0xfff) == 0xfff) verbose_msg(".");
 		}
-		printf("done\n");
+		verbose_msg("done\n");
 	}
 
 	if (built) {
 		FILE *fp;
 
 		if (!(fp = fopen("wctables.h", "w"))) {
-			printf("cannot open output file 'wctables.h'!\n");
+			verbose_msg("cannot open output file 'wctables.h'!\n");
 			return EXIT_FAILURE;
 		}
 
@@ -815,7 +821,7 @@ size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl)
 		}
 #if 1
 		else if (memcmp(ti[i-1], ti[i], blocksize) > 0) {
-			printf("bad sort %i!\n", i);
+			verbose_msg("bad sort %i!\n", i);
 			abort();
 		}
 #endif
@@ -844,7 +850,7 @@ size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl)
 					shift2 = j;
 					smallest = t;
 					if (!tbl->ii) {
-						printf("ishift %zu  tshift %zu  size %zu\n",
+						verbose_msg("ishift %zu  tshift %zu  size %zu\n",
 							   shift2, shift, t);
 					}
 /*  				} else { */
@@ -869,7 +875,7 @@ size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl)
 			}
 		} else {
 			++recurse;
-			printf("setting ishift %zu  tshift %zu\n",
+			verbose_msg("setting ishift %zu  tshift %zu\n",
 							   shift2, shift);
 			newopt(uit, numblocks, shift2, tbl);
 			--recurse;