]> diplodocus.org Git - nmh/blob - etc/gen-ctype-checked.c
Replace getcpy() with mh_xstrdup() where the string isn't NULL.
[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 X(tolower) \
35 X(toupper) \
36
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) \
41 X(toascii)
42 #else
43 # define CTYPE_FUNCTION_ISASCII
44 #endif
45
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)
50 #else
51 # define CTYPE_FUNCTIONS_C99
52 #endif
53
54 struct ctype_func { const char *name; int (*function) (int); };
55
56 #define X(function) { #function, function },
57 struct ctype_func functions[] =
58 { CTYPE_FUNCTIONS CTYPE_FUNCTION_ISASCII CTYPE_FUNCTIONS_C99 { NULL, 0} };
59 #undef X
60
61
62 int
63 main () {
64 const char *copyright="\
65 /*\n\
66 * %s: checks type of arguments and argument\n\
67 * values for each of the ctype functions\n\
68 *\n\
69 * Generated by etc/gen-ctype-checked.\n\
70 *\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\
74 */\n\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");
79 int status = 0;
80
81 if (header != 0 && cfile != 0) {
82 struct ctype_func *f;
83
84 fprintf (header, copyright, headername);
85 fputs ("#ifndef CTYPE_CHECKED_H\n\
86 #define CTYPE_CHECKED_H\n\
87 #include <ctype.h>\n\
88 \n", header);
89
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);
94
95 for (f = functions; f->function; ++f) {
96 const char *cp = f->name;
97 unsigned int i;
98
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);
102
103 fprintf (cfile, "int %s_type_checked[] = {\n ", cp);
104 for (i = 0; i < 256; ++i) {
105 fprintf (cfile, "%d", (*f->function) (i));
106 if ((i+1) % 8) {
107 fputs (", ", cfile);
108 } else {
109 if (i == 255) {
110 fputs (" };\n\n", cfile);
111 } else {
112 fputs (",\n ", cfile);
113 }
114 }
115 }
116 }
117
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");
123 } else {
124 perror ("fopen in sbr/");
125 status = -1;
126 }
127
128 if (header) { fclose(header); }
129 if (cfile) { fclose(cfile); }
130
131 return status;
132 }