## Stuff that should be cleaned via "make clean"
##
CLEANFILES = config/version.c sbr/sigmsg.h etc/mts.conf \
+ etc/gen-ctype-checked sbr/ctype-checked.h sbr/ctype-checked.c \
etc/mhn.defaults man/man.sed man/mh-chart.man $(man_MANS)
clean-local:
@rm -rf RPM a.out.dSYM uip/a.out.dSYM
##
## Files that need to be built before everything else
##
-BUILT_SOURCES = sbr/sigmsg.h
+BUILT_SOURCES = sbr/sigmsg.h sbr/ctype-checked.c
##
## This is a list of all programs that get installed in the "bin" directory
h/mh.h h/mhcachesbr.h h/mhparse.h h/mime.h h/msh.h \
h/mts.h h/nmh.h h/picksbr.h h/popsbr.h h/prototypes.h \
h/rcvmail.h h/scansbr.h h/signals.h h/tws.h h/utils.h \
- h/vmhsbr.h mts/smtp/smtp.h
+ h/vmhsbr.h mts/smtp/smtp.h sbr/ctype-checked.h
##
## Extra files we need to install in various places
## Automake using the automatic rules
##
EXTRA_DIST = config/version.sh sbr/sigmsg.awk etc/mts.conf.in \
+ etc/gen-ctype-checked.c \
etc/mhn.defaults.sh etc/sendfiles $(MHNSEARCHPROG) DATE MACHINES \
docs/ChangeLog_MH-3_to_MH-6.6 \
docs/ChangeLog_MH-6.7.0_to_MH-6.8.4.html \
sbr/sigmsg.h: $(srcdir)/sbr/sigmsg.awk $(SIGNAL_H)
$(AWK) -f $(srcdir)/sbr/sigmsg.awk $(SIGNAL_H) > $@
+sbr/ctype-checked.h: etc/gen-ctype-checked
+ etc/gen-ctype-checked
+
+sbr/ctype-checked.c: etc/gen-ctype-checked sbr/ctype-checked.h
+
+etc/gen-type-checked: etc/gen-type-checked.c
+
etc/mts.conf: $(srcdir)/etc/mts.conf.in Makefile
@rm -f $@
$(SED) -e 's,%mts%,$(MTS),' \
sbr/showfile.c sbr/signals.c sbr/smatch.c \
sbr/snprintb.c sbr/ssequal.c sbr/strcasecmp.c \
sbr/strindex.c sbr/trimcpy.c sbr/uprf.c sbr/vfgets.c \
- sbr/fmt_def.c sbr/mf.c sbr/utils.c \
+ sbr/fmt_def.c sbr/mf.c sbr/utils.c sbr/ctype-checked.c \
sbr/m_mktemp.c sbr/getansreadline.c config/config.c \
config/version.c
--- /dev/null
+/*
+ * gen-ctype-checked.c: generates ctype-checked.h on stdout
+ *
+ * This code is Copyright (c) 2013, by the authors of nmh.
+ * See the COPYRIGHT file in the root directory of the nmh
+ * distribution for complete copyright information.
+ */
+
+/*
+ * This is intended to catch any calls using a char argument to any of
+ * the is*(int) functions in <ctype.h>. It does that by defining a
+ * macro that uses the argument as an array index, along with a
+ * compiler warning such as gcc -Wchar-subscripts (include with
+ * -Wall). This program creates sbr/ctype-checked.h and
+ * sbr/ctype-checked.c. The header file is put into sbr/ because h/
+ * is unwritable during make distcheck.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+
+#define CTYPE_FUNCTIONS \
+ X(isalnum) \
+ X(isalpha) \
+ X(iscntrl) \
+ X(isdigit) \
+ X(isgraph) \
+ X(islower) \
+ X(isprint) \
+ X(ispunct) \
+ X(isspace) \
+ X(isupper) \
+ X(isxdigit) \
+
+#if (defined (_BSD_SOURCE) && _BSD_SOURCE) || \
+ (defined (_SVID_SOURCE) && _SVID_SOURCE) || \
+ (defined (_XOPEN_SOURCE) && _XOPEN_SOURCE)
+# define CTYPE_FUNCTION_ISASCII X(isascii)
+#else
+# define CTYPE_FUNCTION_ISASCII
+#endif
+
+#if (defined (_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) || \
+ (defined (_ISOC99_SOURCE) && _ISOC99_SOURCE) || \
+ (defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
+# define CTYPE_FUNCTIONS_C99 X(isblank)
+#else
+# define CTYPE_FUNCTIONS_C99
+#endif
+
+struct ctype_func { const char *name; int (*function) (int); };
+
+#define X(function) { #function, function },
+struct ctype_func functions[] =
+ { CTYPE_FUNCTIONS CTYPE_FUNCTION_ISASCII CTYPE_FUNCTIONS_C99 { NULL, 0} };
+#undef X
+
+
+int
+main () {
+ const char *copyright="\
+/*\n\
+ * %s: checks type of arguments and argument\n\
+ * values for each of the ctype functions\n\
+ *\n\
+ * Generated by etc/gen-ctype-checked.\n\
+ *\n\
+ * This code is Copyright (c) 2013, by the authors of nmh.\n\
+ * See the COPYRIGHT file in the root directory of the nmh\n\
+ * distribution for complete copyright information.\n\
+ */\n\n";
+ char headername[] = "sbr/ctype-checked.h";
+ const char cfilename[] = "sbr/ctype-checked.c";
+ FILE *header, *cfile;
+
+ if ((header = fopen (headername, "w")) != 0 &&
+ (cfile = fopen (cfilename, "w")) != 0) {
+ struct ctype_func *f;
+
+ fprintf (header, copyright, headername);
+ fputs ("#ifndef CTYPE_CHECKED_H\n\
+#define CTYPE_CHECKED_H\n\
+#include <ctype.h>\n\
+\n", header);
+
+ fprintf (cfile, copyright, cfilename);
+ fputs ("#include <config.h>\n\n", cfile);
+ fputs ("#ifndef NDEBUG\n", cfile);
+ fputs ("#include <sbr/ctype-checked.h>\n\n", cfile);
+
+ for (f = functions; f->function; ++f) {
+ const char *cp = f->name;
+ unsigned int i;
+
+ fprintf (header, "extern int %s_type_checked[];\n", cp);
+ fprintf (header, "#ifdef %s\n#undef %s\n#endif\n", cp, cp);
+ fprintf (header, "#define %s(c) %s_type_checked[(c)]\n\n", cp, cp);
+
+ fprintf (cfile, "int %s_type_checked[] = {\n ", cp);
+ for (i = 0; i < 256; ++i) {
+ fprintf (cfile, "%d", (*f->function) (i));
+ if ((i+1) % 8) {
+ fputs (", ", cfile);
+ } else {
+ if (i == 255) {
+ fputs (" };\n\n", cfile);
+ } else {
+ fputs (",\n ", cfile);
+ }
+ }
+ }
+ }
+
+ /* Need to put a symbol in the .c file with NDEBUG so the
+ compilation unit isn't empty. */
+ fputs ("#else /* NDEBUG */\n\nint ctype_checked;\n\n", cfile);
+ fputs ("#endif /* NDEBUG */\n", cfile);
+ fprintf (header, "#endif /* CTYPE_CHECKED_H */\n");
+ } else {
+ perror ("fopen in sbr/");
+ return -1;
+ }
+
+ return 0;
+}