Blame stdlib/isomac.c

Packit 6c4009
/* Check system header files for ISO 9899:1990 (ISO C) compliance.
Packit 6c4009
   Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Jens Schweikhardt <schweikh@noc.dfn.de>, 1996.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* This is a simple minded program that tries to find illegal macro
Packit 6c4009
   definitions in system header files. Illegal macro definitions are
Packit 6c4009
   those not from the implementation namespace (i.e. not starting with
Packit 6c4009
   an underscore) or not matching any identifier mandated by The
Packit 6c4009
   Standard. Some common macro names are considered okay, e.g. all those
Packit 6c4009
   beginning with E (which may be defined in <errno.h>) or ending in
Packit 6c4009
   _MAX. See the arrays prefix[] and suffix[] below for details.
Packit 6c4009
Packit 6c4009
   In a compliant implementation no other macros can be defined, because
Packit 6c4009
   you could write strictly conforming programs that may fail to compile
Packit 6c4009
   due to syntax errors: suppose <stdio.h> defines PIPE_BUF, then the
Packit 6c4009
   conforming
Packit 6c4009
Packit 6c4009
   #include <assert.h>
Packit 6c4009
   #include <stdio.h>      <- or where the bogus macro is defined
Packit 6c4009
   #include <string.h>
Packit 6c4009
   #define STR(x) #x
Packit 6c4009
   #define XSTR(x) STR(x)
Packit 6c4009
   int main (void)
Packit 6c4009
   {
Packit 6c4009
     int PIPE_BUF = 0;
Packit 6c4009
     assert (strcmp ("PIPE_BUF", XSTR (PIPE_BUF)) == 0);
Packit 6c4009
     return 0;
Packit 6c4009
   }
Packit 6c4009
Packit 6c4009
   is expected to compile and meet the assertion. If it does not, your
Packit 6c4009
   compiler compiles some other language than Standard C.
Packit 6c4009
Packit 6c4009
   REQUIREMENTS:
Packit 6c4009
     This program calls gcc to get the list of defined macros. If you
Packit 6c4009
     don't have gcc you're probably out of luck unless your compiler or
Packit 6c4009
     preprocessor has something similar to gcc's -dM option. Tune
Packit 6c4009
     PRINT_MACROS in this case. This program assumes headers are found
Packit 6c4009
     under /usr/include and that there is a writable /tmp directory.
Packit 6c4009
     Tune SYSTEM_INCLUDE if your system differs.
Packit 6c4009
     #define BROKEN_SYSTEM if system(NULL) bombs -- one more violation
Packit 6c4009
     of ISO C, by the way.
Packit 6c4009
Packit 6c4009
   OUTPUT:
Packit 6c4009
     Each header file name is printed, followed by illegal macro names
Packit 6c4009
     and their definition. For the above example, you would see
Packit 6c4009
     ...
Packit 6c4009
     /usr/include/stdio.h
Packit 6c4009
     #define PIPE_BUF 5120
Packit 6c4009
     ...
Packit 6c4009
     If your implementation does not yet incorporate Amendment 1 you
Packit 6c4009
     will see messages about iso646.h, wctype.h and wchar.h not being
Packit 6c4009
     found.  */
