/* C Compatible Compiler Preprocessor (CCCP)
- Copyright (C) 1986, 87, 89, 92-96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1986, 87, 89, 92-97, 1998 Free Software Foundation, Inc.
Written by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+Boston, MA 02111-1307, USA. */
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding! */
-\f
-typedef unsigned char U_CHAR;
-
-#ifdef EMACS
-#define NO_SHORTNAMES
-#include "../src/config.h"
-#ifdef open
-#undef open
-#undef read
-#undef write
-#endif /* open */
-#endif /* EMACS */
-
-/* The macro EMACS is defined when cpp is distributed as part of Emacs,
- for the sake of machines with limited C compilers. */
-#ifndef EMACS
#include "config.h"
-#endif /* not EMACS */
-
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
-#endif
-
-#include "pcp.h"
-
-/* By default, colon separates directories in a path. */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
-#endif
-
-/* By default, the suffix for object files is ".o". */
-#ifdef OBJECT_SUFFIX
-#define HAVE_OBJECT_SUFFIX
-#else
-#define OBJECT_SUFFIX ".o"
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <signal.h>
-
-/* The following symbols should be autoconfigured:
- HAVE_FCNTL_H
- HAVE_SYS_TIME_H
- STDC_HEADERS
- TIME_WITH_SYS_TIME
- In the mean time, we'll get by with approximations based
- on existing GCC configuration symbols. */
-
-#ifdef POSIX
-# ifndef STDC_HEADERS
-# define STDC_HEADERS 1
-# endif
-#endif /* defined (POSIX) */
-
-#if defined (POSIX) || (defined (USG) && !defined (VMS))
-# ifndef HAVE_FCNTL_H
-# define HAVE_FCNTL_H 1
-# endif
-#endif
-
-#ifndef RLIMIT_STACK
-# include <time.h>
-#else
-# if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-# else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-# endif
-# include <sys/resource.h>
-#endif
-
-#if HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-#if HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#include <errno.h>
-
-#if HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-char *getenv ();
-#endif
-
-#if STDC_HEADERS
-# include <string.h>
-# ifndef bcmp
-# define bcmp(a, b, n) memcmp (a, b, n)
-# endif
-# ifndef bcopy
-# define bcopy(s, d, n) memcpy (d, s, n)
-# endif
-# ifndef bzero
-# define bzero(d, n) memset (d, 0, n)
-# endif
-#else /* !STDC_HEADERS */
-char *index ();
-char *rindex ();
-
-# if !defined (BSTRING) && (defined (USG) || defined (VMS))
-
-# ifndef bcmp
-# define bcmp my_bcmp
-static int
-my_bcmp (a, b, n)
- register char *a;
- register char *b;
- register unsigned n;
-{
- while (n-- > 0)
- if (*a++ != *b++)
- return 1;
-
- return 0;
-}
-# endif /* !defined (bcmp) */
-
-# ifndef bcopy
-# define bcopy my_bcopy
-static void
-my_bcopy (s, d, n)
- register char *s;
- register char *d;
- register unsigned n;
-{
- while (n-- > 0)
- *d++ = *s++;
-}
-# endif /* !defined (bcopy) */
-
-# ifndef bzero
-# define bzero my_bzero
-static void
-my_bzero (b, length)
- register char *b;
- register unsigned length;
-{
- while (length-- > 0)
- *b++ = 0;
-}
-# endif /* !defined (bzero) */
-
-# endif /* !defined (BSTRING) && (defined (USG) || defined (VMS)) */
-#endif /* ! STDC_HEADERS */
-
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
-# define __attribute__(x)
-#endif
-
-#ifndef PROTO
-# if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-# define PROTO(ARGS) ARGS
-# else
-# define PROTO(ARGS) ()
-# endif
-#endif
-
#if defined (__STDC__) && defined (HAVE_VPRINTF)
# include <stdarg.h>
-# define VA_START(va_list, var) va_start (va_list, var)
# define PRINTF_ALIST(msg) char *msg, ...
# define PRINTF_DCL(msg)
# define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (__printf__, m, n)))
#else
# include <varargs.h>
-# define VA_START(va_list, var) va_start (va_list)
# define PRINTF_ALIST(msg) msg, va_alist
# define PRINTF_DCL(msg) char *msg; va_dcl
# define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (__printf__, m, n)))
#define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
#define PRINTF_PROTO_2(ARGS) PRINTF_PROTO(ARGS, 2, 3)
#define PRINTF_PROTO_3(ARGS) PRINTF_PROTO(ARGS, 3, 4)
+#define PRINTF_PROTO_4(ARGS) PRINTF_PROTO(ARGS, 4, 5)
-#if HAVE_UNISTD_H
-# include <unistd.h>
+#include "system.h"
+#include <sys/stat.h>
+#include <signal.h>
+
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
+typedef unsigned char U_CHAR;
+
+#include "gansidecl.h"
+#include "pcp.h"
+
+#ifndef GET_ENVIRONMENT
+#define GET_ENVIRONMENT(ENV_VALUE,ENV_NAME) ENV_VALUE = getenv (ENV_NAME)
+#endif
+
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __attribute__(x)
+#endif
+
+#ifndef STANDARD_INCLUDE_DIR
+# define STANDARD_INCLUDE_DIR "/usr/include"
+#endif
+
+/* By default, colon separates directories in a path. */
+#ifndef PATH_SEPARATOR
+# define PATH_SEPARATOR ':'
+#endif
+
+/* By default, the suffix for object files is ".o". */
+#ifdef OBJECT_SUFFIX
+# define HAVE_OBJECT_SUFFIX
+#else
+# define OBJECT_SUFFIX ".o"
#endif
/* VMS-specific definitions */
#ifdef VMS
#include <descrip.h>
+#include <ssdef.h>
+#include <syidef.h>
#define open(fname,mode,prot) VMS_open (fname,mode,prot)
#define fopen(fname,mode) VMS_fopen (fname,mode)
#define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
#define INO_T_EQ(a, b) 0
#endif
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
#undef MIN
#undef MAX
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
# include <inttypes.h>
# define HOST_WIDE_INT intmax_t
# else
-# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \
- && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
+# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
# define HOST_WIDE_INT int
# else
-# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \
- || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
+# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
# define HOST_WIDE_INT long
# else
# define HOST_WIDE_INT long long
#define INO_T_HASH(a) (a)
#endif
-/* Define a generic NULL if one hasn't already been defined. */
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef GENERIC_PTR
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define GENERIC_PTR void *
-#else
-#define GENERIC_PTR char *
-#endif
-#endif
-
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR) 0)
-#endif
-
#ifndef INCLUDE_LEN_FUDGE
#define INCLUDE_LEN_FUDGE 0
#endif
char *strerror (int,...);
#endif
HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
-HOST_WIDE_INT parse_c_expression PROTO((char *));
-
-#ifndef errno
-extern int errno;
-#endif
+HOST_WIDE_INT parse_c_expression PROTO((char *, int));
\f
/* Name under which this program was invoked. */
static int debug_output = 0;
/* Nonzero means pass #include lines through to the output,
- even if they are ifdeffed out. */
+ even if they are ifdefed out. */
static int dump_includes;
/* Nonzero indicates special processing used by the pcp program. The
/* Nonzero means warn if undefined identifiers are evaluated in an #if. */
-int warn_undef;
+static int warn_undef;
/* Nonzero means warn if #import is used. */
static int no_output;
+/* Nonzero means we should look for header.gcc files that remap file names. */
+static int remap;
+
/* Nonzero means this file was included with a -imacros or -include
command line and should not be recorded as an include file. */
char *fname;
/* Filename specified with #line directive. */
char *nominal_fname;
+ /* The length of nominal_fname, which may contain embedded NULs. */
+ size_t nominal_fname_len;
/* Include file description. */
struct include_file *inc;
/* Record where in the search path this file was found.
U_CHAR *expansion;
int line; /* Line number of definition */
char *file; /* File of definition */
+ size_t file_len; /* Length of file (which can contain NULs) */
char rest_args; /* Nonzero if last arg. absorbs the rest */
struct reflist {
struct reflist *next;
enum node_type type; /* Code which describes which directive. */
};
-#define IS_INCLUDE_DIRECTIVE_TYPE(t) (T_INCLUDE <= (t) && (t) <= T_IMPORT)
+#define IS_INCLUDE_DIRECTIVE_TYPE(t) \
+((int) T_INCLUDE <= (int) (t) && (int) (t) <= (int) T_IMPORT)
/* These functions are declared to return int instead of void since they
are going to be placed in the table and some old compilers have trouble with
struct if_stack {
struct if_stack *next; /* for chaining to the next stack frame */
char *fname; /* copied from input when frame is made */
+ size_t fname_len; /* similarly */
int lineno; /* similarly */
int if_succeeded; /* true if a leg of this if-group
has been passed through rescan */
\f
static int safe_read PROTO((int, char *, int));
static void safe_write PROTO((int, char *, int));
+static void eprint_string PROTO((char *, size_t));
int main PROTO((int, char **));
static U_CHAR *skip_to_end_of_comment PROTO((FILE_BUF *, int *, int));
static U_CHAR *skip_quoted_string PROTO((U_CHAR *, U_CHAR *, int, int *, int *, int *));
-static char *quote_string PROTO((char *, char *));
+static char *quote_string PROTO((char *, char *, size_t));
static U_CHAR *skip_paren_group PROTO((FILE_BUF *));
/* Last arg to output_line_directive. */
struct argdata;
static char *macarg PROTO((struct argdata *, int));
-static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, int *, int *, int *, int));
+static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, struct hashnode *, int *, int *, int *, int));
static int discard_comments PROTO((U_CHAR *, int, int));
static void warning_with_line PRINTF_PROTO_2((int, char *, ...));
void pedwarn PRINTF_PROTO_1((char *, ...));
void pedwarn_with_line PRINTF_PROTO_2((int, char *, ...));
-static void pedwarn_with_file_and_line PRINTF_PROTO_3((char *, int, char *, ...));
+static void pedwarn_with_file_and_line PRINTF_PROTO_4((char *, size_t, int, char *, ...));
static void print_containing_files PROTO((void));
static struct file_name_list *new_include_prefix PROTO((struct file_name_list *, char *, char *, char *));
static void append_include_chain PROTO((struct file_name_list *, struct file_name_list *));
+static int quote_string_for_make PROTO((char *, char *));
static void deps_output PROTO((char *, int));
static void fatal PRINTF_PROTO_1((char *, ...)) __attribute__ ((noreturn));
len -= written;
}
}
+
+/* Print a string to stderr, with extra handling in case it contains
+ embedded NUL characters. Any present are written as is.
+
+ Using fwrite for this purpose produces undesireable results on VMS
+ when stderr happens to be a record oriented file, such as a batch log
+ file, rather than a stream oriented one. */
+
+static void
+eprint_string (string, length)
+ char *string;
+ size_t length;
+{
+ size_t segment_length;
+
+ do {
+ fprintf(stderr, "%s", string);
+ length -= (segment_length = strlen(string));
+ if (length > 0)
+ {
+ fputc('\0', stderr);
+ length -= 1;
+ /* Advance past the portion which has already been printed. */
+ string += segment_length + 1;
+ }
+ } while (length > 0);
+}
+
\f
int
main (argc, argv)
/* Target-name to write with the dependency information. */
char *deps_target = 0;
-#ifdef RLIMIT_STACK
+#if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT)
/* Get rid of any avoidable limit on stack size. */
{
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max;
setrlimit (RLIMIT_STACK, &rlim);
}
-#endif /* RLIMIT_STACK defined */
+#endif
#ifdef SIGPIPE
signal (SIGPIPE, pipe_closed);
case 'i':
if (!strcmp (argv[i], "-include")) {
+ int temp = i;
+
if (i + 1 == argc)
fatal ("Filename missing after `-include' option");
else
- simplify_filename (pend_includes[i] = argv[++i]);
+ simplify_filename (pend_includes[temp] = argv[++i]);
}
if (!strcmp (argv[i], "-imacros")) {
+ int temp = i;
+
if (i + 1 == argc)
fatal ("Filename missing after `-imacros' option");
else
- simplify_filename (pend_files[i] = argv[++i]);
+ simplify_filename (pend_files[temp] = argv[++i]);
}
if (!strcmp (argv[i], "-iprefix")) {
if (i + 1 == argc)
no_precomp = 1;
break;
+ case 'r':
+ if (!strcmp (argv[i], "-remap"))
+ remap = 1;
+ break;
+
case 'u':
/* Sun compiler passes undocumented switch "-undef".
Let's assume it means to inhibit the predefined symbols. */
/* Some people say that CPATH should replace the standard include dirs,
but that seems pointless: it comes before them, so it overrides them
anyway. */
- cp = getenv ("CPATH");
+ GET_ENVIRONMENT (cp, "CPATH");
if (cp && ! no_standard_includes)
path_include (cp);
if (in_fname == NULL)
in_fname = "";
fp->nominal_fname = fp->fname = in_fname;
+ fp->nominal_fname_len = strlen (in_fname);
fp->lineno = 0;
/* In C++, wchar_t is a distinct basic type, and we can expect
if (!inhibit_predefs) {
char *p = (char *) alloca (strlen (predefs) + 1);
+
+#ifdef VMS
+ struct dsc$descriptor_s lcl_name;
+ struct item_list {
+ unsigned short length; /* input length */
+ unsigned short code; /* item code */
+ unsigned long dptr; /* data ptr */
+ unsigned long lptr; /* output length ptr */
+ };
+
+ unsigned long syi_length;
+ char syi_data[16];
+
+ struct item_list items[] = {
+ { 16, SYI$_VERSION, 0, 0 },
+ { 0, 0, 0, 0 }
+ };
+
+ items[0].dptr = (unsigned long)syi_data;
+ items[0].lptr = (unsigned long)(&syi_length);
+
+ if (SYS$GETSYIW (0, 0, 0, items, NULL, NULL, NULL, NULL) == SS$_NORMAL)
+ {
+ unsigned long vms_version_value;
+ char *vers;
+
+ vers = syi_data;
+ vms_version_value = 0;
+
+ if (*vers == 'V')
+ vers++;
+ if (ISDIGIT (*vers))
+ {
+ vms_version_value = (*vers - '0') * 10000000;
+ }
+ vers++;
+ if (*vers == '.')
+ {
+ vers++;
+ if (ISDIGIT (*vers))
+ {
+ vms_version_value += (*vers - '0') * 100000;
+ }
+ }
+
+ if (vms_version_value > 0)
+ {
+ char versbuf[32];
+
+ sprintf (versbuf, "__VMS_VER=%08ld", vms_version_value);
+ if (debug_output)
+ output_line_directive (fp, &outbuf, 0, same_file);
+ make_definition (versbuf, &outbuf);
+ }
+ }
+#endif
+
strcpy (p, predefs);
while (*p) {
char *q;
switch ((objc << 1) + cplusplus)
{
case 0:
- epath = getenv ("C_INCLUDE_PATH");
+ GET_ENVIRONMENT (epath, "C_INCLUDE_PATH");
break;
case 1:
- epath = getenv ("CPLUS_INCLUDE_PATH");
+ GET_ENVIRONMENT (epath, "CPLUS_INCLUDE_PATH");
break;
case 2:
- epath = getenv ("OBJC_INCLUDE_PATH");
+ GET_ENVIRONMENT (epath, "OBJC_INCLUDE_PATH");
break;
case 3:
- epath = getenv ("OBJCPLUS_INCLUDE_PATH");
+ GET_ENVIRONMENT (epath, "OBJCPLUS_INCLUDE_PATH");
break;
}
/* If the environment var for this language is set,
if (fstat (f, &st) != 0)
pfatal_with_name (in_fname);
fp->nominal_fname = fp->fname = in_fname;
+ fp->nominal_fname_len = strlen (in_fname);
fp->lineno = 1;
fp->system_header_p = 0;
/* JF all this is mine about reading pipes and ttys */
} else {
/* Read a file whose size we can determine in advance.
For the sake of VMS, st.st_size is just an upper bound. */
- fp->buf = (U_CHAR *) xmalloc (st.st_size + 2);
- fp->length = safe_read (f, (char *) fp->buf, st.st_size);
+ size_t s = (size_t) st.st_size;
+ if (s != st.st_size || s + 2 < s)
+ memory_full ();
+ fp->buf = (U_CHAR *) xmalloc (s + 2);
+ fp->length = safe_read (f, (char *) fp->buf, s);
if (fp->length < 0) goto perror;
}
fp->bufp = fp->buf;
if ((linsize >= 7) && !bcmp (ibp, "VARARGS", 7)) {
*cmdlen = 7;
ibp += 7; linsize -= 7;
- if ((linsize == 0) || ! isdigit (*ibp)) return "VARARGS";
+ if ((linsize == 0) || ! ISDIGIT (*ibp)) return "VARARGS";
/* OK, read a number */
- for (numptr = *argstart = ibp; (numptr < limit) && isdigit (*numptr);
+ for (numptr = *argstart = ibp; (numptr < limit) && ISDIGIT (*numptr);
numptr++);
*arglen = numptr - *argstart;
return "VARARGS";
/* Handle any pending identifier;
but the L in L'...' or L"..." is not an identifier. */
- if (ident_length
- && ! (ident_length == 1 && hash == HASHSTEP (0, 'L')))
- goto specialchar;
+ if (ident_length) {
+ if (! (ident_length == 1 && hash == HASHSTEP (0, 'L')))
+ goto specialchar;
+ ident_length = hash = 0;
+ }
start_line = ip->lineno;
if (!traditional) {
error_with_line (line_for_error (start_line),
"unterminated string or character constant");
- error_with_line (multiline_string_line,
- "possible real start of unterminated constant");
- multiline_string_line = 0;
+ if (multiline_string_line) {
+ error_with_line (multiline_string_line,
+ "possible real start of unterminated constant");
+ multiline_string_line = 0;
+ }
}
break;
}
break;
case '\\':
- if (ibp >= limit)
- break;
if (*ibp == '\n') {
- /* Backslash newline is replaced by nothing at all,
- but keep the line counts correct. */
- --obp;
+ /* Backslash newline is replaced by nothing at all, but
+ keep the line counts correct. But if we are reading
+ from a macro, keep the backslash newline, since backslash
+ newlines have already been processed. */
+ if (ip->macro)
+ *obp++ = '\n';
+ else
+ --obp;
++ibp;
++ip->lineno;
} else {
/* ANSI stupidly requires that in \\ the second \
is *not* prevented from combining with a newline. */
- while (*ibp == '\\' && ibp[1] == '\n') {
- ibp += 2;
- ++ip->lineno;
+ if (!ip->macro) {
+ while (*ibp == '\\' && ibp[1] == '\n') {
+ ibp += 2;
+ ++ip->lineno;
+ }
}
*obp++ = *ibp++;
}
break;
case '/':
+ if (ip->macro != 0)
+ goto randomchar;
if (*ibp == '\\' && ibp[1] == '\n')
newline_fix (ibp);
-
if (*ibp != '*'
&& !(cplusplus_comments && *ibp == '/'))
goto randomchar;
- if (ip->macro != 0)
- goto randomchar;
if (ident_length)
goto specialchar;
if (ident_length == 0) {
for (;;) {
- while (ibp[0] == '\\' && ibp[1] == '\n') {
- ++ip->lineno;
- ibp += 2;
+ if (!ip->macro) {
+ while (ibp[0] == '\\' && ibp[1] == '\n') {
+ ++ip->lineno;
+ ibp += 2;
+ }
}
c = *ibp++;
if (!is_idchar[c] && c != '.') {
/* A sign can be part of a preprocessing number
if it follows an `e' or `p'. */
if (c == 'e' || c == 'E' || c == 'p' || c == 'P') {
- while (ibp[0] == '\\' && ibp[1] == '\n') {
- ++ip->lineno;
- ibp += 2;
+ if (!ip->macro) {
+ while (ibp[0] == '\\' && ibp[1] == '\n') {
+ ++ip->lineno;
+ ibp += 2;
+ }
}
if (*ibp == '+' || *ibp == '-') {
*obp++ = *ibp++;
old_iln = ip->lineno;
old_oln = op->lineno;
}
- /* A comment: copy it unchanged or discard it. */
- else if (*ibp == '/' && ibp[1] == '*') {
- if (put_out_comments) {
- *obp++ = '/';
- *obp++ = '*';
- } else if (! traditional) {
- *obp++ = ' ';
- }
- ibp += 2;
- while (ibp + 1 != limit
- && !(ibp[0] == '*' && ibp[1] == '/')) {
- /* We need not worry about newline-marks,
- since they are never found in comments. */
- if (*ibp == '\n') {
- /* Newline in a file. Count it. */
- ++ip->lineno;
- ++op->lineno;
- }
- if (put_out_comments)
- *obp++ = *ibp++;
- else
- ibp++;
- }
- ibp += 2;
- if (put_out_comments) {
- *obp++ = '*';
- *obp++ = '/';
- }
- }
else if (is_space[*ibp]) {
*obp++ = *ibp++;
if (ibp[-1] == '\n') {
}
}
}
+ else if (ip->macro)
+ break;
+ else if (*ibp == '/') {
+ /* If a comment, copy it unchanged or discard it. */
+ if (ibp[1] == '\\' && ibp[2] == '\n')
+ newline_fix (ibp + 1);
+ if (ibp[1] == '*') {
+ if (put_out_comments) {
+ *obp++ = '/';
+ *obp++ = '*';
+ } else if (! traditional) {
+ *obp++ = ' ';
+ }
+ for (ibp += 2; ibp < limit; ibp++) {
+ /* We need not worry about newline-marks,
+ since they are never found in comments. */
+ if (ibp[0] == '*') {
+ if (ibp[1] == '\\' && ibp[2] == '\n')
+ newline_fix (ibp + 1);
+ if (ibp[1] == '/') {
+ ibp += 2;
+ if (put_out_comments) {
+ *obp++ = '*';
+ *obp++ = '/';
+ }
+ break;
+ }
+ }
+ if (*ibp == '\n') {
+ /* Newline in a file. Count it. */
+ ++ip->lineno;
+ ++op->lineno;
+ }
+ if (put_out_comments)
+ *obp++ = *ibp;
+ }
+ } else if (ibp[1] == '/' && cplusplus_comments) {
+ if (put_out_comments) {
+ *obp++ = '/';
+ *obp++ = '/';
+ } else if (! traditional) {
+ *obp++ = ' ';
+ }
+ for (ibp += 2; *ibp != '\n' || ibp[-1] == '\\'; ibp++)
+ if (put_out_comments)
+ *obp++ = *ibp;
+ } else
+ break;
+ }
+ else if (ibp[0] == '\\' && ibp[1] == '\n') {
+ ibp += 2;
+ ++ip->lineno;
+ }
else break;
}
if (*ibp != '(') {
ip = &instack[indepth];
ip->fname = 0;
ip->nominal_fname = 0;
+ ip->nominal_fname_len = 0;
ip->inc = 0;
ip->system_header_p = 0;
ip->macro = 0;
if (*bp != ' ' && *bp != '\t' && pedantic)
pedwarn ("%s in preprocessing directive", char_name[*bp]);
bp++;
- } else if (*bp == '/' && (bp[1] == '*'
- || (cplusplus_comments && bp[1] == '/'))) {
+ } else if (*bp == '/') {
+ if (bp[1] == '\\' && bp[2] == '\n')
+ newline_fix (bp + 1);
+ if (! (bp[1] == '*' || (cplusplus_comments && bp[1] == '/')))
+ break;
ip->bufp = bp + 2;
skip_to_end_of_comment (ip, &ip->lineno, 0);
bp = ip->bufp;
}
break;
+ case '"':
+ /* "..." is special for #include. */
+ if (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) {
+ while (bp < limit && *bp != '\n') {
+ if (*bp == '"') {
+ bp++;
+ break;
+ }
+ if (*bp == '\\' && bp[1] == '\n') {
+ ip->lineno++;
+ copy_directive = 1;
+ bp++;
+ }
+ bp++;
+ }
+ break;
+ }
+ /* Fall through. */
case '\'':
- case '\"':
bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, ©_directive, &unterminated);
/* Don't bother calling the directive if we already got an error
message due to unterminated string. Skip everything and pretend
= skip_quoted_string (xp - 1, bp, ip->lineno,
NULL_PTR, NULL_PTR, NULL_PTR);
while (xp != bp1)
- if (*xp == '\\') {
- if (*++xp != '\n')
- *cp++ = '\\';
- else
- xp++;
- } else
- *cp++ = *xp++;
+ *cp++ = *xp++;
}
break;
directives through. */
if (!no_output && already_output == 0
- && (kt->type == T_DEFINE ? dump_names <= dump_macros
+ && (kt->type == T_DEFINE ? (int) dump_names <= (int) dump_macros
: IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes
: kt->type == T_PRAGMA)) {
int len;
case T_FILE:
case T_BASE_FILE:
{
- char *string;
- if (hp->type == T_FILE)
- string = ip->nominal_fname;
- else
- string = instack[0].nominal_fname;
+ FILE_BUF *p = hp->type == T_FILE ? ip : &instack[0];
+ char *string = p->nominal_fname;
if (string)
{
- buf = (char *) alloca (3 + 4 * strlen (string));
- quote_string (buf, string);
+ size_t string_len = p->nominal_fname_len;
+ buf = (char *) alloca (3 + 4 * string_len);
+ quote_string (buf, string, string_len);
}
else
buf = "\"\"";
FILE_BUF *fp;
/* Copy the operand text, concatenating the strings. */
{
- while (fin != limit) {
- while (fin != limit && *fin != '\"')
- *fend++ = *fin++;
- fin++;
+ for (;;) {
+ for (;;) {
+ if (fin == limit)
+ goto invalid_include_file_name;
+ *fend = *fin++;
+ if (*fend == '"')
+ break;
+ fend++;
+ }
if (fin == limit)
break;
/* If not at the end, there had better be another string. */
/* Found a named file. Figure out dir of the file,
and put it in front of the search list. */
dsp = ((struct file_name_list *)
- alloca (sizeof (struct file_name_list) + strlen (nam)));
+ alloca (sizeof (struct file_name_list)
+ + fp->nominal_fname_len));
strcpy (dsp->fname, nam);
simplify_filename (dsp->fname);
nam = base_name (dsp->fname);
* code from case '<' is repeated here) and generates a warning.
* (Note: macro expansion of `xyz' takes precedence.)
*/
- if (retried && isalpha(*(U_CHAR *) (--fbeg))) {
- while (fin != limit && (!isspace(*fin)))
+ /* Note: The argument of ISALPHA() can be evaluated twice, so do
+ the pre-decrement outside of the macro. */
+ if (retried && (--fbeg, ISALPHA(*(U_CHAR *) (fbeg)))) {
+ while (fin != limit && (!ISSPACE(*fin)))
*fend++ = *fin++;
warning ("VAX-C-style include specification found, use '#include <filename.h>' !");
vaxc_include = 1;
#endif
fail:
- if (retried) {
- error ("`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
- return 0;
- } else {
+ if (! retried) {
/* Expand buffer and then remove any newline markers.
We can't just tell expand_to_temp_buffer to omit the markers,
since it would put extra spaces in include file names. */
FILE_BUF trybuf;
U_CHAR *src;
+ int errors_before_expansion = errors;
trybuf = expand_to_temp_buffer (buf, limit, 1, 0);
+ if (errors != errors_before_expansion) {
+ free (trybuf.buf);
+ goto invalid_include_file_name;
+ }
src = trybuf.buf;
buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
limit = buf;
}
*limit = 0;
free (trybuf.buf);
- retried++;
+ retried = 1;
goto get_filename;
}
+
+ invalid_include_file_name:
+ error ("`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
+ return 0;
}
/* For #include_next, skip in the search path
char *s = fname;
char *p;
#if defined (__MSDOS__) || defined (_WIN32)
- if (isalpha (s[0]) && s[1] == ':') s += 2;
+ if (ISALPHA (s[0]) && s[1] == ':') s += 2;
#endif
#ifdef VMS
if ((p = rindex (s, ':'))) s = p + 1; /* Skip device. */
char *filename;
{
#if defined (__MSDOS__) || (defined (_WIN32) && !defined (__CYGWIN32__))
- if (isalpha (filename[0]) && filename[1] == ':') filename += 2;
+ if (ISALPHA (filename[0]) && filename[1] == ':') filename += 2;
#endif
#if defined (__CYGWIN32__)
/* At present, any path that begins with a drive spec is absolute. */
- if (isalpha (filename[0]) && filename[1] == ':') return 1;
+ if (ISALPHA (filename[0]) && filename[1] == ':') return 1;
#endif
if (filename[0] == '/') return 1;
#ifdef DIR_SEPARATOR
Do only the simplifications allowed by Posix.
It is OK to miss simplifications on non-Posix hosts,
- since this merely leads to suboptimial results. */
+ since this merely leads to suboptimal results. */
static size_t
simplify_filename (filename)
U_CHAR *importing;
struct include_file **pinc;
{
- char *fname = remap_include_file (filename, searchptr);
+ char *fname = remap ? remap_include_file (filename, searchptr) : filename;
int fd = -2;
/* Look up FNAME in include_hashtab. */
return fd;
}
-/* Return the remapped name of the the include file FILENAME.
+/* Return the remapped name of the include file FILENAME.
SEARCHPTR is the directory being tried from the include file path. */
static char *
fp = &instack[indepth + 1];
bzero ((char *) fp, sizeof (FILE_BUF));
fp->nominal_fname = fp->fname = fname;
+ fp->nominal_fname_len = strlen (fname);
fp->inc = inc;
fp->length = 0;
fp->lineno = 1;
fp->dir = dirptr;
if (S_ISREG (inc->st.st_mode)) {
- fp->buf = (U_CHAR *) xmalloc (inc->st.st_size + 2);
+ size_t s = (size_t) inc->st.st_size;
+ if (s != inc->st.st_size || s + 2 < s)
+ memory_full ();
+ fp->buf = (U_CHAR *) xmalloc (s + 2);
fp->bufp = fp->buf;
- /* Read the file contents, knowing that inc->st.st_size is an upper bound
+ /* Read the file contents, knowing that s is an upper bound
on the number of bytes we can read. */
- fp->length = safe_read (f, (char *) fp->buf, inc->st.st_size);
+ fp->length = safe_read (f, (char *) fp->buf, s);
if (fp->length < 0) goto nope;
}
else if (S_ISDIR (inc->st.st_mode)) {
if (S_ISREG (st->st_mode))
{
- buf = xmalloc (st->st_size + 2);
- length = safe_read (pcf, buf, st->st_size);
+ size_t s = (size_t) st->st_size;
+ if (s != st->st_size || s + 2 < s)
+ memory_full ();
+ buf = xmalloc (s + 2);
+ length = safe_read (pcf, buf, s);
if (length < 0)
goto nope;
}
line_directive_len *= 2);
sprintf (line_directive, "\n# %d ", next_string->lineno);
strcpy (quote_string (line_directive + strlen (line_directive),
- (char *) next_string->filename),
+ (char *) next_string->filename,
+ strlen ((char *) next_string->filename)),
"\n");
safe_write (fileno (stdout), line_directive, strlen (line_directive));
safe_write (fileno (stdout),
int sym_length; /* and how long it is */
int line = instack[indepth].lineno;
char *file = instack[indepth].nominal_fname;
+ size_t file_len = instack[indepth].nominal_fname_len;
int rest_args = 0;
DEFINITION *defn;
/* do we have a "special" rest-args extension here? */
if (limit - bp > REST_EXTENSION_LENGTH
&& bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
+ if (pedantic && !instack[indepth].system_header_p)
+ pedwarn ("ANSI C does not allow macro with variable arguments");
rest_args = 1;
temp->rest_args = 1;
break;
defn->line = line;
defn->file = file;
+ defn->file_len = file_len;
/* OP is null if this is a predefinition */
defn->predefined = !op;
pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam);
if (hp->type == T_MACRO)
- pedwarn_with_file_and_line (hp->value.defn->file, hp->value.defn->line,
+ pedwarn_with_file_and_line (hp->value.defn->file,
+ hp->value.defn->file_len,
+ hp->value.defn->line,
"this is the location of the previous definition");
}
/* Replace the old definition. */
if (d1->nargs != d2->nargs)
return 1;
- if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
+ if (pedantic
+ && strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
return 1;
for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
a1 = a1->next, a2 = a2->next) {
}
} else {
/* In -traditional mode, recognize arguments inside strings and
- and character constants, and ignore special properties of #.
+ character constants, and ignore special properties of #.
Arguments inside strings are considered "stringified", but no
extra quote marks are supplied. */
switch (c) {
return hp;
}
-/* Find the most recent hash node for name name (ending with first
+/* Find the most recent hash node for name "name" (ending with first
non-identifier char) installed by install
If LEN is >= 0, it is the length of the name.
bp = tem.buf;
SKIP_WHITE_SPACE (bp);
- if (!isdigit (*bp)) {
+ if (!ISDIGIT (*bp)) {
error ("invalid format `#line' directive");
return 0;
}
pedwarn ("line number out of range in `#line' directive");
/* skip over the line number. */
- while (isdigit (*bp))
+ while (ISDIGIT (*bp))
bp++;
#if 0 /* #line 10"foo.c" is supposed to be allowed. */
break;
case '\"':
- p[-1] = 0;
+ *--p = 0;
goto fname_done;
}
fname_done:
if (hp->length == fname_length &&
bcmp (hp->value.cpval, fname, fname_length) == 0) {
ip->nominal_fname = hp->value.cpval;
+ ip->nominal_fname_len = fname_length;
break;
}
if (hp == 0) {
hp->next = *hash_bucket;
*hash_bucket = hp;
- hp->length = fname_length;
ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
- bcopy (fname, hp->value.cpval, fname_length);
+ ip->nominal_fname_len = hp->length = fname_length;
+ bcopy (fname, hp->value.cpval, fname_length + 1);
}
} else if (*bp) {
error ("invalid format `#line' directive");
bcopy ((char *) buf, (char *) copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
+
+ if (pedantic && !instack[indepth].system_header_p)
+ pedwarn ("ANSI C does not allow `#warning'");
+
/* Use `pedwarn' not `warning', because #warning isn't in the C Standard;
if -pedantic-errors is given, #warning should cause an error. */
pedwarn ("#warning %s", copy);
if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
error ("`#elif' after `#else'");
fprintf (stderr, " (matches line %d", if_stack->lineno);
- if (if_stack->fname != NULL && ip->fname != NULL
- && strcmp (if_stack->fname, ip->nominal_fname) != 0)
- fprintf (stderr, ", file %s", if_stack->fname);
+ if (! (if_stack->fname_len == ip->nominal_fname_len
+ && !bcmp (if_stack->fname, ip->nominal_fname,
+ if_stack->fname_len))) {
+ fprintf (stderr, ", file ");
+ eprint_string (if_stack->fname, if_stack->fname_len);
+ }
fprintf (stderr, ")\n");
}
if_stack->type = T_ELIF;
delete_macro (save_defined); /* clean up special symbol */
temp_obuf.buf[temp_obuf.length] = '\n';
- value = parse_c_expression ((char *) temp_obuf.buf);
+ value = parse_c_expression ((char *) temp_obuf.buf,
+ warn_undef && !instack[indepth].system_header_p);
free (temp_obuf.buf);
HASHNODE *hp;
if (! traditional) {
- if (isdigit (buf[0]))
+ if (ISDIGIT (buf[0]))
pedwarn ("`#%s' argument starts with a digit", keyword->name);
else if (end != limit)
pedwarn ("garbage at end of `#%s' argument", keyword->name);
temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
temp->fname = ip->nominal_fname;
+ temp->fname_len = ip->nominal_fname_len;
temp->lineno = ip->lineno;
temp->next = if_stack;
temp->control_macro = control_macro;
/* Save info about where the group starts. */
U_CHAR *beg_of_group = bp;
int beg_lineno = ip->lineno;
+ int skipping_include_directive = 0;
if (output_conditionals && op != 0) {
char *ptr = "#failed\n";
bp = skip_to_end_of_comment (ip, &ip->lineno, 0);
}
break;
+ case '<':
+ if (skipping_include_directive) {
+ while (bp < endb && *bp != '>' && *bp != '\n') {
+ if (*bp == '\\' && bp[1] == '\n') {
+ ip->lineno++;
+ bp++;
+ }
+ bp++;
+ }
+ }
+ break;
case '\"':
+ if (skipping_include_directive) {
+ while (bp < endb && *bp != '\n') {
+ if (*bp == '"') {
+ bp++;
+ break;
+ }
+ if (*bp == '\\' && bp[1] == '\n') {
+ ip->lineno++;
+ bp++;
+ }
+ bp++;
+ }
+ break;
+ }
+ /* Fall through. */
case '\'':
bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno,
NULL_PTR, NULL_PTR);
break;
case '\\':
- /* Char after backslash loses its special meaning. */
- if (bp < endb) {
- if (*bp == '\n')
- ++ip->lineno; /* But do update the line-count. */
+ /* Char after backslash loses its special meaning in some cases. */
+ if (*bp == '\n') {
+ ++ip->lineno;
+ bp++;
+ } else if (traditional && bp < endb)
bp++;
- }
break;
case '\n':
++ip->lineno;
beg_of_line = bp;
+ skipping_include_directive = 0;
break;
case '%':
if (beg_of_line == 0 || traditional)
else if (*bp == '\\' && bp[1] == '\n')
bp += 2;
else if (*bp == '/') {
+ if (bp[1] == '\\' && bp[2] == '\n')
+ newline_fix (bp + 1);
if (bp[1] == '*') {
for (bp += 2; ; bp++) {
if (*bp == '\n')
else if (*bp == '*') {
if (bp[-1] == '/' && warn_comments)
warning ("`/*' within comment");
+ if (bp[1] == '\\' && bp[2] == '\n')
+ newline_fix (bp + 1);
if (bp[1] == '/')
break;
}
if_stack = temp;
temp->lineno = ip->lineno;
temp->fname = ip->nominal_fname;
+ temp->fname_len = ip->nominal_fname_len;
temp->type = kt->type;
break;
case T_ELSE:
free (temp);
break;
- default:
+ case T_INCLUDE:
+ case T_INCLUDE_NEXT:
+ case T_IMPORT:
+ skipping_include_directive = 1;
+ break;
+
+ default:
break;
}
break;
if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
error ("`#else' after `#else'");
fprintf (stderr, " (matches line %d", if_stack->lineno);
- if (strcmp (if_stack->fname, ip->nominal_fname) != 0)
- fprintf (stderr, ", file %s", if_stack->fname);
+ if (! (if_stack->fname_len == ip->nominal_fname_len
+ && !bcmp (if_stack->fname, ip->nominal_fname,
+ if_stack->fname_len))) {
+ fprintf (stderr, ", file ");
+ eprint_string (if_stack->fname, if_stack->fname_len);
+ }
fprintf (stderr, ")\n");
}
if_stack->type = T_ELSE;
++*count_newlines;
bp += 2;
}
- if (*bp == '\n' && count_newlines) {
+ if (*bp == '\n') {
if (backslash_newlines_p)
*backslash_newlines_p = 1;
- ++*count_newlines;
+ if (count_newlines)
+ ++*count_newlines;
}
bp++;
} else if (c == '\n') {
}
/* Place into DST a quoted string representing the string SRC.
+ SRCLEN is the length of SRC; SRC may contain null bytes.
Return the address of DST's terminating null. */
static char *
-quote_string (dst, src)
+quote_string (dst, src, srclen)
char *dst, *src;
+ size_t srclen;
{
U_CHAR c;
+ char *srclim = src + srclen;
*dst++ = '\"';
- for (;;)
+ while (src != srclim)
switch ((c = *src++))
{
default:
- if (isprint (c))
+ if (ISPRINT (c))
*dst++ = c;
else
{
*dst++ = '\\';
*dst++ = c;
break;
-
- case '\0':
- *dst++ = '\"';
- *dst = '\0';
- return dst;
}
+
+ *dst++ = '\"';
+ *dst = '\0';
+ return dst;
}
/* Skip across a group of balanced parens, starting from IP->bufp.
ip->bufp++;
}
- line_directive_buf = (char *) alloca (4 * strlen (ip->nominal_fname) + 100);
+ line_directive_buf = (char *) alloca (4 * ip->nominal_fname_len + 100);
sprintf (line_directive_buf, "# %d ", ip->lineno);
line_end = quote_string (line_directive_buf + strlen (line_directive_buf),
- ip->nominal_fname);
+ ip->nominal_fname, ip->nominal_fname_len);
if (file_change != same_file) {
*line_end++ = ' ';
*line_end++ = file_change == enter_file ? '1' : '2';
for (; i < arglen; i++) {
c = arg->raw[i];
- /* Special markers Newline Space
- generate nothing for a stringified argument. */
- if (c == '\n' && arg->raw[i+1] != '\n') {
- i++;
- continue;
- }
+ if (! in_string) {
+ /* Special markers Newline Space
+ generate nothing for a stringified argument. */
+ if (c == '\n' && arg->raw[i+1] != '\n') {
+ i++;
+ continue;
+ }
- /* Internal sequences of whitespace are replaced by one space
- except within an string or char token. */
- if (! in_string
- && (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c])) {
- while (1) {
- /* Note that Newline Space does occur within whitespace
- sequences; consider it part of the sequence. */
- if (c == '\n' && is_space[arg->raw[i+1]])
- i += 2;
- else if (c != '\n' && is_space[c])
- i++;
- else break;
- c = arg->raw[i];
+ /* Internal sequences of whitespace are replaced by one space
+ except within an string or char token. */
+ if (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c]) {
+ while (1) {
+ /* Note that Newline Space does occur within whitespace
+ sequences; consider it part of the sequence. */
+ if (c == '\n' && is_space[arg->raw[i+1]])
+ i += 2;
+ else if (c != '\n' && is_space[c])
+ i++;
+ else break;
+ c = arg->raw[i];
+ }
+ i--;
+ c = ' ';
}
- i--;
- c = ' ';
}
if (escaped)
/* Escape these chars */
if (c == '\"' || (in_string && c == '\\'))
xbuf[totlen++] = '\\';
- if (isprint (c))
- xbuf[totlen++] = c;
- else {
- sprintf ((char *) &xbuf[totlen], "\\%03o", (unsigned int) c);
- totlen += 4;
- }
+ /* We used to output e.g. \008 for control characters here,
+ but this doesn't conform to the C Standard.
+ Just output the characters as-is. */
+ xbuf[totlen++] = c;
}
if (!traditional)
xbuf[totlen++] = '\"'; /* insert ending quote */
ip2->fname = 0;
ip2->nominal_fname = 0;
+ ip2->nominal_fname_len = 0;
ip2->inc = 0;
/* This may not be exactly correct, but will give much better error
messages for nested macro calls than using a line number of zero. */
/* Try to parse as much of the argument as exists at this
input stack level. */
- U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length,
+ U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro,
&paren, &newlines, &comments, rest_args);
/* If we find the end of the argument at this level,
ip = &instack[--indepth];
newlines = 0;
comments = 0;
- bp = macarg1 (ip->bufp, ip->buf + ip->length, &paren,
+ bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro, &paren,
&newlines, &comments, rest_args);
final_start = bufsize;
bufsize += bp - ip->bufp;
#endif
if (c == '\"' || c == '\\') /* escape these chars */
totlen++;
- else if (!isprint (c))
- totlen += 3;
}
argptr->stringified_length = totlen;
}
}
\f
/* Scan text from START (inclusive) up to LIMIT (exclusive),
+ taken from the expansion of MACRO,
counting parens in *DEPTHPTR,
and return if reach LIMIT
or before a `)' that would make *DEPTHPTR negative
Set *COMMENTS to 1 if a comment is seen. */
static U_CHAR *
-macarg1 (start, limit, depthptr, newlines, comments, rest_args)
+macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
U_CHAR *start;
register U_CHAR *limit;
+ struct hashnode *macro;
int *depthptr, *newlines, *comments;
int rest_args;
{
break;
case '\\':
/* Traditionally, backslash makes following char not special. */
- if (bp + 1 < limit && traditional)
- {
- bp++;
- /* But count source lines anyway. */
- if (*bp == '\n')
- ++*newlines;
- }
+ if (traditional && bp + 1 < limit && bp[1] != '\n')
+ bp++;
break;
case '\n':
++*newlines;
break;
case '/':
+ if (macro)
+ break;
if (bp[1] == '\\' && bp[2] == '\n')
newline_fix (bp + 1);
if (bp[1] == '*') {
bp++;
if (*bp == '\n')
++*newlines;
- while (*bp == '\\' && bp[1] == '\n') {
- bp += 2;
+ if (!macro) {
+ while (*bp == '\\' && bp[1] == '\n') {
+ bp += 2;
+ ++*newlines;
+ }
}
} else if (*bp == '\n') {
++*newlines;
obp--;
else
obp[-1] = ' ';
- ibp++;
- while (ibp + 1 < limit) {
- if (ibp[0] == '*'
- && ibp[1] == '\\' && ibp[2] == '\n')
- newline_fix (ibp + 1);
- if (ibp[0] == '*' && ibp[1] == '/')
- break;
- ibp++;
+ while (++ibp < limit) {
+ if (ibp[0] == '*') {
+ if (ibp[1] == '\\' && ibp[2] == '\n')
+ newline_fix (ibp + 1);
+ if (ibp[1] == '/') {
+ ibp += 2;
+ break;
+ }
+ }
}
- ibp += 2;
break;
case '\'':
break;
if (c == '\n' && quotec == '\'')
break;
- if (c == '\\' && ibp < limit) {
- while (*ibp == '\\' && ibp[1] == '\n')
- ibp += 2;
- *obp++ = *ibp++;
+ if (c == '\\') {
+ if (ibp < limit && *ibp == '\n') {
+ ibp++;
+ obp--;
+ } else {
+ while (*ibp == '\\' && ibp[1] == '\n')
+ ibp += 2;
+ if (ibp < limit)
+ *obp++ = *ibp++;
+ }
}
}
}
int quotec = c;
while (ibp < limit) {
*obp++ = c = *ibp++;
- if (c == quotec)
+ if (c == quotec && ibp[-2] != '\\')
break;
if (c == '\n' && quotec == '\'')
break;
break;
}
- if (ip != NULL)
- fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
+ if (ip != NULL) {
+ eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+ fprintf (stderr, ":%d: ", ip->lineno);
+ }
vfprintf (stderr, msg, args);
fprintf (stderr, "\n");
errors++;
error_from_errno (name)
char *name;
{
+ int e = errno;
int i;
FILE_BUF *ip = NULL;
break;
}
- if (ip != NULL)
- fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
+ if (ip != NULL) {
+ eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+ fprintf (stderr, ":%d: ", ip->lineno);
+ }
- fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
+ fprintf (stderr, "%s: %s\n", name, my_strerror (e));
errors++;
}
break;
}
- if (ip != NULL)
- fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
+ if (ip != NULL) {
+ eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+ fprintf (stderr, ":%d: ", ip->lineno);
+ }
fprintf (stderr, "warning: ");
vfprintf (stderr, msg, args);
fprintf (stderr, "\n");
break;
}
- if (ip != NULL)
- fprintf (stderr, "%s:%d: ", ip->nominal_fname, line);
+ if (ip != NULL) {
+ eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+ fprintf (stderr, ":%d: ", line);
+ }
vfprintf (stderr, msg, args);
fprintf (stderr, "\n");
errors++;
break;
}
- if (ip != NULL)
- fprintf (stderr, line ? "%s:%d: " : "%s: ", ip->nominal_fname, line);
+ if (ip != NULL) {
+ eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+ fprintf (stderr, line ? ":%d: " : ": ", line);
+ }
fprintf (stderr, "warning: ");
vfprintf (stderr, msg, args);
fprintf (stderr, "\n");
static void
#if defined (__STDC__) && defined (HAVE_VPRINTF)
-pedwarn_with_file_and_line (char *file, int line, PRINTF_ALIST (msg))
+pedwarn_with_file_and_line (char *file, size_t file_len, int line,
+ PRINTF_ALIST (msg))
#else
-pedwarn_with_file_and_line (file, line, PRINTF_ALIST (msg))
+pedwarn_with_file_and_line (file, file_len, line, PRINTF_ALIST (msg))
char *file;
+ size_t file_len;
int line;
PRINTF_DCL (msg)
#endif
if (!pedantic_errors && inhibit_warnings)
return;
- if (file != NULL)
- fprintf (stderr, "%s:%d: ", file, line);
+ if (file) {
+ eprint_string (file, file_len);
+ fprintf (stderr, ":%d: ", line);
+ }
if (pedantic_errors)
errors++;
if (!pedantic_errors)
fprintf (stderr, ",\n ");
}
- fprintf (stderr, " from %s:%d", ip->nominal_fname, ip->lineno);
+ fprintf (stderr, " from ");
+ eprint_string (ip->nominal_fname, ip->nominal_fname_len);
+ fprintf (stderr, ":%d", ip->lineno);
}
if (! first)
fprintf (stderr, ":\n");
}
/*
- * find the most recent hash node for name name (ending with first
+ * find the most recent hash node for name "name" (ending with first
* non-identifier char) installed by install
*
* If LEN is >= 0, it is the length of the name.
if (unterminated)
return;
while (p != p1)
- if (*p == '\\' && p[1] == '\n')
- p += 2;
- else
- *q++ = *p++;
+ *q++ = *p++;
} else if (*p == '\\' && p[1] == '\n')
p += 2;
/* Change newline chars into newline-markers. */
ip = &instack[++indepth];
ip->nominal_fname = ip->fname = "*Initialization*";
+ ip->nominal_fname_len = strlen (ip->nominal_fname);
ip->buf = ip->bufp = buf;
ip->length = strlen ((char *) buf);
ip = &instack[++indepth];
ip->nominal_fname = ip->fname = "*undef*";
+ ip->nominal_fname_len = strlen (ip->nominal_fname);
ip->buf = ip->bufp = (U_CHAR *) str;
ip->length = strlen (str);
ip = &instack[++indepth];
ip->nominal_fname = ip->fname = "*Initialization*";
+ ip->nominal_fname_len = strlen (ip->nominal_fname);
ip->buf = ip->bufp = buf;
ip->length = strlen ((char *) buf);
len = simplify_filename (dir->fname);
/* Convert directory name to a prefix. */
- if (dir->fname[len - 1] != DIR_SEPARATOR) {
+ if (len && dir->fname[len - 1] != DIR_SEPARATOR) {
if (len == 1 && dir->fname[len - 1] == '.')
len = 0;
else
last_include = last;
}
\f
+/* Place into DST a representation of the file named SRC that is suitable
+ for `make'. Do not null-terminate DST. Return its length. */
+static int
+quote_string_for_make (dst, src)
+ char *dst;
+ char *src;
+{
+ char *p = src;
+ int i = 0;
+ for (;;)
+ {
+ char c = *p++;
+ switch (c)
+ {
+ case '\0':
+ case ' ':
+ case '\t':
+ {
+ /* GNU make uses a weird quoting scheme for white space.
+ A space or tab preceded by 2N+1 backslashes represents
+ N backslashes followed by space; a space or tab
+ preceded by 2N backslashes represents N backslashes at
+ the end of a file name; and backslashes in other
+ contexts should not be doubled. */
+ char *q;
+ for (q = p - 1; src < q && q[-1] == '\\'; q--)
+ {
+ if (dst)
+ dst[i] = '\\';
+ i++;
+ }
+ }
+ if (!c)
+ return i;
+ if (dst)
+ dst[i] = '\\';
+ i++;
+ goto ordinary_char;
+
+ case '$':
+ if (dst)
+ dst[i] = c;
+ i++;
+ /* Fall through. This can mishandle things like "$(" but
+ there's no easy fix. */
+ default:
+ ordinary_char:
+ /* This can mishandle characters in the string "\0\n%*?[\\~";
+ exactly which chars are mishandled depends on the `make' version.
+ We know of no portable solution for this;
+ even GNU make 3.76.1 doesn't solve the problem entirely.
+ (Also, '\0' is mishandled due to our calling conventions.) */
+ if (dst)
+ dst[i] = c;
+ i++;
+ break;
+ }
+ }
+}
+
+
/* Add output to `deps_buffer' for the -M switch.
STRING points to the text to be output.
SPACER is ':' for targets, ' ' for dependencies. */
char *string;
int spacer;
{
- int size = strlen (string);
+ int size = quote_string_for_make ((char *) 0, string);
if (size == 0)
return;
spacer = 0;
}
- if (deps_size + size + 8 > deps_allocated_size) {
- deps_allocated_size = (deps_size + size + 50) * 2;
+ if (deps_size + 2 * size + 8 > deps_allocated_size) {
+ deps_allocated_size = (deps_size + 2 * size + 50) * 2;
deps_buffer = xrealloc (deps_buffer, deps_allocated_size);
}
if (spacer == ' ') {
deps_buffer[deps_size++] = ' ';
deps_column++;
}
- bcopy (string, &deps_buffer[deps_size], size);
+ quote_string_for_make (&deps_buffer[deps_size], string);
deps_size += size;
deps_column += size;
if (spacer == ':') {
perror_with_name (name)
char *name;
{
- fprintf (stderr, "%s: ", progname);
- fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
+ fprintf (stderr, "%s: %s: %s\n", progname, name, my_strerror (errno));
errors++;
}
char *type;
FILE *oldfile;
{
+#undef freopen /* Get back the real freopen routine. */
if (strcmp (type, "w") == 0)
- return decc$freopen (fname, type, oldfile,
+ return freopen (fname, type, oldfile,
"mbc=16", "deq=64", "fop=tef", "shr=nil");
- return decc$freopen (fname, type, oldfile, "mbc=16");
+ return freopen (fname, type, oldfile, "mbc=16");
}
static FILE *
char *fname;
char *type;
{
+#undef fopen /* Get back the real fopen routine. */
/* The gcc-vms-1.42 distribution's header files prototype fopen with two
fixed arguments, which matches ANSI's specification but not VAXCRTL's
pre-ANSI implementation. This hack circumvents the mismatch problem. */
- FILE *(*vmslib_fopen)() = (FILE *(*)()) decc$fopen;
+ FILE *(*vmslib_fopen)() = (FILE *(*)()) fopen;
if (*type == 'w')
return (*vmslib_fopen) (fname, type, "mbc=32",
int flags;
int prot;
{
- return decc$open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef");
+#undef open /* Get back the real open routine. */
+ return open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef");
}
\f
/* more VMS hackery */
#include <fab.h>
#include <nam.h>
-extern unsigned long sys$parse(), sys$search();
+extern unsigned long SYS$PARSE(), SYS$SEARCH();
/* Work around another library bug. If a file is located via a searchlist,
and if the device it's on is not the same device as the one specified
bad enough, but then compounding the problem by reporting the reason for
failure as "normal successful completion." */
+#undef fstat /* Get back to the library version. */
static int
VMS_fstat (fd, statbuf)
int fd;
struct stat *statbuf;
{
- int result = decc$fstat (fd, statbuf);
+ int result = fstat (fd, statbuf);
if (result < 0)
{
{
struct FAB fab;
struct NAM nam;
- char exp_nam[NAM$C_MAXRSS+1], /* expanded name buffer for sys$parse */
- res_nam[NAM$C_MAXRSS+1]; /* resultant name buffer for sys$search */
+ char exp_nam[NAM$C_MAXRSS+1], /* expanded name buffer for SYS$PARSE */
+ res_nam[NAM$C_MAXRSS+1]; /* resultant name buffer for SYS$SEARCH */
fab = cc$rms_fab;
fab.fab$l_fna = (char *) name;
nam.nam$l_esa = exp_nam, nam.nam$b_ess = sizeof exp_nam - 1;
nam.nam$l_rsa = res_nam, nam.nam$b_rss = sizeof res_nam - 1;
nam.nam$b_nop = NAM$M_PWD | NAM$M_NOCONCEAL;
- if (sys$parse (&fab) & 1)
+ if (SYS$PARSE (&fab) & 1)
{
- if (sys$search (&fab) & 1)
+ if (SYS$SEARCH (&fab) & 1)
{
res_nam[nam.nam$b_rsl] = '\0';
result = stat (res_nam, statbuf);
/* Clean up searchlist context cached by the system. */
nam.nam$b_nop = NAM$M_SYNCHK;
fab.fab$l_fna = 0, fab.fab$b_fns = 0;
- (void) sys$parse (&fab);
+ (void) SYS$PARSE (&fab);
}
}