]> diplodocus.org Git - nmh/blob - etc/gen-ctype-checked.c
Document argsplit changes in mh-profile man page.
[nmh] / etc / gen-ctype-checked.c
1 /*
2 * gen-ctype-checked.c: generates ctype-checked.h on stdout
3 *
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.
7 */
8
9 /*
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.
17 */
18
19 #include <ctype.h>
20 #include <stdio.h>
21
22 #define CTYPE_FUNCTIONS \
23 X(isalnum) \
24 X(isalpha) \
25 X(iscntrl) \
26 X(isdigit) \
27 X(isgraph) \
28 X(islower) \
29 X(isprint) \
30 X(ispunct) \
31 X(isspace) \
32 X(isupper) \
33 X(isxdigit) \
34
35 #if (defined (_BSD_SOURCE) && _BSD_SOURCE) || \
36 (defined (_SVID_SOURCE) && _SVID_SOURCE) || \
37 (defined (_XOPEN_SOURCE) && _XOPEN_SOURCE)
38 # define CTYPE_FUNCTION_ISASCII X(isascii)
39 #else
40 # define CTYPE_FUNCTION_ISASCII
41 #endif
42
43 #if (defined (_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) || \
44 (defined (_ISOC99_SOURCE) && _ISOC99_SOURCE) || \
45 (defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
46 # define CTYPE_FUNCTIONS_C99 X(isblank)
47 #else
48 # define CTYPE_FUNCTIONS_C99
49 #endif
50
51 struct ctype_func { const char *name; int (*function) (int); };
52
53 #define X(function) { #function, function },
54 struct ctype_func functions[] =
55 { CTYPE_FUNCTIONS CTYPE_FUNCTION_ISASCII CTYPE_FUNCTIONS_C99 { NULL, 0} };
56 #undef X
57
58
59 int
60 main () {
61 const char *copyright="\
62 /*\n\
63 * %s: checks type of arguments and argument\n\
64 * values for each of the ctype functions\n\
65 *\n\
66 * Generated by etc/gen-ctype-checked.\n\
67 *\n\
68 * This code is Copyright (c) 2013, by the authors of nmh.\n\
69 * See the COPYRIGHT file in the root directory of the nmh\n\
70 * distribution for complete copyright information.\n\
71 */\n\n";
72 char headername[] = "sbr/ctype-checked.h";
73 const char cfilename[] = "sbr/ctype-checked.c";
74 FILE *header, *cfile;
75
76 if ((header = fopen (headername, "w")) != 0 &&
77 (cfile = fopen (cfilename, "w")) != 0) {
78 struct ctype_func *f;
79
80 fprintf (header, copyright, headername);
81 fputs ("#ifndef CTYPE_CHECKED_H\n\
82 #define CTYPE_CHECKED_H\n\
83 #include <ctype.h>\n\
84 \n", header);
85
86 fprintf (cfile, copyright, cfilename);
87 fputs ("#include <config.h>\n\n", cfile);
88 fputs ("#ifndef NDEBUG\n", cfile);
89 fputs ("#include <sbr/ctype-checked.h>\n\n", cfile);
90
91 for (f = functions; f->function; ++f) {
92 const char *cp = f->name;
93 unsigned int i;
94
95 fprintf (header, "extern int %s_type_checked[];\n", cp);
96 fprintf (header, "#ifdef %s\n#undef %s\n#endif\n", cp, cp);
97 fprintf (header, "#define %s(c) %s_type_checked[(c)]\n\n", cp, cp);
98
99 fprintf (cfile, "int %s_type_checked[] = {\n ", cp);
100 for (i = 0; i < 256; ++i) {
101 fprintf (cfile, "%d", (*f->function) (i));
102 if ((i+1) % 8) {
103 fputs (", ", cfile);
104 } else {
105 if (i == 255) {
106 fputs (" };\n\n", cfile);
107 } else {
108 fputs (",\n ", cfile);
109 }
110 }
111 }
112 }
113
114 /* Need to put a symbol in the .c file with NDEBUG so the
115 compilation unit isn't empty. */
116 fputs ("#else /* NDEBUG */\n\nint ctype_checked;\n\n", cfile);
117 fputs ("#endif /* NDEBUG */\n", cfile);
118 fprintf (header, "#endif /* CTYPE_CHECKED_H */\n");
119 } else {
120 perror ("fopen in sbr/");
121 return -1;
122 }
123
124 return 0;
125 }