Packit 6c4009
Packit 6c4009
#ifndef _GNU_SOURCE
Packit 6c4009
# define _GNU_SOURCE 1
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
Packit 6c4009
#define HEADER_MAX          256
Packit 6c4009
Packit 6c4009
static char macrofile[] = "/tmp/isomac.XXXXXX";
Packit 6c4009
Packit 6c4009
/* ISO C header names including Amendment 1 (without ".h" suffix).  */
Packit 6c4009
static char *header[] =
Packit 6c4009
{
Packit 6c4009
  "assert", "ctype", "errno", "float", "iso646", "limits", "locale",
Packit 6c4009
  "math", "setjmp", "signal", "stdarg", "stddef", "stdio", "stdlib",
Packit 6c4009
  "string", "time", "wchar", "wctype"
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Macros with these prefixes are considered okay.  */
Packit 6c4009
static char *prefix[] =
Packit 6c4009
{
Packit 6c4009
  "_", "E", "is", "str", "mem", "SIG", "FLT_", "DBL_", "LDBL_",
Packit 6c4009
  "LC_", "wmem", "wcs"
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Macros with these suffixes are considered okay.  Will not work for
Packit 6c4009
   parametrized macros with arguments.  */
Packit 6c4009
static char *suffix[] =
Packit 6c4009
{
Packit 6c4009
  "_MAX", "_MIN"
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* These macros are considered okay. In fact, these are just more prefixes.  */
Packit 6c4009
static char *macros[] =
Packit 6c4009
{
Packit 6c4009
  "BUFSIZ", "CHAR_BIT", "CHAR_MAX", "CHAR_MIN", "CLOCKS_PER_SEC",
Packit 6c4009
  "DBL_DIG", "DBL_EPSILON", "DBL_MANT_DIG", "DBL_MAX",
Packit 6c4009
  "DBL_MAX_10_EXP", "DBL_MAX_EXP", "DBL_MIN", "DBL_MIN_10_EXP",
Packit 6c4009
  "DBL_MIN_EXP", "EDOM", "EILSEQ", "EOF", "ERANGE", "EXIT_FAILURE",
Packit 6c4009
  "EXIT_SUCCESS", "FILENAME_MAX", "FLT_DIG", "FLT_EPSILON",
Packit 6c4009
  "FLT_MANT_DIG", "FLT_MAX", "FLT_MAX_10_EXP", "FLT_MAX_EXP",
Packit 6c4009
  "FLT_MIN", "FLT_MIN_10_EXP", "FLT_MIN_EXP", "FLT_RADIX",
Packit 6c4009
  "FLT_ROUNDS", "FOPEN_MAX", "HUGE_VAL", "INT_MAX", "INT_MIN",
Packit 6c4009
  "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", "LC_NUMERIC",
Packit 6c4009
  "LC_TIME", "LDBL_DIG", "LDBL_EPSILON", "LDBL_MANT_DIG", "LDBL_MAX",
Packit 6c4009
  "LDBL_MAX_10_EXP", "LDBL_MAX_EXP", "LDBL_MIN", "LDBL_MIN_10_EXP",
Packit 6c4009
  "LDBL_MIN_EXP", "LONG_MAX", "LONG_MIN", "L_tmpnam", "MB_CUR_MAX",
Packit 6c4009
  "MB_LEN_MAX", "NDEBUG", "NULL", "RAND_MAX", "SCHAR_MAX",
Packit 6c4009
  "SCHAR_MIN", "SEEK_CUR", "SEEK_END", "SEEK_SET", "SHRT_MAX",
Packit 6c4009
  "SHRT_MIN", "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV",
Packit 6c4009
  "SIGTERM", "SIG_DFL", "SIG_ERR", "SIG_IGN", "TMP_MAX", "UCHAR_MAX",
Packit 6c4009
  "UINT_MAX", "ULONG_MAX", "USHRT_MAX", "WCHAR_MAX", "WCHAR_MIN",
Packit 6c4009
  "WEOF", "_IOFBF", "_IOLBF", "_IONBF", "abort", "abs", "acos",
Packit 6c4009
  "acosf", "acosl", "and", "and_eq", "asctime", "asin", "asinf",
Packit 6c4009
  "asinl", "assert", "atan", "atan2", "atan2f", "atan2l", "atanf",
Packit 6c4009
  "atanl", "atexit", "atof", "atoi", "atol", "bitand", "bitor",
Packit 6c4009
  "bsearch", "btowc", "calloc", "ceil", "ceilf", "ceill", "clearerr",
Packit 6c4009
  "clock", "clock_t", "compl", "cos", "cosf", "cosh", "coshf",
Packit 6c4009
  "coshl", "cosl", "ctime", "difftime", "div", "div_t", "errno",
Packit 6c4009
  "exit", "exp", "expf", "expl", "fabs", "fabsf", "fabsl", "fclose",
Packit 6c4009
  "feof", "ferror", "fflush", "fgetc", "fgetpos", "fgets", "fgetwc",
Packit 6c4009
  "fgetws", "floor", "floorf", "floorl", "fmod", "fmodf", "fmodl",
Packit 6c4009
  "fopen", "fprintf", "fputc", "fputs", "fputwc", "fputws", "fread",
Packit 6c4009
  "free", "freopen", "frexp", "frexpf", "frexpl", "fscanf", "fseek",
Packit 6c4009
  "fsetpos", "ftell", "fwide", "fwprintf", "fwrite", "fwscanf",
Packit 6c4009
  "getc", "getchar", "getenv", "gets", "getwc", "getwchar", "gmtime",
Packit 6c4009
  "isalnum", "isalpha", "iscntrl", "isdigit", "isgraph", "islower",
Packit 6c4009
  "isprint", "ispunct", "isspace", "isupper", "iswalnum", "iswalpha",
Packit 6c4009
  "iswcntrl", "iswctype", "iswdigit", "iswgraph", "iswlower",
Packit 6c4009
  "iswprint", "iswpunct", "iswspace", "iswupper", "iswxdigit",
Packit 6c4009
  "isxdigit", "labs", "ldexp", "ldexpf", "ldexpl", "ldiv", "ldiv_t",
Packit 6c4009
  "localeconv", "localtime", "log", "log10", "log10f", "log10l",
Packit 6c4009
  "logf", "logl", "longjmp", "malloc", "mblen", "mbrlen", "mbrtowc",
Packit 6c4009
  "mbsinit", "mbsrtowcs", "mbstate_t", "mbstowcs", "mbtowc", "memchr",
Packit 6c4009
  "memcmp", "memcpy", "memmove", "memset", "mktime", "modf", "modff",
Packit 6c4009
  "modfl", "not", "not_eq", "offsetof", "or", "or_eq", "perror",
Packit 6c4009
  "pow", "powf", "powl", "printf", "ptrdiff_t", "putc", "putchar",
Packit 6c4009
  "puts", "putwc", "putwchar", "qsort", "raise", "rand", "realloc",
Packit 6c4009
  "remove", "rename", "rewind", "scanf", "setbuf", "setjmp",
Packit 6c4009
  "setlocale", "setvbuf", "sig_atomic_t", "signal", "sin", "sinf",
Packit 6c4009
  "sinh", "sinhf", "sinhl", "sinl", "size_t", "sprintf", "sqrt",
Packit 6c4009
  "sqrtf", "sqrtl", "srand", "sscanf", "stderr", "stdin", "stdout",
Packit 6c4009
  "strcat", "strchr", "strcmp", "strcoll", "strcpy", "strcspn",
Packit 6c4009
  "strerror", "strftime", "strlen", "strncat", "strncmp", "strncpy",
Packit 6c4009
  "strpbrk", "strrchr", "strspn", "strstr", "strtod", "strtok",
Packit 6c4009
  "strtol", "strtoul", "strxfrm", "swprintf", "swscanf", "system",
Packit 6c4009
  "tan", "tanf", "tanh", "tanhf", "tanhl", "tanl", "time", "time_t",
Packit 6c4009
  "tmpfile", "tmpnam", "tolower", "toupper", "towctrans", "towlower",
Packit 6c4009
  "towupper", "ungetc", "ungetwc", "va_arg", "va_copy", "va_end", "va_start",
Packit 6c4009
  "vfprintf", "vfwprintf", "vprintf", "vsprintf", "vswprintf",
Packit 6c4009
  "vwprintf", "wchar_t", "wcrtomb", "wcscat", "wcschr", "wcscmp",
Packit 6c4009
  "wcscoll", "wcscpy", "wcscspn", "wcsftime", "wcslen", "wcsncat",
Packit 6c4009
  "wcsncmp", "wcsncpy", "wcspbrk", "wcsrchr", "wcsrtombs", "wcsspn",
Packit 6c4009
  "wcsstr", "wcstod", "wcstok", "wcstol", "wcstombs", "wcstoul",
Packit 6c4009
  "wcsxfrm", "wctob", "wctomb", "wctrans", "wctrans_t", "wctype",
Packit 6c4009
  "wctype_t", "wint_t", "wmemchr", "wmemcmp", "wmemcpy", "wmemmove",
Packit 6c4009
  "wmemset", "wprintf", "wscanf", "xor", "xor_eq"
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
#define NUMBER_OF_HEADERS              (sizeof header / sizeof *header)
Packit 6c4009
#define NUMBER_OF_PREFIXES             (sizeof prefix / sizeof *prefix)
Packit 6c4009
#define NUMBER_OF_SUFFIXES             (sizeof suffix / sizeof *suffix)
Packit 6c4009
#define NUMBER_OF_MACROS               (sizeof macros / sizeof *macros)
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Format string to build command to invoke compiler.  */
Packit 6c4009
static const char fmt[] = "\
Packit 6c4009
echo \"#include <%s>\" |\
Packit 6c4009
%s -E -dM -ansi -pedantic %s -D_LIBC -D_ISOMAC \
Packit 6c4009
-DIN_MODULE=MODULE_extramodules -I. \
Packit 6c4009
-isystem `%s --print-prog-name=include` - 2> /dev/null > %s";
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* The compiler we use (given on the command line).  */
Packit 6c4009
char *CC;
Packit 6c4009
/* The -I parameters for CC to find all headers.  */
Packit 6c4009
char *INC;
Packit 6c4009
Packit 6c4009
static char *xstrndup (const char *, size_t);
Packit 6c4009
static const char **get_null_defines (void);
Packit 6c4009
static int check_header (const char *, const char **);
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
main (int argc, char *argv[])
Packit 6c4009
{
Packit 6c4009
  int h;
Packit 6c4009
  int result = 0;
Packit 6c4009
  const char **ignore_list;
Packit 6c4009
Packit 6c4009
  CC = argc > 1 ? argv[1] : "gcc";
Packit 6c4009
  INC = argc > 2 ? argv[2] : "";
Packit 6c4009
Packit 6c4009
  if (system (NULL) == 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("Sorry, no command processor.");
Packit 6c4009
      return EXIT_FAILURE;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* First get list of symbols which are defined by the compiler.  */
Packit 6c4009
  ignore_list = get_null_defines ();
Packit 6c4009
Packit 6c4009
  fputs ("Tested files:\n", stdout);
Packit 6c4009
Packit 6c4009
  for (h = 0; h < NUMBER_OF_HEADERS; ++h)
Packit 6c4009
    {
Packit 6c4009
      char file_name[HEADER_MAX];
Packit 6c4009
      sprintf (file_name, "%s.h", header[h]);
Packit 6c4009
      result |= check_header (file_name, ignore_list);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  remove (macrofile);
Packit 6c4009
Packit 6c4009
  /* The test suite should return errors but for now this is not
Packit 6c4009
     practical.  Give a warning and ask the user to correct the bugs.  */
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static char *
Packit 6c4009
xstrndup (const char *s, size_t n)
Packit 6c4009
{
Packit 6c4009
  size_t len = n;
Packit 6c4009
  char *new = malloc (len + 1);
Packit 6c4009
Packit 6c4009
  if (new == NULL)
Packit 6c4009
    return NULL;
Packit 6c4009
Packit 6c4009
  new[len] = '\0';
Packit 6c4009
  return memcpy (new, s, len);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static const char **
Packit 6c4009
get_null_defines (void)
Packit 6c4009
{
Packit 6c4009
  char line[BUFSIZ], *command;
Packit 6c4009
  char **result = NULL;
Packit 6c4009
  size_t result_len = 0;
Packit 6c4009
  size_t result_max = 0;
Packit 6c4009
  FILE *input;
Packit 6c4009
  int first = 1;
Packit 6c4009
Packit 6c4009
  int fd = mkstemp (macrofile);
Packit 6c4009
  if (fd == -1)
Packit 6c4009
    {
Packit 6c4009
      printf ("mkstemp failed: %m\n");
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
  close (fd);
Packit 6c4009
Packit 6c4009
  command = malloc (sizeof fmt + sizeof "/dev/null" + 2 * strlen (CC)
Packit 6c4009
		    + strlen (INC) + strlen (macrofile));
Packit 6c4009
Packit 6c4009
  if (command == NULL)
Packit 6c4009
    {
Packit 6c4009
      puts ("No more memory.");
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  sprintf (command, fmt, "/dev/null", CC, INC, CC, macrofile);
Packit 6c4009
Packit 6c4009
  if (system (command))
Packit 6c4009
    {
Packit 6c4009
      puts ("system() returned nonzero");
Packit 6c4009
      free (command);
Packit 6c4009
      return NULL;
Packit 6c4009
    }
Packit 6c4009
  free (command);
Packit 6c4009
  input = fopen (macrofile, "r");
Packit 6c4009
Packit 6c4009
  if (input == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("Could not read %s: ", macrofile);
Packit 6c4009
      perror (NULL);
Packit 6c4009
      return NULL;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  while (fgets (line, sizeof line, input) != NULL)
Packit 6c4009
    {
Packit 6c4009
      int i, okay = 0;
Packit 6c4009
      size_t endmac;
Packit 6c4009
      char *start, *end;
Packit 6c4009
      if (strlen (line) < 9 || line[7] != ' ')
Packit 6c4009
	{ /* "#define A" */
Packit 6c4009
	  printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
Packit 6c4009
		  line);
Packit 6c4009
	  continue;
Packit 6c4009
	}
Packit 6c4009
      if (line[8] == '_')
Packit 6c4009
	/* It's a safe identifier.  */
Packit 6c4009
	continue;
Packit 6c4009
      if (result_len == result_max)
Packit 6c4009
	{
Packit 6c4009
	  result_max += 10;
Packit 6c4009
	  result = realloc (result, result_max * sizeof (char **));
Packit 6c4009
	  if (result == NULL)
Packit 6c4009
	    {
Packit 6c4009
	      puts ("No more memory.");
Packit 6c4009
	      exit (1);
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      start = &line[8];
Packit 6c4009
      for (end = start + 1; !isspace (*end) && *end != '\0'; ++end)
Packit 6c4009
	;
Packit 6c4009
      result[result_len] = xstrndup (start, end - start);
Packit 6c4009
Packit 6c4009
      if (strcmp (result[result_len], "IN_MODULE") != 0)
Packit 6c4009
	{
Packit 6c4009
	  if (first)
Packit 6c4009
	    {
Packit 6c4009
	      fputs ("The following identifiers will be ignored since the compiler defines them\nby default:\n", stdout);
Packit 6c4009
	      first = 0;
Packit 6c4009
	    }
Packit 6c4009
	  puts (result[result_len]);
Packit 6c4009
	}
Packit 6c4009
      ++result_len;
Packit 6c4009
    }
Packit 6c4009
  if (result_len == result_max)
Packit 6c4009
    {
Packit 6c4009
      result_max += 1;
Packit 6c4009
      result = realloc (result, result_max * sizeof (char **));
Packit 6c4009
      if (result == NULL)
Packit 6c4009
	{
Packit 6c4009
	  puts ("No more memory.");
Packit 6c4009
	  exit (1);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  result[result_len] = NULL;
Packit 6c4009
  fclose (input);
Packit 6c4009
Packit 6c4009
  return (const char **) result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
check_header (const char *file_name, const char **except)
Packit 6c4009
{
Packit 6c4009
  char line[BUFSIZ], *command;
Packit 6c4009
  FILE *input;
Packit 6c4009
  int result = 0;
Packit 6c4009
Packit 6c4009
  command = malloc (sizeof fmt + strlen (file_name) + 2 * strlen (CC)
Packit 6c4009
		    + strlen (INC) + strlen (macrofile));
Packit 6c4009
Packit 6c4009
  if (command == NULL)
Packit 6c4009
    {
Packit 6c4009
      puts ("No more memory.");
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  puts (file_name);
Packit 6c4009
  sprintf (command, fmt, file_name, CC, INC, CC, macrofile);
Packit 6c4009
Packit 6c4009
  if (system (command))
Packit 6c4009
    {
Packit 6c4009
      puts ("system() returned nonzero");
Packit 6c4009
      result = 1;
Packit 6c4009
    }
Packit 6c4009
  free (command);
Packit 6c4009
  input = fopen (macrofile, "r");
Packit 6c4009
Packit 6c4009
  if (input == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("Could not read %s: ", macrofile);
Packit 6c4009
      perror (NULL);
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  while (fgets (line, sizeof line, input) != NULL)
Packit 6c4009
    {
Packit 6c4009
      int i, okay = 0;
Packit 6c4009
      size_t endmac;
Packit 6c4009
      const char **cpp;
Packit 6c4009
      if (strlen (line) < 9 || line[7] != ' ')
Packit 6c4009
	{ /* "#define A" */
Packit 6c4009
	  printf ("Malformed input, expected '#define MACRO'\ngot '%s'\n",
Packit 6c4009
		  line);
Packit 6c4009
	  result = 1;
Packit 6c4009
	  continue;
Packit 6c4009
	}
Packit 6c4009
      for (i = 0; i < NUMBER_OF_PREFIXES; ++i)
Packit 6c4009
	{
Packit 6c4009
	  if (!strncmp (line+8, prefix[i], strlen (prefix[i]))) {
Packit 6c4009
	    ++okay;
Packit 6c4009
	    break;
Packit 6c4009
	  }
Packit 6c4009
	}
Packit 6c4009
      if (okay)
Packit 6c4009
	continue;
Packit 6c4009
      for (i = 0; i < NUMBER_OF_MACROS; ++i)
Packit 6c4009
	{
Packit 6c4009
	  if (!strncmp (line + 8, macros[i], strlen (macros[i])))
Packit 6c4009
	    {
Packit 6c4009
	      ++okay;
Packit 6c4009
	      break;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      if (okay)
Packit 6c4009
	continue;
Packit 6c4009
      /* Find next char after the macro identifier; this can be either
Packit 6c4009
	 a space or an open parenthesis.  */
Packit 6c4009
      endmac = strcspn (line + 8, " (");
Packit 6c4009
      if (line[8+endmac] == '\0')
Packit 6c4009
	{
Packit 6c4009
	  printf ("malformed input, expected '#define MACRO VALUE'\n"
Packit 6c4009
		  "got '%s'\n", line);
Packit 6c4009
	  result = 1;
Packit 6c4009
	  continue;
Packit 6c4009
	}
Packit 6c4009
      for (i = 0; i < NUMBER_OF_SUFFIXES; ++i)
Packit 6c4009
	{
Packit 6c4009
	  size_t len = strlen (suffix[i]);
Packit 6c4009
	  if (!strncmp (line + 8 + endmac - len, suffix[i], len))
Packit 6c4009
	    {
Packit 6c4009
	      ++okay;
Packit 6c4009
	      break;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
      if (okay)
Packit 6c4009
	continue;
Packit 6c4009
      if (except != NULL)
Packit 6c4009
	for (cpp = except; *cpp != NULL; ++cpp)
Packit 6c4009
	  {
Packit 6c4009
	    size_t len = strlen (*cpp);
Packit 6c4009
	    if (!strncmp (line + 8, *cpp, len) && isspace (line[8 + len]))
Packit 6c4009
	      {
Packit 6c4009
		++okay;
Packit 6c4009
		break;
Packit 6c4009
	      }
Packit 6c4009
	  }
Packit 6c4009
      if (!okay)
Packit 6c4009
	{
Packit 6c4009
	  fputs (line, stdout);
Packit 6c4009
	  result = 2;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  fclose (input);
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* EOF */