2 * gen-ctype-checked.c: generates ctype-checked.h on stdout
4 * This code is Copyright (c) 2013, by the authors of nmh.
5 * See the COPYRIGHT file in the root directory of the nmh
6 * distribution for complete copyright information.
10 * This is intended to catch any calls using a char argument to any of
11 * the is*(int) functions in <ctype.h>. It does that by defining a
12 * macro that uses the argument as an array index, along with a
13 * compiler warning such as gcc -Wchar-subscripts (include with
14 * -Wall). This program creates sbr/ctype-checked.h and
15 * sbr/ctype-checked.c. The header file is put into sbr/ because h/
16 * is unwritable during make distcheck.
22 #define CTYPE_FUNCTIONS \
37 #if (defined (_BSD_SOURCE) && _BSD_SOURCE) || \
38 (defined (_SVID_SOURCE) && _SVID_SOURCE) || \
39 (defined (_XOPEN_SOURCE) && _XOPEN_SOURCE)
40 # define CTYPE_FUNCTION_ISASCII X(isascii) \
43 # define CTYPE_FUNCTION_ISASCII
46 #if (defined (_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) || \
47 (defined (_ISOC99_SOURCE) && _ISOC99_SOURCE) || \
48 (defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
49 # define CTYPE_FUNCTIONS_C99 X(isblank)
51 # define CTYPE_FUNCTIONS_C99
54 struct ctype_func
{ const char *name
; int (*function
) (int); };
56 #define X(function) { #function, function },
57 struct ctype_func functions
[] =
58 { CTYPE_FUNCTIONS CTYPE_FUNCTION_ISASCII CTYPE_FUNCTIONS_C99
{ NULL
, 0} };
64 const char *copyright
="\
66 * %s: checks type of arguments and argument\n\
67 * values for each of the ctype functions\n\
69 * Generated by etc/gen-ctype-checked.\n\
71 * This code is Copyright (c) 2013, by the authors of nmh.\n\
72 * See the COPYRIGHT file in the root directory of the nmh\n\
73 * distribution for complete copyright information.\n\
75 char headername
[] = "sbr/ctype-checked.h";
76 const char cfilename
[] = "sbr/ctype-checked.c";
77 FILE *header
= fopen (headername
, "w");
78 FILE *cfile
= fopen (cfilename
, "w");
81 if (header
!= 0 && cfile
!= 0) {
84 fprintf (header
, copyright
, headername
);
85 fputs ("#ifndef CTYPE_CHECKED_H\n\
86 #define CTYPE_CHECKED_H\n\
90 fprintf (cfile
, copyright
, cfilename
);
91 fputs ("#include <config.h>\n\n", cfile
);
92 fputs ("#ifndef NDEBUG\n", cfile
);
93 fputs ("#include <sbr/ctype-checked.h>\n\n", cfile
);
95 for (f
= functions
; f
->function
; ++f
) {
96 const char *cp
= f
->name
;
99 fprintf (header
, "extern int %s_type_checked[];\n", cp
);
100 fprintf (header
, "#ifdef %s\n#undef %s\n#endif\n", cp
, cp
);
101 fprintf (header
, "#define %s(c) %s_type_checked[(c)]\n\n", cp
, cp
);
103 fprintf (cfile
, "int %s_type_checked[] = {\n ", cp
);
104 for (i
= 0; i
< 256; ++i
) {
105 fprintf (cfile
, "%d", (*f
->function
) (i
));
110 fputs (" };\n\n", cfile
);
112 fputs (",\n ", cfile
);
118 /* Need to put a symbol in the .c file with NDEBUG so the
119 compilation unit isn't empty. */
120 fputs ("#else /* NDEBUG */\n\nvoid ctype_checked();\n\n", cfile
);
121 fputs ("#endif /* NDEBUG */\n", cfile
);
122 fprintf (header
, "#endif /* CTYPE_CHECKED_H */\n");
124 perror ("fopen in sbr/");
128 if (header
) { fclose(header
); }
129 if (cfile
) { fclose(cfile
); }