/* * 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 . 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 #include #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) \ X(tolower) \ X(toupper) \ #if (defined (_BSD_SOURCE) && _BSD_SOURCE) || \ (defined (_SVID_SOURCE) && _SVID_SOURCE) || \ (defined (_XOPEN_SOURCE) && _XOPEN_SOURCE) # define CTYPE_FUNCTION_ISASCII X(isascii) \ X(toascii) #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 \n\ \n", header); fprintf (cfile, copyright, cfilename); fputs ("#include \n\n", cfile); fputs ("#ifndef NDEBUG\n", cfile); fputs ("#include \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; }