Smack: add the execute lable to ldconfig
[platform/upstream/glibc.git] / stdlib / isomac.c
1 /* Check system header files for ISO 9899:1990 (ISO C) compliance.
2    Copyright (C) 1996-2015 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Jens Schweikhardt <schweikh@noc.dfn.de>, 1996.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 /* This is a simple minded program that tries to find illegal macro
21    definitions in system header files. Illegal macro definitions are
22    those not from the implementation namespace (i.e. not starting with
23    an underscore) or not matching any identifier mandated by The
24    Standard. Some common macro names are considered okay, e.g. all those
25    beginning with E (which may be defined in <errno.h>) or ending in
26    _MAX. See the arrays prefix[] and suffix[] below for details.
27
28    In a compliant implementation no other macros can be defined, because
29    you could write strictly conforming programs that may fail to compile
30    due to syntax errors: suppose <stdio.h> defines PIPE_BUF, then the
31    conforming
32
33    #include <assert.h>
34    #include <stdio.h>      <- or where the bogus macro is defined
35    #include <string.h>
36    #define STR(x) #x
37    #define XSTR(x) STR(x)
38    int main (void)
39    {
40      int PIPE_BUF = 0;
41      assert (strcmp ("PIPE_BUF", XSTR (PIPE_BUF)) == 0);
42      return 0;
43    }
44
45    is expected to compile and meet the assertion. If it does not, your
46    compiler compiles some other language than Standard C.
47
48    REQUIREMENTS:
49      This program calls gcc to get the list of defined macros. If you
50      don't have gcc you're probably out of luck unless your compiler or
51      preprocessor has something similar to gcc's -dM option. Tune
52      PRINT_MACROS in this case. This program assumes headers are found
53      under /usr/include and that there is a writable /tmp directory.
54      Tune SYSTEM_INCLUDE if your system differs.
55      #define BROKEN_SYSTEM if system(NULL) bombs -- one more violation
56      of ISO C, by the way.
57
58    OUTPUT:
59      Each header file name is printed, followed by illegal macro names
60      and their definition. For the above example, you would see
61      ...
62      /usr/include/stdio.h
63      #define PIPE_BUF 5120
64      ...
65      If your implementation does not yet incorporate Amendment 1 you
66      will see messages about iso646.h, wctype.h and wchar.h not being
67      found.  */
68
69 #ifndef _GNU_SOURCE
70 # define _GNU_SOURCE 1
71 #endif
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #define HEADER_MAX          256
78
79 static const char *macrofile;
80
81 /* ISO C header names including Amendment 1 (without ".h" suffix).  */
82 static char *header[] =
83 {
84   "assert", "ctype", "errno", "float", "iso646", "limits", "locale",
85   "math", "setjmp", "signal", "stdarg", "stddef", "stdio", "stdlib",
86   "string", "time", "wchar", "wctype"
87 };
88
89 /* Macros with these prefixes are considered okay.  */
90 static char *prefix[] =
91 {
92   "_", "E", "is", "str", "mem", "SIG", "FLT_", "DBL_", "LDBL_",
93   "LC_", "wmem", "wcs"
94 };
95
96 /* Macros with these suffixes are considered okay.  Will not work for
97    parametrized macros with arguments.  */
98 static char *suffix[] =
99 {
100   "_MAX", "_MIN"
101 };
102
103 /* These macros are considered okay. In fact, these are just more prefixes.  */
104 static char *macros[] =
105 {
106   "BUFSIZ", "CHAR_BIT", "CHAR_MAX", "CHAR_MIN", "CLOCKS_PER_SEC",
107   "DBL_DIG", "DBL_EPSILON", "DBL_MANT_DIG", "DBL_MAX",
108   "DBL_MAX_10_EXP", "DBL_MAX_EXP", "DBL_MIN", "DBL_MIN_10_EXP",
109   "DBL_MIN_EXP", "EDOM", "EILSEQ", "EOF", "ERANGE", "EXIT_FAILURE",
110   "EXIT_SUCCESS", "FILENAME_MAX", "FLT_DIG", "FLT_EPSILON",
111   "FLT_MANT_DIG", "FLT_MAX", "FLT_MAX_10_EXP", "FLT_MAX_EXP",
112   "FLT_MIN", "FLT_MIN_10_EXP", "FLT_MIN_EXP", "FLT_RADIX",
113   "FLT_ROUNDS", "FOPEN_MAX", "HUGE_VAL", "INT_MAX", "INT_MIN",
114   "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC",
115   "LC_TIME", "LDBL_DIG", "LDBL_EPSILON", "LDBL_MANT_DIG", "LDBL_MAX",
116   "LDBL_MAX_10_EXP", "LDBL_MAX_EXP", "LDBL_MIN", "LDBL_MIN_10_EXP",
117   "LDBL_MIN_EXP", "LONG_MAX", "LONG_MIN", "L_tmpnam", "MB_CUR_MAX",
118   "MB_LEN_MAX", "NDEBUG", "NULL", "RAND_MAX", "SCHAR_MAX",
119   "SCHAR_MIN", "SEEK_CUR", "SEEK_END", "SEEK_SET", "SHRT_MAX",
120   "SHRT_MIN", "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV",
121   "SIGTERM", "SIG_DFL", "SIG_ERR", "SIG_IGN", "TMP_MAX", "UCHAR_MAX",
122   "UINT_MAX", "ULONG_MAX", "USHRT_MAX", "WCHAR_MAX", "WCHAR_MIN",
123   "WEOF", "_IOFBF", "_IOLBF", "_IONBF", "abort", "abs", "acos",
124   "acosf", "acosl", "and", "and_eq", "asctime", "asin", "asinf",
125   "asinl", "assert", "atan", "atan2", "atan2f", "atan2l", "atanf",
126   "atanl", "atexit", "atof", "atoi", "atol", "bitand", "bitor",
127   "bsearch", "btowc", "calloc", "ceil", "ceilf", "ceill", "clearerr",
128   "clock", "clock_t", "compl", "cos", "cosf", "cosh", "coshf",
129   "coshl", "cosl", "ctime", "difftime", "div", "div_t", "errno",
130   "exit", "exp", "expf", "expl", "fabs", "fabsf", "fabsl", "fclose",
131   "feof", "ferror", "fflush", "fgetc", "fgetpos", "fgets", "fgetwc",
132   "fgetws", "floor", "floorf", "floorl", "fmod", "fmodf", "fmodl",
133   "fopen", "fprintf", "fputc", "fputs", "fputwc", "fputws", "fread",
134   "free", "freopen", "frexp", "frexpf", "frexpl", "fscanf", "fseek",
135   "fsetpos", "ftell", "fwide", "fwprintf", "fwrite", "fwscanf",
136   "getc", "getchar", "getenv", "gets", "getwc", "getwchar", "gmtime",
137   "isalnum", "isalpha", "iscntrl", "isdigit", "isgraph", "islower",
138   "isprint", "ispunct", "isspace", "isupper", "iswalnum", "iswalpha",
139   "iswcntrl", "iswctype", "iswdigit", "iswgraph", "iswlower",
140   "iswprint", "iswpunct", "iswspace", "iswupper", "iswxdigit",
141   "isxdigit", "labs", "ldexp", "ldexpf", "ldexpl", "ldiv", "ldiv_t",
142   "localeconv", "localtime", "log", "log10", "log10f", "log10l",
143   "logf", "logl", "longjmp", "malloc", "mblen", "mbrlen", "mbrtowc",
144   "mbsinit", "mbsrtowcs", "mbstate_t", "mbstowcs", "mbtowc", "memchr",
145   "memcmp", "memcpy", "memmove", "memset", "mktime", "modf", "modff",
146   "modfl", "not", "not_eq", "offsetof", "or", "or_eq", "perror",
147   "pow", "powf", "powl", "printf", "ptrdiff_t", "putc", "putchar",
148   "puts", "putwc", "putwchar", "qsort", "raise", "rand", "realloc",
149   "remove", "rename", "rewind", "scanf", "setbuf", "setjmp",
150   "setlocale", "setvbuf", "sig_atomic_t", "signal", "sin", "sinf",
151   "sinh", "sinhf", "sinhl", "sinl", "size_t", "sprintf", "sqrt",
152   "sqrtf", "sqrtl", "srand", "sscanf", "stderr", "stdin", "stdout",
153   "strcat", "strchr", "strcmp", "strcoll", "strcpy", "strcspn",
154   "strerror", "strftime", "strlen", "strncat", "strncmp", "strncpy",
155   "strpbrk", "strrchr", "strspn", "strstr", "strtod", "strtok",
156   "strtol", "strtoul", "strxfrm", "swprintf", "swscanf", "system",
157   "tan", "tanf", "tanh", "tanhf", "tanhl", "tanl", "time", "time_t",
158   "tmpfile", "tmpnam", "tolower", "toupper", "towctrans", "towlower",
159   "towupper", "ungetc", "ungetwc", "va_arg", "va_copy", "va_end", "va_start",
160   "vfprintf", "vfwprintf", "vprintf", "vsprintf", "vswprintf",
161   "vwprintf", "wchar_t", "wcrtomb", "wcscat", "wcschr", "wcscmp",
162   "wcscoll", "wcscpy", "wcscspn", "wcsftime", "wcslen", "wcsncat",
163   "wcsncmp", "wcsncpy", "wcspbrk", "wcsrchr", "wcsrtombs", "wcsspn",
164   "wcsstr", "wcstod", "wcstok", "wcstol", "wcstombs", "wcstoul",
165   "wcsxfrm", "wctob", "wctomb", "wctrans", "wctrans_t", "wctype",
166   "wctype_t", "wint_t", "wmemchr", "wmemcmp", "wmemcpy", "wmemmove",
167   "wmemset", "wprintf", "wscanf", "xor", "xor_eq"
168 };
169
170 #define NUMBER_OF_HEADERS              (sizeof header / sizeof *header)
171 #define NUMBER_OF_PREFIXES             (sizeof prefix / sizeof *prefix)
172 #define NUMBER_OF_SUFFIXES             (sizeof suffix / sizeof *suffix)
173 #define NUMBER_OF_MACROS               (sizeof macros / sizeof *macros)
174
175
176 /* Format string to build command to invoke compiler.  */
177 static const char fmt[] = "\
178 echo \"#include <%s>\" |\
179 %s -E -dM -ansi -pedantic %s -D_LIBC -D_ISOMAC \
180 -DIN_MODULE=MODULE_extramodules -I. \
181 -isystem `%s --print-prog-name=include` - 2> /dev/null > %s";
182
183
184 /* The compiler we use (given on the command line).  */
185 char *CC;
186 /* The -I parameters for CC to find all headers.  */
187 char *INC;
188
189 static char *xstrndup (const char *, size_t);
190 static const char **get_null_defines (void);
191 static int check_header (const char *, const char **);
192
193 int
194 main (int argc, char *argv[])
195 {
196   int h;
197   int result = 0;
198   const char **ignore_list;
199
200   CC = argc > 1 ? argv[1] : "gcc";
201   INC = argc > 2 ? argv[2] : "";
202
203   if (system (NULL) == 0)
204     {
205       puts ("Sorry, no command processor.");
206       return EXIT_FAILURE;
207     }
208
209   /* First get list of symbols which are defined by the compiler.  */
210   ignore_list = get_null_defines ();
211
212   fputs ("Tested files:\n", stdout);
213
214   for (h = 0; h < NUMBER_OF_HEADERS; ++h)
215     {
216       char file_name[HEADER_MAX];
217       sprintf (file_name, "%s.h", header[h]);
218       result |= check_header (file_name, ignore_list);
219     }
220
221   /* The test suite should return errors but for now this is not
222      practical.  Give a warning and ask the user to correct the bugs.  */
223   return result;
224 }
225
226
227 static char *
228 xstrndup (const char *s, size_t n)
229 {
230   size_t len = n;
231   char *new = malloc (len + 1);
232
233   if (new == NULL)
234     return NULL;
235
236   new[len] = '\0';
237   return memcpy (new, s, len);
238 }
239
240
241 static const char **
242 get_null_defines (void)
243 {
244   char line[BUFSIZ], *command;
245   char **result = NULL;
246   size_t result_len = 0;
247   size_t result_max = 0;
248   FILE *input;
249   int first = 1;
250
251   macrofile = tmpnam (NULL);
252
253   command = malloc (sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC)
254                     + strlen (INC) + strlen (macrofile));
255
256   if (command == NULL)
257     {
258       puts ("No more memory.");
259       exit (1);
260     }
261
262   sprintf (command, fmt, "/dev/null", CC, INC, CC, macrofile);
263
264   if (system (command))
265     {
266       puts ("system() returned nonzero");
267       free (command);
268       return NULL;
269     }
270   free (command);
271   input = fopen (macrofile, "r");
272
273   if (input == NULL)
274     {
275       printf ("Could not read %s: ", macrofile);
276       perror (NULL);
277       return NULL;
278     }
279
280   while (fgets (line, sizeof line, input) != NULL)
281     {
282       int i, okay = 0;
283       size_t endmac;
284       char *start, *end;
285       if (strlen (line) < 9 || line[7] != ' ')
286         { /* "#define A" */
287           printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
288                   line);
289           continue;
290         }
291       if (line[8] == '_')
292         /* It's a safe identifier.  */
293         continue;
294       if (result_len == result_max)
295         {
296           result_max += 10;
297           result = realloc (result, result_max * sizeof (char **));
298           if (result == NULL)
299             {
300               puts ("No more memory.");
301               exit (1);
302             }
303         }
304       start = &line[8];
305       for (end = start + 1; !isspace (*end) && *end != '\0'; ++end)
306         ;
307       result[result_len] = xstrndup (start, end - start);
308
309       if (strcmp (result[result_len], "IN_MODULE") != 0)
310         {
311           if (first)
312             {
313               fputs ("The following identifiers will be ignored since the compiler defines them\nby default:\n", stdout);
314               first = 0;
315             }
316           puts (result[result_len]);
317         }
318       ++result_len;
319     }
320   if (result_len == result_max)
321     {
322       result_max += 1;
323       result = realloc (result, result_max * sizeof (char **));
324       if (result == NULL)
325         {
326           puts ("No more memory.");
327           exit (1);
328         }
329     }
330   result[result_len] = NULL;
331   fclose (input);
332   remove (macrofile);
333
334   return (const char **) result;
335 }
336
337
338 static int
339 check_header (const char *file_name, const char **except)
340 {
341   char line[BUFSIZ], *command;
342   FILE *input;
343   int result = 0;
344
345   command = malloc (sizeof fmt + strlen (file_name) + 2 * strlen (CC)
346                     + strlen (INC) + strlen (macrofile));
347
348   if (command == NULL)
349     {
350       puts ("No more memory.");
351       exit (1);
352     }
353
354   puts (file_name);
355   sprintf (command, fmt, file_name, CC, INC, CC, macrofile);
356
357   if (system (command))
358     {
359       puts ("system() returned nonzero");
360       result = 1;
361     }
362   free (command);
363   input = fopen (macrofile, "r");
364
365   if (input == NULL)
366     {
367       printf ("Could not read %s: ", macrofile);
368       perror (NULL);
369       return 1;
370     }
371
372   while (fgets (line, sizeof line, input) != NULL)
373     {
374       int i, okay = 0;
375       size_t endmac;
376       const char **cpp;
377       if (strlen (line) < 9 || line[7] != ' ')
378         { /* "#define A" */
379           printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
380                   line);
381           result = 1;
382           continue;
383         }
384       for (i = 0; i < NUMBER_OF_PREFIXES; ++i)
385         {
386           if (!strncmp (line+8, prefix[i], strlen (prefix[i]))) {
387             ++okay;
388             break;
389           }
390         }
391       if (okay)
392         continue;
393       for (i = 0; i < NUMBER_OF_MACROS; ++i)
394         {
395           if (!strncmp (line + 8, macros[i], strlen (macros[i])))
396             {
397               ++okay;
398               break;
399             }
400         }
401       if (okay)
402         continue;
403       /* Find next char after the macro identifier; this can be either
404          a space or an open parenthesis.  */
405       endmac = strcspn (line + 8, " (");
406       if (line[8+endmac] == '\0')
407         {
408           printf ("malformed input, expected '#define MACRO VALUE'\n"
409                   "got '%s'\n", line);
410           result = 1;
411           continue;
412         }
413       for (i = 0; i < NUMBER_OF_SUFFIXES; ++i)
414         {
415           size_t len = strlen (suffix[i]);
416           if (!strncmp (line + 8 + endmac - len, suffix[i], len))
417             {
418               ++okay;
419               break;
420             }
421         }
422       if (okay)
423         continue;
424       if (except != NULL)
425         for (cpp = except; *cpp != NULL; ++cpp)
426           {
427             size_t len = strlen (*cpp);
428             if (!strncmp (line + 8, *cpp, len) && isspace (line[8 + len]))
429               {
430                 ++okay;
431                 break;
432               }
433           }
434       if (!okay)
435         {
436           fputs (line, stdout);
437           result = 2;
438         }
439     }
440   fclose (input);
441   remove (macrofile);
442
443   return result;
444 }
445
446 /* EOF */