/* CPP Library.
- Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
- Written by Per Bothner, 1994-95.
- Based on CCCP program by by Paul Rubin, June 1986
+ Copyright (C) 1986, 87, 89, 92-6, 1997 Free Software Foundation, Inc.
+ Contributed by Per Bothner, 1994-95.
+ Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
This program is free software; you can redistribute it and/or modify it
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, 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! */
-
-#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
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
#include "config.h"
-#endif /* not EMACS */
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
+#ifndef STDC_VALUE
+#define STDC_VALUE 1
#endif
-#ifndef LOCAL_INCLUDE_DIR
-#define LOCAL_INCLUDE_DIR "/usr/local/include"
+#include <ctype.h>
+#include <stdio.h>
+#include <signal.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
#endif
-#if 0 /* We can't get ptrdiff_t, so I arranged not to need PTR_INT_TYPE. */
-#ifdef __STDC__
-#define PTR_INT_TYPE ptrdiff_t
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
#else
-#define PTR_INT_TYPE long
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+#endif
#endif
-#endif /* 0 */
-#include "cpplib.h"
-#include "cpphash.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
-#ifndef STDC_VALUE
-#define STDC_VALUE 1
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
#endif
-/* By default, colon separates directories in a path. */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
#endif
-/* In case config.h defines these. */
-#undef bcopy
-#undef bzero
-#undef bcmp
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <signal.h>
-#ifdef __STDC__
-#include <string.h>
-#include <stdlib.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
#endif
-#ifndef VMS
-#ifndef USG
-#include <sys/time.h> /* for __DATE__ and __TIME__ */
-#include <sys/resource.h>
-#else
-#include <sys/param.h> /* CYGNUS LOCAL: shebs -noquiet */
-#include <sys/times.h>
-#include <time.h>
-#include <fcntl.h>
-#endif /* USG */
-#endif /* not VMS */
+#ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#endif
-/* This defines "errno" properly for VMS, and gives us EACCES. */
+/* This defines "errno" properly for VMS, and gives us EACCES. */
#include <errno.h>
+#include "cpplib.h"
+#include "cpphash.h"
+#include "gansidecl.h"
+
+#ifdef NEED_DECLARATION_INDEX
extern char *index ();
+#endif
+
+#ifdef NEED_DECLARATION_RINDEX
extern char *rindex ();
+#endif
+
+#ifdef NEED_DECLARATION_GETENV
+extern char *getenv ();
+#endif
+
+extern char *update_path ();
#ifndef O_RDONLY
#define O_RDONLY 0
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
-/* Find the largest host integer type and set its size and type. */
-
-#ifndef HOST_BITS_PER_WIDE_INT
-
-#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
-#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
-#define HOST_WIDE_INT long
-#else
-#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
-#define HOST_WIDE_INT int
-#endif
-
+/* Find the largest host integer type and set its size and type.
+ Watch out: on some crazy hosts `long' is shorter than `int'. */
+
+#ifndef HOST_WIDE_INT
+# if HAVE_INTTYPES_H
+# 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)
+# define HOST_WIDE_INT int
+# else
+# 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
+# endif
+# endif
+# endif
#endif
#ifndef S_ISREG
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#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
+/* By default, colon separates directories in a path. */
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
#endif
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
+#ifndef STANDARD_INCLUDE_DIR
+#define STANDARD_INCLUDE_DIR "/usr/include"
#endif
-
#ifndef INCLUDE_LEN_FUDGE
#define INCLUDE_LEN_FUDGE 0
#endif
struct assertion_hashnode *prev;
/* also, a back pointer to this node's hash
chain is kept, in case the node is the head
- of the chain and gets deleted. */
+ of the chain and gets deleted. */
struct assertion_hashnode **bucket_hdr;
int length; /* length of token, for quick comparison */
U_CHAR *name; /* the actual name */
#define NEWLINE_FIX \
do {while (PEEKC() == '\\' && PEEKN(1) == '\n') FORWARD(2); } while(0)
-/* Same, but assume we've already read the potential '\\' into C. */
+/* Same, but assume we've already read the potential '\\' into C. */
#define NEWLINE_FIX1(C) do { \
while ((C) == '\\' && PEEKC() == '\n') { FORWARD(1); (C) = GETC(); }\
} while(0)
-/* Name under which this program was invoked. */
-
-char *progname;
-
struct cpp_pending {
struct cpp_pending *next;
char *cmd;
/* Forward declarations. */
-extern char *xmalloc ();
+char *xmalloc ();
+void cpp_fatal ();
+void cpp_file_line_for_message PARAMS ((cpp_reader *, char *, int, int));
+void cpp_hash_cleanup PARAMS ((cpp_reader *));
+void cpp_message ();
+void cpp_print_containing_files PARAMS ((cpp_reader *));
static void add_import ();
static void append_include_chain ();
-static void make_undef ();
-static void make_definition ();
static void make_assertion ();
static void path_include ();
static void initialize_builtins ();
static void initialize_char_syntax ();
-static void dump_arg_n ();
-static void dump_defn_1 ();
extern void delete_macro ();
+#if 0
static void trigraph_pcp ();
+#endif
static int finclude ();
static void validate_else ();
static int comp_def_part ();
+#ifdef abort
extern void fancy_abort ();
-static void pipe_closed ();
-static void print_containing_files ();
+#endif
static int lookup_import ();
static int redundant_include_p ();
static is_system_include ();
static struct file_name_map *read_name_map ();
static char *read_filename_string ();
static int open_include_file ();
-static int check_preconditions ();
-static void pcfinclude ();
-static void pcstring_used ();
static int check_macro_name ();
static int compare_defs ();
static int compare_token_lists ();
static HOST_WIDE_INT eval_if_expression ();
static int change_newlines ();
-static int line_for_error ();
extern int hashf ();
-static int file_size_and_mode ();
static struct arglist *read_token_list ();
static void free_token_list ();
static int safe_read ();
static void push_macro_expansion PARAMS ((cpp_reader *,
- U_CHAR*, int, HASHNODE*));
+ U_CHAR *, int, HASHNODE *));
+static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
extern char *xrealloc ();
-extern char *xcalloc ();
+static char *xcalloc ();
static char *savestring ();
static void conditional_skip ();
/* External declarations. */
-extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader*));
+extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader *));
-extern char *getenv ();
extern FILE *fdopen ();
extern char *version_string;
extern struct tm *localtime ();
};
/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
- via the same directory as the file that #included it. */
-#define SELF_DIR_DUMMY ((struct file_name_list*)(~0))
+ via the same directory as the file that #included it. */
+#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
-/* #include "file" looks in source file dir, then stack. */
-/* #include <file> just looks in the stack. */
-/* -I directories are added to the end, then the defaults are added. */
+/* #include "file" looks in source file dir, then stack. */
+/* #include <file> just looks in the stack. */
+/* -I directories are added to the end, then the defaults are added. */
/* The */
static struct default_include {
char *fname; /* The name of the directory. */
+ char *component; /* The component containing the directory */
int cplusplus; /* Only look here if we're compiling C++. */
int cxx_aware; /* Includes in this directory don't need to
be wrapped in extern "C" when compiling
#else
= {
/* Pick up GNU C++ specific include files. */
- { GPLUSPLUS_INCLUDE_DIR, 1, 1 },
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
+ { OLD_GPLUSPLUS_INCLUDE_DIR, 0, 1, 1 },
#ifdef CROSS_COMPILE
/* This is the dir for fixincludes. Put it just before
the files that we fix. */
- { GCC_INCLUDE_DIR, 0, 0 },
+ { GCC_INCLUDE_DIR, "GCC", 0, 0 },
/* For cross-compilation, this dir name is generated
automatically in Makefile.in. */
- { CROSS_INCLUDE_DIR, 0, 0 },
+ { CROSS_INCLUDE_DIR, "GCC",0, 0 },
+#ifdef TOOL_INCLUDE_DIR
/* This is another place that the target system's headers might be. */
- { TOOL_INCLUDE_DIR, 0, 1 },
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
#else /* not CROSS_COMPILE */
+#ifdef LOCAL_INCLUDE_DIR
/* This should be /usr/local/include and should come before
the fixincludes-fixed header files. */
- { LOCAL_INCLUDE_DIR, 0, 1 },
+ { LOCAL_INCLUDE_DIR, 0, 0, 1 },
+#endif
+#ifdef TOOL_INCLUDE_DIR
/* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */
- { TOOL_INCLUDE_DIR, 0, 1 },
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
/* This is the dir for fixincludes. Put it just before
the files that we fix. */
- { GCC_INCLUDE_DIR, 0, 0 },
+ { GCC_INCLUDE_DIR, "GCC", 0, 0 },
/* Some systems have an extra dir of include files. */
#ifdef SYSTEM_INCLUDE_DIR
- { SYSTEM_INCLUDE_DIR, 0, 0 },
+ { SYSTEM_INCLUDE_DIR, 0, 0, 0 },
#endif
- { STANDARD_INCLUDE_DIR, 0, 0 },
+#ifndef STANDARD_INCLUDE_COMPONENT
+#define STANDARD_INCLUDE_COMPONENT 0
+#endif
+ { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
#endif /* not CROSS_COMPILE */
- { 0, 0, 0 }
+ { 0, 0, 0, 0 }
};
#endif /* no INCLUDE_DEFAULTS */
int length; /* Length of name */
int (*func)(); /* Function to handle directive */
char *name; /* Name of directive */
- enum node_type type; /* Code which describes which directive. */
- char command_reads_line; /* One if rest of line is read by func. */
- char traditional_comments; /* Nonzero: keep comments if -traditional. */
- char pass_thru; /* Copy preprocessed directive to output file.*/
+ enum node_type type; /* Code which describes which directive. */
+ char command_reads_line; /* One if rest of line is read by func. */
};
+#define IS_INCLUDE_DIRECTIVE_TYPE(t) (T_INCLUDE <= (t) && (t) <= T_IMPORT)
+
/* Here is the actual list of #-directives, most-often-used first.
The initialize_builtins function assumes #define is the very first. */
static struct directive directive_table[] = {
- { 6, do_define, "define", T_DEFINE, 0, 1},
+ { 6, do_define, "define", T_DEFINE},
{ 5, do_xifdef, "ifdef", T_IFDEF, 1},
{ 6, do_xifdef, "ifndef", T_IFNDEF, 1},
{ 7, do_include, "include", T_INCLUDE, 1},
{ 5, do_undef, "undef", T_UNDEF},
{ 5, do_error, "error", T_ERROR},
{ 7, do_warning, "warning", T_WARNING},
- { 6, do_pragma, "pragma", T_PRAGMA, 0, 0, 1},
+ { 6, do_pragma, "pragma", T_PRAGMA},
{ 4, do_line, "line", T_LINE, 1},
- { 5, do_ident, "ident", T_IDENT, 1, 0, 1},
+ { 5, do_ident, "ident", T_IDENT, 1},
#ifdef SCCS_DIRECTIVE
{ 4, do_sccs, "sccs", T_SCCS},
#endif
{ -1, 0, "", T_UNUSED},
};
\f
-/* table to tell if char can be part of a C identifier. */
+/* table to tell if char can be part of a C identifier. */
U_CHAR is_idchar[256];
-/* table to tell if char can be first char of a c identifier. */
+/* table to tell if char can be first char of a c identifier. */
U_CHAR is_idstart[256];
/* table to tell if c is horizontal space. */
U_CHAR is_hor_space[256];
is_space['\r'] = 1;
}
-/*
- * Skip over a quoted string. BP points to the opening quote.
- * Returns a pointer after the closing quote. Don't go past LIMIT.
- * START_LINE is the line number of the starting point (but it need
- * not be valid if the starting point is inside a macro expansion).
- *
- * The input stack state is not changed.
- */
-static U_CHAR *
-skip_quoted_string (pfile, first, start_line)
- cpp_reader *pfile;
- int first;
- int start_line;
-{
- int c;
-
- while (1)
- {
- c = GETC ();
- if (c == EOF)
- {
- cpp_error_with_line (pfile, line_for_error (start_line),
- "unterminated string or character constant");
-#if 0
- cpp_error_with_line (pfile, multiline_string_line,
- "possible real start of unterminated constant");
- multiline_string_line = 0;
-#endif
- break;
- }
- if (c == '\\')
- {
- c = GETC ();
- NEWLINE_FIX1(c);
- }
- else if (c == '\n')
- {
- if (CPP_TRADITIONAL (pfile))
- {
- /* Unterminated strings and character constants are 'legal'. */
- FORWARD(-1); /* Don't consume the newline. */
- break;
- }
- if (CPP_PEDANTIC (pfile) || first == '\'')
- {
- cpp_error_with_line (pfile, line_for_error (start_line),
- "unterminated string or character constant");
- FORWARD(-1);
- break;
- }
- /* If not traditional, then allow newlines inside strings. */
-#if 0
- if (multiline_string_line == 0)
- multiline_string_line = start_line;
-#endif
- }
- else if (c == first)
- break;
- }
-}
/* Place into PFILE a quoted string representing the string SRC.
- Caller must reserve enough space in pfile->token_buffer. */
+ Caller must reserve enough space in pfile->token_buffer. */
+
static void
quote_string (pfile, src)
cpp_reader *pfile;
CPP_PUTC_Q (pfile, c);
else
{
- sprintf (CPP_PWRITTEN (pfile), "\\%03o", c);
+ sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c);
CPP_ADJUST_WRITTEN (pfile, 4);
}
break;
}
}
-/* Make sure PFILE->token_buffer will hold at least N more chars. */
+/* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */
void
cpp_grow_buffer (pfile, n)
{
long old_written = CPP_WRITTEN (pfile);
pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;
- pfile->token_buffer = (char*)
+ pfile->token_buffer = (U_CHAR *)
xrealloc(pfile->token_buffer, pfile->token_buffer_size);
CPP_SET_WRITTEN (pfile, old_written);
}
* be identifier=definition.
*/
-static void
-make_definition (pfile, str)
+void
+cpp_define (pfile, str)
cpp_reader *pfile;
U_CHAR *str;
{
char *option;
U_CHAR *str;
{
- cpp_buffer *ip;
struct directive *kt;
U_CHAR *buf, *p, *q;
return;
}
- ip = cpp_push_buffer (pfile, buf, strlen (buf));
- do_assert (pfile, NULL, NULL, NULL);
- cpp_pop_buffer (pfile);
+ if (cpp_push_buffer (pfile, buf, strlen (buf)) != NULL)
+ {
+ do_assert (pfile, NULL, NULL, NULL);
+ cpp_pop_buffer (pfile);
+ }
}
\f
/* Append a chain of `struct file_name_list's
}
\f
void
-init_parse_options (opts)
- struct cpp_options *opts;
+cpp_options_init (opts)
+ cpp_options *opts;
{
- bzero (opts, sizeof *opts);
+ bzero ((char *) opts, sizeof *opts);
opts->in_fname = NULL;
opts->out_fname = NULL;
/* Initialize is_idchar to allow $. */
opts->dollars_in_ident = 1;
initialize_char_syntax (opts);
- opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 0;
opts->no_line_commands = 0;
opts->no_trigraphs = 1;
opts->print_include_names = 0;
opts->dump_macros = dump_none;
opts->no_output = 0;
+ opts->remap = 0;
opts->cplusplus = 0;
opts->cplusplus_comments = 0;
cpp_buffer *pbuf;
cpp_reader *pfile;
{
- HASHNODE *macro = (HASHNODE*)pbuf->data;
+ HASHNODE *macro = (HASHNODE *) pbuf->data;
if (macro->type == T_DISABLED)
macro->type = T_MACRO;
if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
cpp_buffer *pbuf;
cpp_reader *pfile;
{
+ if (pbuf->buf)
+ {
+ free (pbuf->buf);
+ pbuf->buf = 0;
+ }
return 0;
}
-static void
-newline_fix (pfile)
- cpp_reader *pfile;
-{
-#if 1
- NEWLINE_FIX;
-#else
- register U_CHAR *p = bp;
-
- /* First count the backslash-newline pairs here. */
-
- while (p[0] == '\\' && p[1] == '\n')
- p += 2;
-
- /* What follows the backslash-newlines is not embarrassing. */
-
- if (*p != '/' && *p != '*')
- return;
-
- /* Copy all potentially embarrassing characters
- that follow the backslash-newline pairs
- down to where the pairs originally started. */
-
- while (*p == '*' || *p == '/')
- *bp++ = *p++;
-
- /* Now write the same number of pairs after the embarrassing chars. */
- while (bp < p) {
- *bp++ = '\\';
- *bp++ = '\n';
- }
-#endif
-}
-
/* Assuming we have read '/'.
If this is the start of a comment (followed by '*' or '/'),
skip to the end of the comment, and return ' '.
Return EOF if we reached the end of file before the end of the comment.
- If not the start of a comment, return '/'. */
+ If not the start of a comment, return '/'. */
static int
skip_comment (pfile, linep)
cpp_reader *pfile;
long *linep;
{
- int c;
+ int c = 0;
while (PEEKC() == '\\' && PEEKN(1) == '\n')
{
if (linep)
{
c = GETC ();
if (c == EOF)
- return ' '; /* Allow // to be terminated by EOF. */
+ return ' '; /* Allow // to be terminated by EOF. */
while (c == '\\' && PEEKC() == '\n')
{
FORWARD(1);
}
if (c == '\n')
{
- /* Don't consider final '\n' to be part of comment. */
+ /* Don't consider final '\n' to be part of comment. */
FORWARD(-1);
return ' ';
}
}
/* Skip whitespace \-newline and comments. Does not macro-expand. */
+
void
cpp_skip_hspace (pfile)
cpp_reader *pfile;
else if (c == '\\' && PEEKN(1) == '\n') {
FORWARD(2);
}
+ else if (c == '@' && CPP_BUFFER (pfile)->has_escapes
+ && is_hor_space[PEEKN(1)])
+ FORWARD(2);
else return;
}
}
/* Read the rest of the current line.
- The line is appended to PFILE's output buffer. */
+ The line is appended to PFILE's output buffer. */
-void
+static void
copy_rest_of_line (pfile)
cpp_reader *pfile;
{
break;
case '/':
nextc = PEEKC();
- if (nextc == '*' || (opts->cplusplus_comments && nextc == '*'))
+ if (nextc == '*' || (opts->cplusplus_comments && nextc == '/'))
goto scan_directive_token;
break;
case '\f':
goto done_a_directive;
}
- /* Now find the directive name. */
+ /* Now find the directive name. */
CPP_PUTC (pfile, '#');
parse_name (pfile, GETC());
ident = pfile->token_buffer + old_written + 1;
break;
}
- if (! kt->command_reads_line)
+ if (kt->command_reads_line)
+ after_ident = 0;
+ else
{
/* Nonzero means do not delete comments within the directive.
#define needs this when -traditional. */
- int comments = CPP_TRADITIONAL (pfile) && kt->traditional_comments;
+ int comments = CPP_TRADITIONAL (pfile) && kt->type == T_DEFINE;
int save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
CPP_OPTIONS (pfile)->put_out_comments = comments;
after_ident = CPP_WRITTEN (pfile);
CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
}
- /* For #pragma and #define, we may want to pass through the directive.
+ /* We may want to pass through #define, #pragma, and #include.
Other directives may create output, but we don't want the directive
- itself out, so we pop it now. For example #include may write a #line
- command (see comment in do_include), and conditionals may emit
+ itself out, so we pop it now. For example conditionals may emit
#failed ... #endfailed stuff. But note that popping the buffer
means the parameters to kt->func may point after pfile->limit
so these parameters are invalid as soon as something gets appended
to the token_buffer. */
line_end = CPP_PWRITTEN (pfile);
- if (!kt->pass_thru && kt->type != T_DEFINE)
+ if (! (kt->type == T_DEFINE
+ || kt->type == T_PRAGMA
+ || (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)
+ && CPP_OPTIONS (pfile)->dump_includes)))
CPP_SET_WRITTEN (pfile, old_written);
(*kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);
- if (kt->pass_thru
- || (kt->type == T_DEFINE
- && CPP_OPTIONS (pfile)->dump_macros == dump_definitions))
- {
- /* Just leave the entire #define in the output stack. */
- }
- else if (kt->type == T_DEFINE
- && CPP_OPTIONS (pfile)->dump_macros == dump_names)
+
+ if (kt->type == T_DEFINE)
{
- U_CHAR *p = pfile->token_buffer + old_written + 7; /* Skip "#define". */
- SKIP_WHITE_SPACE (p);
- while (is_idchar[*p]) p++;
- pfile->limit = p;
- CPP_PUTC (pfile, '\n');
+ if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
+ {
+ /* Skip "#define". */
+ U_CHAR *p = pfile->token_buffer + old_written + 7;
+
+ SKIP_WHITE_SPACE (p);
+ while (is_idchar[*p]) p++;
+ pfile->limit = p;
+ CPP_PUTC (pfile, '\n');
+ }
+ else if (CPP_OPTIONS (pfile)->dump_macros != dump_definitions)
+ CPP_SET_WRITTEN (pfile, old_written);
}
- else if (kt->type == T_DEFINE)
- CPP_SET_WRITTEN (pfile, old_written);
+
done_a_directive:
return 1;
appeared. So the arglist is just convenience data passed
between these two routines. It is not kept around after
the current #define has been processed and entered into the
- hash table. */
+ hash table. */
struct arglist {
struct arglist *next;
MACRONAME is the macro name itself (so we can avoid recursive expansion)
and NAMELEN is its length in characters.
-Note that comments and backslash-newlines have already been deleted
-from the argument. */
+ Note that comments, backslash-newlines, and leading white space
+ have already been deleted from the argument. */
static DEFINITION *
-collect_expansion (pfile, buf, end, nargs, arglist)
+collect_expansion (pfile, buf, limit, nargs, arglist)
cpp_reader *pfile;
- U_CHAR *buf, *end;
+ U_CHAR *buf, *limit;
int nargs;
struct arglist *arglist;
{
DEFINITION *defn;
- register U_CHAR *p, *limit, *lastp, *exp_p;
+ register U_CHAR *p, *lastp, *exp_p;
struct reflist *endpat = NULL;
/* Pointer to first nonspace after last ## seen. */
U_CHAR *concat = 0;
/* Scan thru the replacement list, ignoring comments and quoted
strings, picking up on the macro calls. It does a linear search
thru the arg list on every potential symbol. Profiling might say
- that something smarter should happen. */
+ that something smarter should happen. */
- if (end < buf)
+ if (limit < buf)
abort ();
/* Find the beginning of the trailing whitespace. */
- /* Find end of leading whitespace. */
- limit = end;
p = buf;
while (p < limit && is_space[limit[-1]]) limit--;
- while (p < limit && is_space[*p]) p++;
/* Allocate space for the text in the macro definition.
Leading and trailing whitespace chars need 2 bytes each.
Each other input char may or may not need 1 byte,
- so this is an upper bound.
- The extra 2 are for invented trailing newline-marker and final null. */
+ so this is an upper bound. The extra 5 are for invented
+ leading and trailing newline-marker and final null. */
maxsize = (sizeof (DEFINITION)
- + 2 * (end - limit) + 2 * (p - buf)
- + (limit - p) + 3);
+ + (limit - p) + 5);
+ /* Occurrences of '@' get doubled, so allocate extra space for them. */
+ while (p < limit)
+ if (*p++ == '@')
+ maxsize++;
defn = (DEFINITION *) xcalloc (1, maxsize);
defn->nargs = nargs;
p = buf;
- /* Add one initial space (often removed by macroexpand). */
+ /* Add one initial space escape-marker to prevent accidental
+ token-pasting (often removed by macroexpand). */
+ *exp_p++ = '@';
*exp_p++ = ' ';
if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {
expected_delimiter = c;
break;
- /* Special hack: if a \# is written in the #define
- include a # in the definition. This is useless for C code
- but useful for preprocessing other things. */
-
case '\\':
- /* \# quotes a # even outside of strings. */
- if (p < limit && *p == '#' && !expected_delimiter) {
- exp_p--;
- *exp_p++ = *p++;
- } else if (p < limit && expected_delimiter) {
+ if (p < limit && expected_delimiter) {
/* In a string, backslash goes through
and makes next char ordinary. */
*exp_p++ = *p++;
break;
case '@':
- *exp_p++ = c;
+ /* An '@' in a string or character constant stands for itself,
+ and does not need to be escaped. */
+ if (!expected_delimiter)
+ *exp_p++ = c;
break;
case '#':
Don't leave the # in the expansion. */
exp_p--;
SKIP_WHITE_SPACE (p);
- if (p == limit || ! is_idstart[*p])
+ if (p == limit || ! is_idstart[*p]
+ || (*p == 'L' && p + 1 < limit && (p[1] == '\'' || p[1] == '"')))
cpp_error (pfile,
"`#' operator is not followed by a macro argument name");
else
while (p != limit && is_idchar[*p]) p++;
id_len = p - id_beg;
- if (is_idstart[c]) {
+ if (is_idstart[c]
+ && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {
register struct arglist *arg;
for (arg = arglist; arg != NULL; arg = arg->next) {
}
}
- if (limit < end) {
- while (limit < end && is_space[*limit]) {
- *exp_p++ = *limit++;
+ if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0)
+ {
+ /* If ANSI, put in a "@ " marker to prevent token pasting.
+ But not if "inside a string" (which in ANSI mode
+ happens only for -D option). */
+ *exp_p++ = '@';
+ *exp_p++ = ' ';
}
- } else if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0) {
- /* There is no trailing whitespace, so invent some in ANSI mode.
- But not if "inside a string" (which in ANSI mode
- happens only for -D option). */
- *exp_p++ = ' ';
- }
*exp_p = '\0';
#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)
/* Create a DEFINITION node from a #define directive. Arguments are
- as for do_define. */
+ as for do_define. */
+
static MACRODEF
create_definition (buf, limit, pfile, predefinition)
U_CHAR *buf, *limit;
/* Lossage will occur if identifiers or control keywords are broken
across lines using backslash. This is not the right place to take
- care of that. */
+ care of that. */
if (*bp == '(') {
struct arglist *arg_ptrs = NULL;
while (is_idchar[*bp]) {
bp++;
/* do we have a "special" rest-args extension here? */
- if (limit - bp > REST_EXTENSION_LENGTH &&
- strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
+ if (limit - bp > REST_EXTENSION_LENGTH
+ && strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
rest_args = 1;
temp->rest_args = 1;
break;
struct arglist *otemp;
for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
- if (temp->length == otemp->length &&
- strncmp (temp->name, otemp->name, temp->length) == 0) {
+ if (temp->length == otemp->length
+ && strncmp (temp->name, otemp->name, temp->length) == 0) {
U_CHAR *name;
name = (U_CHAR *) alloca (temp->length + 1);
}
++bp; /* skip paren */
- /* Skip exactly one space or tab if any. */
- if (bp < limit && (*bp == ' ' || *bp == '\t')) ++bp;
- /* now everything from bp before limit is the definition. */
+ SKIP_WHITE_SPACE (bp);
+ /* now everything from bp before limit is the definition. */
defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);
defn->rest_args = rest_args;
}
}
}
- /* now everything from bp before limit is the definition. */
+ /* now everything from bp before limit is the definition. */
defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
defn->args.argnames = (U_CHAR *) "";
}
for (p = symname; is_idchar[*p]; p++)
;
sym_length = p - symname;
- if (sym_length == 0)
+ if (sym_length == 0
+ || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
cpp_error (pfile, "invalid %s name", usage);
else if (!is_idstart[*symname]) {
- U_CHAR *msg; /* what pain... */
+ U_CHAR *msg; /* what pain... */
msg = (U_CHAR *) alloca (sym_length + 1);
bcopy (symname, msg, sym_length);
msg[sym_length] = 0;
return sym_length;
}
-/*
- * return zero if two DEFINITIONs are isomorphic
- */
+/* Return zero if two DEFINITIONs are isomorphic. */
+
static int
-compare_defs (d1, d2)
+compare_defs (pfile, d1, d2)
+ cpp_reader *pfile;
DEFINITION *d1, *d2;
{
register struct reflist *a1, *a2;
if (d1->nargs != d2->nargs)
return 1;
- if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
+ if (CPP_PEDANTIC (pfile)
+ && 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) {
ok = 1;
/* Redefining a macro is ok if the definitions are the same. */
else if (hp->type == T_MACRO)
- ok = ! compare_defs (mdef.defn, hp->value.defn);
+ ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
/* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST)
ok = ! CPP_OPTIONS (pfile)->done_initializing;
/* Print the warning if it's not ok. */
if (!ok)
{
- U_CHAR *msg; /* what pain... */
+ U_CHAR *msg; /* what pain... */
/* If we are passing through #define and #undef directives, do
that for this re-definition now. */
if stringified.
`use_count' is the number of times this macro arg is substituted
into the macro. If the actual use count exceeds 10,
- the value stored is 10. */
+ the value stored is 10. */
/* raw and expanded are relative to ARG_BASE */
#define ARG_BASE ((pfile)->token_buffer)
int raw_length, expand_length;
int stringified_length;
char newlines;
- char comments;
char use_count;
};
+/* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack.
+ If BUFFER != NULL, then use the LENGTH characters in BUFFER
+ as the new input buffer.
+ Return the new buffer, or NULL on failure. */
-cpp_buffer*
+cpp_buffer *
cpp_push_buffer (pfile, buffer, length)
cpp_reader *pfile;
U_CHAR *buffer;
long length;
{
-#ifdef STATIC_BUFFERS
- register cpp_buffer *buf;
+ register cpp_buffer *buf = CPP_BUFFER (pfile);
if (buf == pfile->buffer_stack)
- fatal ("macro or `#include' recursion too deep");
- buf = CPP_BUFFER (pfile) - 1;
- bzero ((char *) buf, sizeof (cpp_buffer));
- CPP_BUFFER (pfile) = buf;
-#else
- register cpp_buffer *buf = (cpp_buffer*) xmalloc (sizeof(cpp_buffer));
+ {
+ cpp_fatal (pfile, "%s: macro or `#include' recursion too deep",
+ buf->fname);
+ return NULL;
+ }
+ buf--;
bzero ((char *) buf, sizeof (cpp_buffer));
- CPP_PREV_BUFFER (buf) = CPP_BUFFER (pfile);
CPP_BUFFER (pfile) = buf;
-#endif
buf->if_stack = pfile->if_stack;
buf->cleanup = null_cleanup;
buf->underflow = null_underflow;
return buf;
}
-cpp_buffer*
+cpp_buffer *
cpp_pop_buffer (pfile)
cpp_reader *pfile;
{
cpp_buffer *buf = CPP_BUFFER (pfile);
-#ifdef STATIC_BUFFERS
(*buf->cleanup) (buf, pfile);
return ++CPP_BUFFER (pfile);
-#else
- cpp_buffer *next_buf = CPP_PREV_BUFFER (buf);
- (*buf->cleanup) (buf, pfile);
- CPP_BUFFER (pfile) = next_buf;
- free (buf);
- return next_buf;
-#endif
}
/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer.
- Pop the buffer when done. */
+ Pop the buffer when done. */
void
cpp_scan_buffer (pfile)
for (;;)
{
enum cpp_token token = cpp_get_token (pfile);
- if (token == CPP_EOF) /* Should not happen ... */
+ if (token == CPP_EOF) /* Should not happen ... */
break;
if (token == CPP_POP && CPP_BUFFER (pfile) == buffer)
{
}
/*
- * Rescan a string into pfile's buffer.
+ * Rescan a string (which may have escape marks) into pfile's buffer.
* Place the result in pfile->token_buffer.
*
* The input is copied before it is scanned, so it is safe to pass
* it something from the token_buffer that will get overwritten
* (because it follows CPP_WRITTEN). This is used by do_include.
- *
- * OUTPUT_MARKS nonzero means keep Newline markers found in the input
- * and insert such markers when appropriate. See `rescan' for details.
- * OUTPUT_MARKS is 1 for macroexpanding a macro argument separately
- * before substitution; it is 0 for other uses.
*/
-void
+static void
cpp_expand_to_buffer (pfile, buf, length)
cpp_reader *pfile;
U_CHAR *buf;
buf1[length] = 0;
ip = cpp_push_buffer (pfile, buf1, length);
+ if (ip == NULL)
+ return;
+ ip->has_escapes = 1;
#if 0
ip->lineno = obuf.lineno = 1;
#endif
}
}
-/* Move line_base forward, updating lineno and colno. */
+/* Move line_base forward, updating lineno and colno. */
static void
update_position (pbuf)
}
}
-/* Return the cpp_buffer that corresponds to a file (not a macro). */
+/* Return the cpp_buffer that corresponds to a file (not a macro). */
-cpp_buffer*
+cpp_buffer *
cpp_file_buffer (pfile)
cpp_reader *pfile;
{
- cpp_buffer *ip;
+ cpp_buffer *ip = CPP_BUFFER (pfile);
- for (ip = CPP_BUFFER (pfile); ip != NULL; ip = CPP_PREV_BUFFER (ip))
+ for ( ; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
if (ip->fname != NULL)
return ip;
return NULL;
long line, col;
cpp_buffer *ip = CPP_BUFFER (pfile);
- if (CPP_OPTIONS (pfile)->no_line_commands
- || ip->fname == NULL || CPP_OPTIONS (pfile)->no_output) {
+ if (ip->fname == NULL)
return;
- }
update_position (ip);
+
+ if (CPP_OPTIONS (pfile)->no_line_commands
+ || CPP_OPTIONS (pfile)->no_output)
+ return;
+
line = CPP_BUFFER (pfile)->lineno;
col = CPP_BUFFER (pfile)->colno;
adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
+ if (CPP_OPTIONS (pfile)->no_line_commands)
+ return;
+
if (conditional) {
if (line == pfile->lineno)
return;
CPP_PUTS_Q (pfile, sharp_line, sizeof(sharp_line)-1);
}
- sprintf (CPP_PWRITTEN (pfile), "%d ", line);
+ sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
quote_string (pfile, ip->nominal_fname);
}
\f
/*
- * Parse a macro argument and store the info on it into *ARGPTR.
+ * Parse a macro argument and append the info on PFILE's token_buffer.
* REST_ARGS means to absorb the rest of the args.
* Return nonzero to indicate a syntax error.
*/
goto found;
break;
found:
- /* Remove ',' or ')' from argument buffer. */
+ /* Remove ',' or ')' from argument buffer. */
CPP_ADJUST_WRITTEN (pfile, -1);
goto done;
default: ;
cpp_reader *pfile;
{
if (!pfile->timebuf) {
- time_t t = time ((time_t *)0);
+ time_t t = time ((time_t *) 0);
pfile->timebuf = localtime (&t);
}
return pfile->timebuf;
for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
{
- if (ip == NULL)
+ if (ip == CPP_NULL_BUFFER (pfile))
{
cpp_error (pfile, "cccp error: not in any file?!");
return; /* the show must go on */
char *string;
if (hp->type == T_BASE_FILE)
{
- while (CPP_PREV_BUFFER (ip))
+ while (CPP_PREV_BUFFER (ip) != CPP_NULL_BUFFER (pfile))
ip = CPP_PREV_BUFFER (ip);
}
string = ip->nominal_fname;
case T_INCLUDE_LEVEL:
true_indepth = 0;
- for (ip = CPP_BUFFER (pfile); ip != NULL; ip = CPP_PREV_BUFFER (ip))
+ ip = CPP_BUFFER (pfile);
+ for (; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
if (ip->fname != NULL)
true_indepth++;
case T_CONST:
buf = (char *) alloca (4 * sizeof (int));
sprintf (buf, "%d", hp->value.ival);
+#ifdef STDC_0_IN_SYSTEM_HEADERS
+ if (ip->system_header_p
+ && hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0
+ && ! cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", -1, -1))
+ strcpy (buf, "0");
+#endif
#if 0
if (pcp_inside_if && pcp_outfile)
/* Output a precondition for this macro use */
case T_SPECLINE:
{
- long line = CPP_BUFFER (pfile)->lineno;
- long col = CPP_BUFFER (pfile)->colno;
- cpp_buffer *ip = CPP_BUFFER (pfile);
+ long line = ip->lineno;
+ long col = ip->colno;
adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
buf = (char *) alloca (10);
- sprintf (buf, "%d", line);
+ sprintf (buf, "%ld", line);
}
break;
if (!is_idstart[*ip->cur])
goto oops;
+ if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
+ goto oops;
if (hp = cpp_lookup (pfile, ip->cur, -1, -1))
{
#if 0
if (pcp_outfile && pcp_inside_if
&& (hp->type == T_CONST
|| (hp->type == T_MACRO && hp->value.defn->predefined)))
- /* Output a precondition for this macro use. */
+ /* Output a precondition for this macro use. */
fprintf (pcp_outfile, "#define %s\n", hp->name);
#endif
buf = " 1 ";
return;
}
+/* Write out a #define command for the special named MACRO_NAME
+ to PFILE's token_buffer. */
+
+static void
+dump_special_to_buffer (pfile, macro_name)
+ cpp_reader *pfile;
+ char *macro_name;
+{
+ static char define_directive[] = "#define ";
+ int macro_name_length = strlen (macro_name);
+ output_line_command (pfile, 0, same_file);
+ CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
+ CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
+ CPP_PUTS_Q (pfile, macro_name, macro_name_length);
+ CPP_PUTC_Q (pfile, ' ');
+ cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
+ CPP_PUTC (pfile, '\n');
+}
+
/* Initialize the built-in macros. */
static void
initialize_builtins (pfile)
cpp_reader *pfile;
{
- install ("__LINE__", -1, T_SPECLINE, 0, 0, -1);
- install ("__DATE__", -1, T_DATE, 0, 0, -1);
- install ("__FILE__", -1, T_FILE, 0, 0, -1);
- install ("__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1);
- install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1);
- install ("__VERSION__", -1, T_VERSION, 0, 0, -1);
+ install ((U_CHAR *)"__LINE__", -1, T_SPECLINE, 0, 0, -1);
+ install ((U_CHAR *)"__DATE__", -1, T_DATE, 0, 0, -1);
+ install ((U_CHAR *)"__FILE__", -1, T_FILE, 0, 0, -1);
+ install ((U_CHAR *)"__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1);
+ install ((U_CHAR *)"__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1);
+ install ((U_CHAR *)"__VERSION__", -1, T_VERSION, 0, 0, -1);
#ifndef NO_BUILTIN_SIZE_TYPE
- install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1);
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
- install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1);
#endif
- install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1);
- install ("__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1);
- install ("__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1);
- install ("__TIME__", -1, T_TIME, 0, 0, -1);
+ install ((U_CHAR *)"__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__TIME__", -1, T_TIME, 0, 0, -1);
if (!CPP_TRADITIONAL (pfile))
- install ("__STDC__", -1, T_CONST, STDC_VALUE, 0, -1);
+ install ((U_CHAR *)"__STDC__", -1, T_CONST, STDC_VALUE, 0, -1);
if (CPP_OPTIONS (pfile)->objc)
- install ("__OBJC__", -1, T_CONST, 1, 0, -1);
+ install ((U_CHAR *)"__OBJC__", -1, T_CONST, 1, 0, -1);
/* This is supplied using a -D by the compiler driver
so that it is present only when truly compiling with GNU C. */
/* install ("__GNUC__", -1, T_CONST, 2, 0, -1); */
if (CPP_OPTIONS (pfile)->debug_output)
{
- char directive[2048];
- register struct directive *dp = &directive_table[0];
- struct tm *timebuf = timestamp ();
- cpp_buffer *pbuffer = CPP_BUFFER (pfile);
-
- while (CPP_PREV_BUFFER (pbuffer))
- pbuffer = CPP_PREV_BUFFER (pbuffer);
- sprintf (directive, " __BASE_FILE__ \"%s\"\n",
- pbuffer->nominal_fname);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
- sprintf (directive, " __VERSION__ \"%s\"\n", version_string);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
+ dump_special_to_buffer (pfile, "__BASE_FILE__");
+ dump_special_to_buffer (pfile, "__VERSION__");
#ifndef NO_BUILTIN_SIZE_TYPE
- sprintf (directive, " __SIZE_TYPE__ %s\n", SIZE_TYPE);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
+ dump_special_to_buffer (pfile, "__SIZE_TYPE__");
#endif
-
#ifndef NO_BUILTIN_PTRDIFF_TYPE
- sprintf (directive, " __PTRDIFF_TYPE__ %s\n", PTRDIFF_TYPE);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
+ dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
#endif
-
- sprintf (directive, " __WCHAR_TYPE__ %s\n", CPP_WCHAR_TYPE (pfile));
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
- sprintf (directive, " __DATE__ \"%s %2d %4d\"\n",
- monthnames[timebuf->tm_mon],
- timebuf->tm_mday, timebuf->tm_year + 1900);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
- sprintf (directive, " __TIME__ \"%02d:%02d:%02d\"\n",
- timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
+ dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
+ dump_special_to_buffer (pfile, "__DATE__");
+ dump_special_to_buffer (pfile, "__TIME__");
if (!CPP_TRADITIONAL (pfile))
- {
- sprintf (directive, " __STDC__ 1");
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)],
- pfile, dp);
- }
+ dump_special_to_buffer (pfile, "__STDC__");
if (CPP_OPTIONS (pfile)->objc)
- {
- sprintf (directive, " __OBJC__ 1");
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)],
- pfile, dp);
- }
+ dump_special_to_buffer (pfile, "__OBJC__");
}
}
\f
/* Return 1 iff a token ending in C1 followed directly by a token C2
- could cause mis-tokenization. */
+ could cause mis-tokenization. */
static int
unsafe_chars (c1, c2)
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- case 'e': case 'E':
+ case 'e': case 'E': case 'p': case 'P':
if (c2 == '-' || c2 == '+')
return 1; /* could extend a pre-processing number */
goto letter;
case 'L':
if (c2 == '\'' || c2 == '\"')
- return 1; /* Could turn into L"xxx" or L'xxx'. */
+ return 1; /* Could turn into L"xxx" or L'xxx'. */
goto letter;
letter:
case '_':
case 'a': case 'b': case 'c': case 'd': case 'f':
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+ case 'm': case 'n': case 'o': case 'q': case 'r':
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K':
- case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'M': case 'N': case 'O': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z':
- /* We're in the middle of either a name or a pre-processing number. */
+ /* We're in the middle of either a name or a pre-processing number. */
return (is_idchar[c2] || c2 == '.');
case '<': case '>': case '!': case '%': case '#': case ':':
case '^': case '&': case '|': case '*': case '/': case '=':
int nargs;
DEFINITION *defn = hp->value.defn;
register U_CHAR *xbuf;
+ long start_line, start_column;
int xbuf_len;
struct argdata *args;
long old_written = CPP_WRITTEN (pfile);
dump_single_macro (hp, pcp_outfile);
#endif
+ pfile->output_escapes++;
+ cpp_buf_line_and_col (cpp_file_buffer (pfile), &start_line, &start_column);
+
nargs = defn->nargs;
if (nargs >= 0)
{
- char *parse_error = 0;
enum cpp_token token;
args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
/* Parse all the macro args that are supplied. I counts them.
The first NARGS args are stored in ARGS.
The rest are discarded. If rest_args is set then we assume
- macarg absorbed the rest of the args. */
+ macarg absorbed the rest of the args. */
i = 0;
rest_args = 0;
rest_args = 0;
token = macarg (pfile, 0);
if (token == CPP_EOF || token == CPP_POP)
{
- parse_error = "unterminated macro call";
-#if 1
- cpp_error_with_line (pfile, line_for_error (0), parse_error);
-#else
- cpp_error_with_line (pfile, line_for_error (start_line), parse_error);
-#endif
- break;
+ cpp_error_with_line (pfile, start_line, start_column,
+ "unterminated macro call");
+ return;
}
i++;
} while (token == CPP_COMMA);
rest_zero = 0;
if (nargs == 0 && i > 0)
{
- if (! parse_error)
- cpp_error (pfile, "arguments given to macro `%s'", hp->name);
+ cpp_error (pfile, "arguments given to macro `%s'", hp->name);
}
else if (i < nargs)
{
/* the rest args token is allowed to absorb 0 tokens */
else if (i == nargs - 1 && defn->rest_args)
rest_zero = 1;
- else if (parse_error)
- ;
else if (i == 0)
cpp_error (pfile, "macro `%s' used without args", hp->name);
else if (i == 1)
}
else if (i > nargs)
{
- if (! parse_error)
- cpp_error (pfile,
- "macro `%s' used with too many (%d) args", hp->name, i);
+ cpp_error (pfile,
+ "macro `%s' used with too many (%d) args", hp->name, i);
}
}
int c;
/* Initially need_space is -1. Otherwise, 1 means the
previous character was a space, but we suppressed it;
- 0 means the previous character was a non-space. */
+ 0 means the previous character was a non-space. */
int need_space = -1;
i = 0;
arg->stringified = CPP_WRITTEN (pfile);
one space except within an string or char token.*/
if (is_space[c])
{
+ if (CPP_WRITTEN (pfile) > arg->stringified
+ && (CPP_PWRITTEN (pfile))[-1] == '@')
+ {
+ /* "@ " escape markers are removed */
+ CPP_ADJUST_WRITTEN (pfile, -1);
+ continue;
+ }
if (need_space == 0)
need_space = 1;
continue;
else
{
CPP_RESERVE (pfile, 4);
- sprintf (CPP_PWRITTEN (pfile), "\\%03o",
+ sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o",
(unsigned int) c);
CPP_ADJUST_WRITTEN (pfile, 4);
}
if (args[ap->argno].expand_length < 0)
{
args[ap->argno].expanded = CPP_WRITTEN (pfile);
- pfile->output_escapes++;
cpp_expand_to_buffer (pfile,
ARG_BASE + args[ap->argno].raw,
args[ap->argno].raw_length);
- pfile->output_escapes--;
args[ap->argno].expand_length
= CPP_WRITTEN (pfile) - args[ap->argno].expanded;
}
while (p1 != l1 && is_space[*p1]) p1++;
while (p1 != l1 && is_idchar[*p1])
xbuf[totlen++] = *p1++;
+ /* Delete any no-reexpansion marker that follows
+ an identifier at the beginning of the argument
+ if the argument is concatenated with what precedes it. */
+ if (p1[0] == '@' && p1[1] == '-')
+ p1 += 2;
}
if (ap->raw_after)
{
if (!ap->raw_before && totlen > 0 && arg->expand_length
&& !CPP_TRADITIONAL(pfile)
&& unsafe_chars (xbuf[totlen-1], expanded[0]))
- xbuf[totlen++] = ' ';
+ {
+ xbuf[totlen++] = '@';
+ xbuf[totlen++] = ' ';
+ }
bcopy (expanded, xbuf + totlen, arg->expand_length);
totlen += arg->expand_length;
if (!ap->raw_after && totlen > 0 && offset < defn->length
&& !CPP_TRADITIONAL(pfile)
&& unsafe_chars (xbuf[totlen-1], exp[offset]))
- xbuf[totlen++] = ' ';
+ {
+ xbuf[totlen++] = '@';
+ xbuf[totlen++] = ' ';
+ }
/* If a macro argument with newlines is used multiple times,
then only expand the newlines once. This avoids creating
}
/* if there is anything left of the definition
- after handling the arg list, copy that in too. */
+ after handling the arg list, copy that in too. */
for (i = offset; i < defn->length; i++)
{
}
+ pfile->output_escapes--;
+
/* Now put the expansion on the input stack
so our caller will commence reading from it. */
push_macro_expansion (pfile, xbuf, xbuf_len, hp);
CPP_BUFFER (pfile)->has_escapes = 1;
- /* Pop the space we've used in the token_buffer for argument expansion. */
+ /* Pop the space we've used in the token_buffer for argument expansion. */
CPP_SET_WRITTEN (pfile, old_written);
/* Recursive macro use sometimes works traditionally.
HASHNODE *hp;
{
register cpp_buffer *mbuf = cpp_push_buffer (pfile, xbuf, xbuf_len);
+ if (mbuf == NULL)
+ return;
mbuf->cleanup = macro_cleanup;
mbuf->data = hp;
- /* The first char of the expansion should be a ' ' added by
+ /* The first chars of the expansion should be a "@ " added by
collect_expansion. This is to prevent accidental token-pasting
between the text preceding the macro invocation, and the macro
expansion text.
Also, we don't need the extra space if the first char is '(',
or some other (less common) characters. */
- if (xbuf[0] == ' '
- && (is_idchar[xbuf[1]] || xbuf[1] == '(' || xbuf[1] == '\''
- || xbuf[1] == '\"'))
- mbuf->cur++;
+ if (xbuf[0] == '@' && xbuf[1] == ' '
+ && (is_idchar[xbuf[2]] || xbuf[2] == '(' || xbuf[2] == '\''
+ || xbuf[2] == '\"'))
+ mbuf->cur += 2;
}
\f
/* Like cpp_get_token, except that it does not read past end-of-line.
case CPP_POP:
if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
return token;
- /* ... else fall though ... */
+ /* ... else fall though ... */
case CPP_HSPACE: case CPP_COMMENT:
CPP_SET_WRITTEN (pfile, old_written);
break;
This function expects to see "fname" or <fname> on the input.
The input is normally in part of the output_buffer following
- CPP_WRITTEN, and will get overwriiten by output_line_command.
+ CPP_WRITTEN, and will get overwritten by output_line_command.
I.e. in input file specification has been popped by handle_directive.
- This is safe. */
+ This is safe. */
static int
do_include (pfile, keyword, unused1, unused2)
int f; /* file number */
int retried = 0; /* Have already tried macro
- expanding the include line*/
+ expanding the include line */
int angle_brackets = 0; /* 0 for "...", 1 for <...> */
int pcf = -1;
char *pcfbuf;
int pcfnum;
f= -1; /* JF we iz paranoid! */
+ if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
+ {
+ if (importing)
+ cpp_pedwarn (pfile, "ANSI C does not allow `#import'");
+ if (skip_dirs)
+ cpp_pedwarn (pfile, "ANSI C does not allow `#include_next'");
+ }
+
if (importing && CPP_OPTIONS (pfile)->warn_import
&& !CPP_OPTIONS (pfile)->inhibit_warnings
&& !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning)
if (CPP_OPTIONS (pfile)->first_bracket_include)
search_start = CPP_OPTIONS (pfile)->first_bracket_include;
}
- /* If -I- was specified, don't search current dir, only spec'd ones. */
+ /* If -I- was specified, don't search current dir, only spec'd ones. */
else if (! CPP_OPTIONS (pfile)->ignore_srcdir)
{
- cpp_buffer *fp;
+ cpp_buffer *fp = CPP_BUFFER (pfile);
/* We have "filename". Figure out directory this source
- file is coming from and put it on the front of the list. */
+ file is coming from and put it on the front of the list. */
- for (fp = CPP_BUFFER (pfile); fp != NULL; fp = CPP_PREV_BUFFER (fp))
+ for ( ; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp))
{
int n;
char *ep,*nam;
past the dir in which the containing file was found. */
if (skip_dirs)
{
- cpp_buffer *fp;
- for (fp = CPP_BUFFER (pfile); fp != NULL; fp = CPP_PREV_BUFFER (fp))
+ cpp_buffer *fp = CPP_BUFFER (pfile);
+ for (; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp))
if (fp->fname != NULL)
{
/* fp->dir is null if the containing file was specified with
if (importing)
f = lookup_import (pfile, fname, NULL_PTR);
else
- f = open_include_file (fname, NULL_PTR);
+ f = open_include_file (pfile, fname, NULL_PTR);
if (f == -2)
return 0; /* Already included this file */
} else {
if (importing)
f = lookup_import (pfile, fname, searchptr);
else
- f = open_include_file (fname, searchptr);
+ f = open_include_file (pfile, fname, searchptr);
if (f == -2)
return 0; /* Already included this file */
#ifdef EACCES
if (searchptr->fname[0] == 0)
continue;
- p = xmalloc (strlen (searchptr->fname)
- + strlen (fname) + 2);
+ p = (char *) alloca (strlen (searchptr->fname)
+ + strlen (fname) + 2);
strcpy (p, searchptr->fname);
strcat (p, "/");
strcat (p, fname);
/* Check to see if this include file is a once-only include file.
If so, give up. */
- struct file_name_list* ptr;
+ struct file_name_list *ptr;
for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next) {
if (!strcmp (ptr->fname, fname)) {
close (f);
- return 0; /* This file was once'd. */
+ return 0; /* This file was once'd. */
}
}
for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) {
if (!strcmp (ptr->fname, fname))
- break; /* This file was included before. */
+ break; /* This file was included before. */
}
if (ptr == 0) {
if (CPP_OPTIONS(pfile)->print_include_names)
{
cpp_buffer *buf = CPP_BUFFER (pfile);
- while ((buf = CPP_PREV_BUFFER (buf)) != NULL)
+ while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile))
putc ('.', stderr);
fprintf (stderr, "%s\n", fname);
}
/* Actually process the file. */
- /* Record file on "seen" list for #import. */
+ /* Record file on "seen" list for #import. */
add_import (pfile, f, fname);
pcftry = (char *) alloca (strlen (fname) + 30);
#endif
/* Actually process the file */
+ if (cpp_push_buffer (pfile, NULL, 0) == NULL)
+ return 0;
if (finclude (pfile, f, fname, is_system_include (pfile, fname),
searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
{
* If HASH is >= 0, it is the precomputed hash code.
* Otherwise, compute the hash code.
*/
+
static ASSERTION_HASHNODE *
assertion_install (pfile, name, len, hash)
cpp_reader *pfile;
delete_assertion (hp)
ASSERTION_HASHNODE *hp;
{
-
+ struct tokenlist_list *tail;
if (hp->prev != NULL)
hp->prev->next = hp->next;
if (hp->next != NULL)
hp->next->prev = hp->prev;
- /* make sure that the bucket chain header that
- the deleted guy was on points to the right thing afterwards. */
+ for (tail = hp->value; tail; )
+ {
+ struct tokenlist_list *next = tail->next;
+ free_token_list (tail->tokens);
+ free (tail);
+ tail = next;
+ }
+
+ /* Make sure that the bucket chain header that
+ the deleted guy was on points to the right thing afterwards. */
if (hp == *hp->bucket_hdr)
*hp->bucket_hdr = hp->next;
The value returned in the end of the string written to RESULT,
or NULL on error. */
-static U_CHAR*
+static U_CHAR *
convert_string (pfile, result, in, limit, handle_escapes)
cpp_reader *pfile;
register U_CHAR *result, *in, *limit;
/* The Newline at the end of this line remains to be processed.
To put the next line at the specified line number,
we must store a line number now that is one less. */
- new_lineno = atoi (pfile->token_buffer + old_written) - 1;
+ new_lineno = atoi ((char *)(pfile->token_buffer + old_written)) - 1;
CPP_SET_WRITTEN (pfile, old_written);
/* NEW_LINENO is one less than the actual line number here. */
}
}
- hash_bucket =
- &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
+ hash_bucket = &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
for (hp = *hash_bucket; hp != NULL; hp = hp->next)
- if (hp->length == fname_length &&
- strncmp (hp->value.cpval, fname, fname_length) == 0) {
+ if (hp->length == fname_length
+ && strncmp (hp->value.cpval, fname, fname_length) == 0) {
ip->nominal_fname = hp->value.cpval;
break;
}
U_CHAR *buf, *limit;
{
int length = limit - buf;
- U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
+ U_CHAR *copy = (U_CHAR *) alloca (length + 1);
bcopy (buf, copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
U_CHAR *buf, *limit;
{
int length = limit - buf;
- U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
+ U_CHAR *copy = (U_CHAR *) alloca (length + 1);
bcopy (buf, copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
- cpp_warning (pfile, "#warning %s", copy);
+ /* Use `pedwarn' not `warning', because #warning isn't in the C Standard;
+ if -pedantic-errors is given, #warning should cause an error. */
+ cpp_pedwarn (pfile, "#warning %s", copy);
return 0;
}
for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
{
- if (ip == NULL)
+ if (ip == CPP_NULL_BUFFER (pfile))
return 0;
if (ip->fname != NULL)
break;
return 0;
}
-/* #ident has already been copied to the output file, so just ignore it. */
+/* Report program identification. */
static int
do_ident (pfile, keyword, buf, limit)
if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
cpp_pedwarn (pfile, "ANSI C does not allow `#ident'");
- /* Leave rest of line to be read by later calls to cpp_get_token. */
+ /* Leave rest of line to be read by later calls to cpp_get_token. */
return 0;
}
* evaluate a #if expression in BUF, of length LENGTH,
* then parse the result as a C expression and return the value as an int.
*/
+
static HOST_WIDE_INT
eval_if_expression (pfile, buf, length)
cpp_reader *pfile;
HOST_WIDE_INT value;
long old_written = CPP_WRITTEN (pfile);
- save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1);
+ save_defined = install ((U_CHAR *)"defined", -1, T_SPEC_DEFINED, 0, 0, -1);
pfile->pcp_inside_if = 1;
value = cpp_parse_expr (pfile);
{
int skip;
cpp_buffer *ip = CPP_BUFFER (pfile);
- U_CHAR* ident;
+ U_CHAR *ident;
int ident_length;
enum cpp_token token;
int start_of_file = 0;
* leaves input ptr at the sharp sign found.
* If ANY is nonzero, return at next directive of any sort.
*/
+
static void
skip_if_group (pfile, any)
cpp_reader *pfile;
}
c = GETC ();
}
- /* We're in the middle of a line. Skip the rest of it. */
+ /* We're in the middle of a line. Skip the rest of it. */
for (;;) {
switch (c)
{
+ long old;
case EOF:
goto done;
case '/': /* possible comment */
break;
case '\"':
case '\'':
- skip_quoted_string (pfile, c, 0 /* FIXME */);
+ FORWARD(-1);
+ old = CPP_WRITTEN (pfile);
+ cpp_get_token (pfile);
+ CPP_SET_WRITTEN (pfile, old);
break;
case '\\':
/* Char after backslash loses its special meaning. */
"text following `%s' violates ANSI standard", directive);
}
-/* Get the next token, and add it to the tex in pfile->token_buffer.
- Return the kind of token we got. */
+/* Get the next token, and add it to the text in pfile->token_buffer.
+ Return the kind of token we got. */
-
enum cpp_token
cpp_get_token (pfile)
cpp_reader *pfile;
{
register int c, c2, c3;
long old_written;
+ long start_line, start_column;
enum cpp_token token;
struct cpp_options *opts = CPP_OPTIONS (pfile);
CPP_BUFFER (pfile)->prev = CPP_BUFFER (pfile)->cur;
cpp_buffer *next_buf
= CPP_PREV_BUFFER (CPP_BUFFER (pfile));
CPP_BUFFER (pfile)->seen_eof = 1;
- if (CPP_BUFFER (pfile)->nominal_fname && next_buf != 0)
+ if (CPP_BUFFER (pfile)->nominal_fname
+ && next_buf != CPP_NULL_BUFFER (pfile))
{
/* We're about to return from an #include file.
- Emit #line information now (as part of the CPP_POP) restult.
- But the #line refers to the file we will pop to. */
+ Emit #line information now (as part of the CPP_POP) result.
+ But the #line refers to the file we will pop to. */
cpp_buffer *cur_buffer = CPP_BUFFER (pfile);
CPP_BUFFER (pfile) = next_buf;
pfile->input_stack_listing_current = 0;
if (opts->put_out_comments)
parse_set_mark (&start_mark, pfile);
newlines = 0;
+ cpp_buf_line_and_col (cpp_file_buffer (pfile),
+ &start_line, &start_column);
c = skip_comment (pfile, &newlines);
if (opts->put_out_comments && (c == '/' || c == EOF))
parse_clear_mark (&start_mark);
goto randomchar;
if (c == EOF)
{
- cpp_error_with_line (pfile, line_for_error (pfile->start_line),
+ cpp_error_with_line (pfile, start_line, start_column,
"unterminated comment");
goto handle_eof;
}
- c = '/'; /* Initial letter of comment. */
+ c = '/'; /* Initial letter of comment. */
return_comment:
/* Comments are equivalent to spaces.
For -traditional, a comment is equivalent to nothing. */
{
#if 0
/* This may not work if cpp_get_token is called recursively,
- since many places look for horizontal space. */
+ since many places look for horizontal space. */
if (newlines)
{
/* Copy the newlines into the output buffer, in order to
CPP_PUTC_Q (pfile, ' ');
return CPP_HSPACE;
}
- if (opts->for_lint) {
#if 0
+ if (opts->for_lint) {
U_CHAR *argbp;
int cmdlen, arglen;
char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
}
/* OK, now bring us back to the state we were in before we entered
- this branch. We need #line b/c the newline for the pragma
- could fuck things up. */
+ this branch. We need #line because the newline for the pragma
+ could mess things up. */
output_line_command (pfile, 0, same_file);
*(obp++) = ' '; /* just in case, if comments are copied thru */
*(obp++) = '/';
}
-#endif
}
+#endif
case '#':
#if 0
case '\'':
/* A single quoted string is treated like a double -- some
programs (e.g., troff) are perverse this way */
-#if 0
- start_line = pfile->lineno;
-#endif
+ cpp_buf_line_and_col (cpp_file_buffer (pfile),
+ &start_line, &start_column);
old_written = CPP_WRITTEN (pfile);
string:
CPP_PUTC (pfile, c);
CPP_BUFFER (pfile) = next_buf;
continue;
}
-#if 0
if (!CPP_TRADITIONAL (pfile))
{
- cpp_error_with_line (pfile, line_for_error (start_line),
+ cpp_error_with_line (pfile, start_line, start_column,
"unterminated string or character constant");
- cpp_error_with_line (pfile, multiline_string_line,
- "possible real start of unterminated constant");
- multiline_string_line = 0;
+ if (pfile->multiline_string_line != start_line
+ && pfile->multiline_string_line != 0)
+ cpp_error_with_line (pfile,
+ pfile->multiline_string_line, -1,
+ "possible real start of unterminated constant");
+ pfile->multiline_string_line = 0;
}
-#endif
break;
}
CPP_PUTC (pfile, cc);
no error. So exit the loop and record the new line. */
if (CPP_TRADITIONAL (pfile))
goto while2end;
-#if 0
if (c == '\'')
{
- cpp_error_with_line (pfile, line_for_error (start_line),
- "unterminated character constant");
+ cpp_error_with_line (pfile, start_line, start_column,
+ "unterminated character constant");
goto while2end;
}
- if (CPP_PEDANTIC (pfile) && multiline_string_line == 0)
+ if (CPP_PEDANTIC (pfile)
+ && pfile->multiline_string_line == 0)
{
- cpp_pedwarn_with_line (pfile,
- line_for_error (start_line),
+ cpp_pedwarn_with_line (pfile, start_line, start_column,
"string constant runs past end of line");
}
- if (multiline_string_line == 0)
- multiline_string_line = ip->lineno - 1;
-#endif
+ if (pfile->multiline_string_line == 0)
+ pfile->multiline_string_line = start_line;
break;
case '\\':
cc = GETC();
if (cc == '\n')
{
- /* Backslash newline is replaced by nothing at all. */
+ /* Backslash newline is replaced by nothing at all. */
CPP_ADJUST_WRITTEN (pfile, -1);
pfile->lineno++;
}
/* Chill style comment */
if (opts->put_out_comments)
parse_set_mark (&start_mark, pfile);
- FORWARD(1); /* Skip second '-'. */
+ FORWARD(1); /* Skip second '-'. */
for (;;)
{
c = GETC ();
break;
if (c == '\n')
{
- /* Don't consider final '\n' to be part of comment. */
+ /* Don't consider final '\n' to be part of comment. */
FORWARD(-1);
break;
}
parse_name (pfile, GETC ());
return CPP_NAME;
}
+ else if (is_space [c])
+ {
+ CPP_RESERVE (pfile, 2);
+ if (pfile->output_escapes)
+ CPP_PUTC_Q (pfile, '@');
+ CPP_PUTC_Q (pfile, c);
+ return CPP_HSPACE;
+ }
}
if (pfile->output_escapes)
{
if (c == EOF)
break;
if (!is_idchar[c] && c != '.'
- && ((c2 != 'e' && c2 != 'E') || (c != '+' && c != '-')))
+ && ((c2 != 'e' && c2 != 'E'
+ && ((c2 != 'p' && c2 != 'P') || CPP_C89 (pfile)))
+ || (c != '+' && c != '-')))
break;
FORWARD(1);
c2= c;
if (hp->type == T_DISABLED)
{
if (pfile->output_escapes)
- { /* Return "@-IDENT", followed by '\0'. */
+ { /* Return "@-IDENT", followed by '\0'. */
int i;
CPP_RESERVE (pfile, 3);
ident = pfile->token_buffer + before_name_written;
if (!is_macro_call)
return CPP_NAME;
}
- /* This is now known to be a macro call. */
+ /* This is now known to be a macro call. */
/* it might not actually be a macro. */
if (hp->type != T_MACRO) {
CPP_SET_WRITTEN (pfile, before_name_written);
}
- /* An extra space is added to the end of a macro expansion
+ /* An extra "@ " is added to the end of a macro expansion
to prevent accidental token pasting. We prefer to avoid
unneeded extra spaces (for the sake of cpp-using tools like
- imake). Here we remove the space if it is safe to do so. */
- if (pfile->buffer->rlimit - pfile->buffer->cur >= 2
- && pfile->buffer->cur[-1] == ' ')
+ imake). Here we remove the space if it is safe to do so. */
+ if (pfile->buffer->rlimit - pfile->buffer->cur >= 3
+ && pfile->buffer->rlimit[-2] == '@'
+ && pfile->buffer->rlimit[-1] == ' ')
{
- int c1 = pfile->buffer->rlimit[-2];
+ int c1 = pfile->buffer->rlimit[-3];
int c2 = CPP_BUF_PEEK (CPP_PREV_BUFFER (CPP_BUFFER (pfile)));
if (c2 == EOF || ! unsafe_chars (c1, c2))
- pfile->buffer->rlimit--;
+ pfile->buffer->rlimit -= 2;
}
-
- goto get_next;
}
- return CPP_NAME;
+ goto get_next;
case ' ': case '\t': case '\v': case '\r':
for (;;)
}
}
-/* Like cpp_get_token, but skip spaces and comments. */
+/* Like cpp_get_token, but skip spaces and comments. */
+
enum cpp_token
cpp_get_non_space_token (pfile)
cpp_reader *pfile;
}
}
-/* Parse an identifier starting with C. */
+/* Parse an identifier starting with C. */
int
parse_name (pfile, c)
break;
}
- CPP_RESERVE(pfile, 2); /* One more for final NUL. */
+ if (c == '$' && CPP_PEDANTIC (pfile))
+ cpp_pedwarn ("`$' in identifier");
+
+ CPP_RESERVE(pfile, 2); /* One more for final NUL. */
CPP_PUTC_Q (pfile, c);
c = GETC();
if (c == EOF)
static int
lookup_import (pfile, filename, searchptr)
-cpp_reader *pfile;
+ cpp_reader *pfile;
char *filename;
struct file_name_list *searchptr;
{
i = i->next;
}
/* Open it and try a match on inode/dev */
- fd = open_include_file (filename, searchptr);
+ fd = open_include_file (pfile, filename, searchptr);
if (fd < 0)
return fd;
fstat (fd, &sb);
while (i) {
/* Compare the inode and the device.
Supposedly on some systems the inode is not a scalar. */
- if (!bcmp (&i->inode, &sb.st_ino, sizeof (sb.st_ino))
+ if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino))
&& i->dev == sb.st_dev) {
close (fd);
return -2; /* return found */
i = (struct import_file *)xmalloc (sizeof (struct import_file));
i->name = (char *)xmalloc (strlen (fname)+1);
strcpy (i->name, fname);
- bcopy (&sb.st_ino, &i->inode, sizeof (sb.st_ino));
+ bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino));
i->dev = sb.st_dev;
i->next = pfile->import_hash_table[hashval];
pfile->import_hash_table[hashval] = i;
return alloc;
}
+/* This structure holds a linked list of file name maps, one per directory. */
+
+struct file_name_map_list
+{
+ struct file_name_map_list *map_list_next;
+ char *map_list_name;
+ struct file_name_map *map_list_map;
+};
+
/* Read the file name map file for DIRNAME. */
static struct file_name_map *
-read_name_map (dirname)
+read_name_map (pfile, dirname)
+ cpp_reader *pfile;
char *dirname;
{
- /* This structure holds a linked list of file name maps, one per
- directory. */
- struct file_name_map_list
- {
- struct file_name_map_list *map_list_next;
- char *map_list_name;
- struct file_name_map *map_list_map;
- };
- static struct file_name_map_list *map_list;
register struct file_name_map_list *map_list_ptr;
char *name;
FILE *f;
- for (map_list_ptr = map_list; map_list_ptr;
+ for (map_list_ptr = CPP_OPTIONS (pfile)->map_list; map_list_ptr;
map_list_ptr = map_list_ptr->map_list_next)
if (! strcmp (map_list_ptr->map_list_name, dirname))
return map_list_ptr->map_list_map;
fclose (f);
}
- map_list_ptr->map_list_next = map_list;
- map_list = map_list_ptr;
+ map_list_ptr->map_list_next = CPP_OPTIONS (pfile)->map_list;
+ CPP_OPTIONS (pfile)->map_list = map_list_ptr;
return map_list_ptr->map_list_map;
}
read_name_map. */
static int
-open_include_file (filename, searchptr)
+open_include_file (pfile, filename, searchptr)
+ cpp_reader *pfile;
char *filename;
struct file_name_list *searchptr;
{
- register struct file_name_map *map;
- register char *from;
- char *p, *dir;
-
- if (searchptr && ! searchptr->got_name_map)
+ if (CPP_OPTIONS (pfile)->remap)
{
- searchptr->name_map = read_name_map (searchptr->fname
- ? searchptr->fname : ".");
- searchptr->got_name_map = 1;
- }
+ register struct file_name_map *map;
+ register char *from;
+ char *p, *dir;
- /* First check the mapping for the directory we are using. */
- if (searchptr && searchptr->name_map)
- {
- from = filename;
- if (searchptr->fname)
- from += strlen (searchptr->fname) + 1;
- for (map = searchptr->name_map; map; map = map->map_next)
+ if (searchptr && ! searchptr->got_name_map)
{
- if (! strcmp (map->map_from, from))
+ searchptr->name_map = read_name_map (pfile,
+ searchptr->fname
+ ? searchptr->fname : ".");
+ searchptr->got_name_map = 1;
+ }
+
+ /* First check the mapping for the directory we are using. */
+ if (searchptr && searchptr->name_map)
+ {
+ from = filename;
+ if (searchptr->fname)
+ from += strlen (searchptr->fname) + 1;
+ for (map = searchptr->name_map; map; map = map->map_next)
{
- /* Found a match. */
- return open (map->map_to, O_RDONLY, 0666);
+ if (! strcmp (map->map_from, from))
+ {
+ /* Found a match. */
+ return open (map->map_to, O_RDONLY, 0666);
+ }
}
}
- }
- /* Try to find a mapping file for the particular directory we are
- looking in. Thus #include <sys/types.h> will look up sys/types.h
- in /usr/include/header.gcc and look up types.h in
- /usr/include/sys/header.gcc. */
- p = rindex (filename, '/');
- if (! p)
- p = filename;
- if (searchptr
- && searchptr->fname
- && strlen (searchptr->fname) == p - filename
- && ! strncmp (searchptr->fname, filename, p - filename))
- {
- /* FILENAME is in SEARCHPTR, which we've already checked. */
- return open (filename, O_RDONLY, 0666);
- }
+ /* Try to find a mapping file for the particular directory we are
+ looking in. Thus #include <sys/types.h> will look up sys/types.h
+ in /usr/include/header.gcc and look up types.h in
+ /usr/include/sys/header.gcc. */
+ p = rindex (filename, '/');
+ if (! p)
+ p = filename;
+ if (searchptr
+ && searchptr->fname
+ && strlen (searchptr->fname) == p - filename
+ && ! strncmp (searchptr->fname, filename, p - filename))
+ {
+ /* FILENAME is in SEARCHPTR, which we've already checked. */
+ return open (filename, O_RDONLY, 0666);
+ }
- if (p == filename)
- {
- dir = ".";
- from = filename;
- }
- else
- {
- dir = (char *) alloca (p - filename + 1);
- bcopy (filename, dir, p - filename);
- dir[p - filename] = '\0';
- from = p + 1;
+ if (p == filename)
+ {
+ dir = ".";
+ from = filename;
+ }
+ else
+ {
+ dir = (char *) alloca (p - filename + 1);
+ bcopy (filename, dir, p - filename);
+ dir[p - filename] = '\0';
+ from = p + 1;
+ }
+ for (map = read_name_map (pfile, dir); map; map = map->map_next)
+ if (! strcmp (map->map_from, from))
+ return open (map->map_to, O_RDONLY, 0666);
}
- for (map = read_name_map (dir); map; map = map->map_next)
- if (! strcmp (map->map_from, from))
- return open (map->map_to, O_RDONLY, 0666);
return open (filename, O_RDONLY, 0666);
}
function above).
DIRPTR is the link in the dir path through which this file was found,
or 0 if the file name was absolute or via the current directory.
- Return 1 on success, 0 on failure. */
+ Return 1 on success, 0 on failure.
+
+ The caller is responsible for the cpp_push_buffer. */
static int
finclude (pfile, f, fname, system_header_p, dirptr)
int system_header_p;
struct file_name_list *dirptr;
{
- int st_mode;
- long st_size;
+ struct stat st;
+ size_t st_size;
long i;
int length;
cpp_buffer *fp; /* For input stack frame */
int missing_newline = 0;
-#if 0
- CHECK_DEPTH (return 0;);
-#endif
-
- if (file_size_and_mode (f, &st_mode, &st_size) < 0)
+ if (fstat (f, &st) < 0)
{
cpp_perror_with_name (pfile, fname);
close (f);
+ cpp_pop_buffer (pfile);
return 0;
}
- fp = cpp_push_buffer (pfile, NULL, 0);
+ fp = CPP_BUFFER (pfile);
fp->nominal_fname = fp->fname = fname;
#if 0
fp->length = 0;
fp->colno = 1;
fp->cleanup = file_cleanup;
- if (S_ISREG (st_mode)) {
+ if (S_ISREG (st.st_mode)) {
+ st_size = (size_t) st.st_size;
+ if (st_size != st.st_size || st_size + 2 < st_size) {
+ cpp_error (pfile, "file `%s' too large", fname);
+ close (f);
+ return 0;
+ }
fp->buf = (U_CHAR *) xmalloc (st_size + 2);
fp->alimit = fp->buf + st_size + 2;
fp->cur = fp->buf;
fp->rlimit = fp->buf + length;
if (length < 0) goto nope;
}
- else if (S_ISDIR (st_mode)) {
+ else if (S_ISDIR (st.st_mode)) {
cpp_error (pfile, "directory `%s' specified in #include", fname);
close (f);
return 0;
} else {
/* Cannot count its file size before reading.
First read the entire file into heap and
- copy them into buffer on stack. */
+ copy them into buffer on stack. */
int bsize = 2000;
bsize *= 2;
fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
}
+ fp->cur = fp->buf;
length = st_size;
}
return 1;
}
+/* This is called after options have been processed.
+ * Check options for consistency, and setup for processing input
+ * from the file named FNAME. (Use standard input if FNAME==NULL.)
+ * Return 1 on success, 0 on failure.
+ */
+
int
-push_parse_file (pfile, fname)
+cpp_start_read (pfile, fname)
cpp_reader *pfile;
char *fname;
{
struct cpp_pending *pend;
char *p;
int f;
+ cpp_buffer *fp;
/* The code looks at the defaults through this pointer, rather than through
the constant structure above. This pointer gets changed if an environment
/* Now that dollars_in_ident is known, initialize is_idchar. */
initialize_char_syntax (opts);
-#if 0
/* Do partial setup of input buffer for the sake of generating
early #line directives (when -g is in effect). */
-
- fp = &instack[++indepth];
- if (in_fname == NULL)
- in_fname = "";
- fp->nominal_fname = fp->fname = in_fname;
+ fp = cpp_push_buffer (pfile, NULL, 0);
+ if (!fp)
+ return 0;
+ if (opts->in_fname == NULL)
+ opts->in_fname = "";
+ fp->nominal_fname = fp->fname = opts->in_fname;
fp->lineno = 0;
-#endif
/* Install __LINE__, etc. Must follow initialize_char_syntax
and option processing. */
*p++= 0;
if (opts->debug_output)
output_line_command (pfile, 0, same_file);
- make_definition (pfile, q);
+ cpp_define (pfile, q);
while (*p == ' ' || *p == '\t')
p++;
} else if (p[0] == '-' && p[1] == 'A') {
/* Now handle the command line options. */
/* Do -U's, -D's and -A's in the order they were seen. */
- /* First reverse the list. */
- {
- struct cpp_pending *prev = 0, *next;
- for (pend = opts->pending; pend; pend = next)
- {
- next = pend->next;
- pend->next = prev;
- prev = pend;
- }
- opts->pending = prev;
+ /* First reverse the list. */
+ opts->pending = nreverse_pending (opts->pending);
- for (pend = opts->pending; pend; pend = pend->next)
- {
- if (pend->cmd != NULL && pend->cmd[0] == '-')
- {
- switch (pend->cmd[1])
- {
- case 'U':
- if (opts->debug_output)
- output_line_command (pfile, 0, same_file);
- do_undef (pfile, NULL, pend->arg, pend->arg + strlen (pend->arg));
- break;
- case 'D':
- if (opts->debug_output)
- output_line_command (pfile, 0, same_file);
- make_definition (pfile, pend->arg);
- break;
- case 'A':
- make_assertion (pfile, "-A", pend->arg);
- break;
- }
- }
- }
- opts->pending = NULL;
- }
+ for (pend = opts->pending; pend; pend = pend->next)
+ {
+ if (pend->cmd != NULL && pend->cmd[0] == '-')
+ {
+ switch (pend->cmd[1])
+ {
+ case 'U':
+ if (opts->debug_output)
+ output_line_command (pfile, 0, same_file);
+ do_undef (pfile, NULL, pend->arg, pend->arg + strlen (pend->arg));
+ break;
+ case 'D':
+ if (opts->debug_output)
+ output_line_command (pfile, 0, same_file);
+ cpp_define (pfile, pend->arg);
+ break;
+ case 'A':
+ make_assertion (pfile, "-A", pend->arg);
+ break;
+ }
+ }
+ }
opts->done_initializing = 1;
- { /* read the appropriate environment variable and if it exists
- replace include_defaults with the listed path. */
+ { /* Read the appropriate environment variable and if it exists
+ replace include_defaults with the listed path. */
char *epath = 0;
switch ((opts->objc << 1) + opts->cplusplus)
{
nstore[endp-startp] = '\0';
include_defaults[num_dirs].fname = savestring (nstore);
+ include_defaults[num_dirs].component = 0;
include_defaults[num_dirs].cplusplus = opts->cplusplus;
include_defaults[num_dirs].cxx_aware = 1;
num_dirs++;
endp++;
}
/* Put the usual defaults back in at the end. */
- bcopy (include_defaults_array, &include_defaults[num_dirs],
+ bcopy ((char *) include_defaults_array,
+ (char *) &include_defaults[num_dirs],
sizeof (include_defaults_array));
}
}
= (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
new->control_macro = 0;
new->c_system_include_path = !p->cxx_aware;
- new->fname = p->fname;
+ new->fname = update_path (p->fname, p->component);
new->got_name_map = 0;
append_include_chain (pfile, new, new);
if (opts->first_system_include == 0)
if (fd < 0)
{
cpp_perror_with_name (pfile, pend->arg);
- return FAILURE_EXIT_CODE;
+ return 0;
}
+ if (!cpp_push_buffer (pfile, NULL, 0))
+ return 0;
finclude (pfile, fd, pend->arg, 0, NULL_PTR);
cpp_scan_buffer (pfile);
}
inhibit compilation. */
if (opts->print_deps_missing_files
&& (opts->print_deps == 0 || !opts->no_output))
- fatal (pfile, "-MG must be specified with one of -M or -MM");
+ {
+ cpp_fatal (pfile, "-MG must be specified with one of -M or -MM");
+ return 0;
+ }
/* Either of two environment variables can specify output of deps.
Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
deps_output (pfile, "-", ':');
else
{
- char *p, *q;
- int len;
+ char *p, *q, *r;
+ int len, x;
+ static char *known_suffixes[] = { ".c", ".C", ".s", ".S", ".m",
+ ".cc", ".cxx", ".cpp", ".cp",
+ ".c++", 0
+ };
/* Discard all directory prefixes from filename. */
if ((q = rindex (opts->in_fname, '/')) != NULL
/* Output P, but remove known suffixes. */
len = strlen (p);
q = p + len;
- if (len >= 2
- && p[len - 2] == '.'
- && index("cCsSm", p[len - 1]))
- q = p + (len - 2);
- else if (len >= 3
- && p[len - 3] == '.'
- && p[len - 2] == 'c'
- && p[len - 1] == 'c')
- q = p + (len - 3);
- else if (len >= 4
- && p[len - 4] == '.'
- && p[len - 3] == 'c'
- && p[len - 2] == 'x'
- && p[len - 1] == 'x')
- q = p + (len - 4);
- else if (len >= 4
- && p[len - 4] == '.'
- && p[len - 3] == 'c'
- && p[len - 2] == 'p'
- && p[len - 1] == 'p')
- q = p + (len - 4);
+ /* Point to the filename suffix. */
+ r = rindex (p, '.');
+ /* Compare against the known suffixes. */
+ x = 0;
+ while (known_suffixes[x] != 0)
+ {
+ if (strncmp (known_suffixes[x], r, q - r) == 0)
+ {
+ /* Make q point to the bit we're going to overwrite
+ with an object suffix. */
+ q = r;
+ break;
+ }
+ x++;
+ }
/* Supply our own suffix. */
#ifndef VMS
trigraph_pcp (fp);
#endif
- /* Scan the -include files before the main input. */
+ /* Scan the -include files before the main input.
+ We push these in reverse order, so that the first one is handled first. */
pfile->no_record_file++;
+ opts->pending = nreverse_pending (opts->pending);
for (pend = opts->pending; pend; pend = pend->next)
{
if (pend->cmd != NULL && strcmp (pend->cmd, "-include") == 0)
if (fd < 0)
{
cpp_perror_with_name (pfile, pend->arg);
- return FAILURE_EXIT_CODE;
+ return 0;
}
+ if (!cpp_push_buffer (pfile, NULL, 0))
+ return 0;
finclude (pfile, fd, pend->arg, 0, NULL_PTR);
- cpp_scan_buffer (pfile);
}
}
pfile->no_record_file--;
- /* Free the pending list. */
+ /* Free the pending list. */
for (pend = opts->pending; pend; )
{
struct cpp_pending *next = pend->next;
#endif
if (finclude (pfile, f, fname, 0, NULL_PTR))
output_line_command (pfile, 0, same_file);
- return SUCCESS_EXIT_CODE;
+ return 1;
}
void
-init_parse_file (pfile)
+cpp_reader_init (pfile)
cpp_reader *pfile;
{
- bzero (pfile, sizeof (cpp_reader));
+ bzero ((char *) pfile, sizeof (cpp_reader));
pfile->get_token = cpp_get_token;
pfile->token_buffer_size = 200;
- pfile->token_buffer = (char*)xmalloc (pfile->token_buffer_size);
+ pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
CPP_SET_WRITTEN (pfile, 0);
pfile->system_include_depth = 0;
pfile->buffer = CPP_NULL_BUFFER(pfile);
}
+static struct cpp_pending *
+nreverse_pending (list)
+ struct cpp_pending *list;
+
+{
+ register struct cpp_pending *prev = 0, *next, *pend;
+ for (pend = list; pend; pend = next)
+ {
+ next = pend->next;
+ pend->next = prev;
+ prev = pend;
+ }
+ return prev;
+}
+
static void
push_pending (pfile, cmd, arg)
cpp_reader *pfile;
char *arg;
{
struct cpp_pending *pend
- = (struct cpp_pending*)xmalloc (sizeof (struct cpp_pending));
+ = (struct cpp_pending *) xmalloc (sizeof (struct cpp_pending));
pend->cmd = cmd;
pend->arg = arg;
pend->next = CPP_OPTIONS (pfile)->pending;
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') {
if (opts->out_fname != NULL)
- fatal ("Usage: %s [switches] input output", argv[0]);
+ {
+ cpp_fatal (pfile, "Usage: %s [switches] input output", argv[0]);
+ return argc;
+ }
else if (opts->in_fname != NULL)
opts->out_fname = argv[i];
else
} else {
switch (argv[i][1]) {
+ missing_filename:
+ cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
+ return argc;
+ missing_dirname:
+ cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
+ return argc;
+
case 'i':
if (!strcmp (argv[i], "-include")
|| !strcmp (argv[i], "-imacros")) {
if (i + 1 == argc)
- fatal ("Filename missing after `%s' option", argv[i]);
+ goto missing_filename;
else
push_pending (pfile, argv[i], argv[i+1]), i++;
}
if (!strcmp (argv[i], "-iprefix")) {
if (i + 1 == argc)
- fatal ("Filename missing after `-iprefix' option");
+ goto missing_filename;
else
opts->include_prefix = argv[++i];
}
struct file_name_list *dirtmp;
if (i + 1 == argc)
- fatal ("Filename missing after `-isystem' option");
+ goto missing_filename;
dirtmp = (struct file_name_list *)
xmalloc (sizeof (struct file_name_list));
dirtmp->control_macro = 0;
dirtmp->c_system_include_path = 0;
if (i + 1 == argc)
- fatal ("Directory name missing after `-iwithprefix' option");
+ goto missing_dirname;
dirtmp->fname = (char *) xmalloc (strlen (argv[i+1])
+ strlen (prefix) + 1);
dirtmp->control_macro = 0;
dirtmp->c_system_include_path = 0;
if (i + 1 == argc)
- fatal ("Directory name missing after `-iwithprefixbefore' option");
+ goto missing_dirname;
dirtmp->fname = (char *) xmalloc (strlen (argv[i+1])
+ strlen (prefix) + 1);
dirtmp->control_macro = 0;
dirtmp->c_system_include_path = 0;
if (i + 1 == argc)
- fatal ("Directory name missing after `-idirafter' option");
+ goto missing_dirname;
else
dirtmp->fname = argv[++i];
dirtmp->got_name_map = 0;
case 'o':
if (opts->out_fname != NULL)
- fatal ("Output filename specified twice");
+ {
+ cpp_fatal (pfile, "Output filename specified twice");
+ return argc;
+ }
if (i + 1 == argc)
- fatal ("Filename missing after -o option");
+ goto missing_filename;
opts->out_fname = argv[++i];
if (!strcmp (opts->out_fname, "-"))
opts->out_fname = "";
#if 0
else if (!strcmp (argv[i], "-pcp")) {
char *pcp_fname = argv[++i];
- pcp_outfile =
- ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
- ? fopen (pcp_fname, "w")
- : fdopen (dup (fileno (stdout)), "w"));
+ pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
+ ? fopen (pcp_fname, "w")
+ : fdopen (dup (fileno (stdout)), "w"));
if (pcp_outfile == 0)
cpp_pfatal_with_name (pfile, pcp_fname);
no_precomp = 1;
case 't':
if (!strcmp (argv[i], "-traditional")) {
opts->traditional = 1;
- if (opts->dollars_in_ident > 0)
- opts->dollars_in_ident = 1;
} else if (!strcmp (argv[i], "-trigraphs")) {
if (!opts->chill)
opts->no_trigraphs = 0;
case 'l':
if (! strcmp (argv[i], "-lang-c"))
- opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->objc = 0;
+ opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->objc = 0;
+ if (! strcmp (argv[i], "-lang-c89"))
+ opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->c89 = 1,
+ opts->objc = 0;
if (! strcmp (argv[i], "-lang-c++"))
- opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->objc = 0;
- if (! strcmp (argv[i], "-lang-c-c++-comments"))
- opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->objc = 0;
+ opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->objc = 0;
if (! strcmp (argv[i], "-lang-objc"))
- opts->objc = 1, opts->cplusplus = 0, opts->cplusplus_comments = 1;
+ opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->objc = 1;
if (! strcmp (argv[i], "-lang-objc++"))
- opts->objc = 1, opts->cplusplus = 1, opts->cplusplus_comments = 1;
+ opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->objc = 1;
if (! strcmp (argv[i], "-lang-asm"))
opts->lang_asm = 1;
if (! strcmp (argv[i], "-lint"))
opts->warn_stringify = 1;
else if (!strcmp (argv[i], "-Wno-traditional"))
opts->warn_stringify = 0;
+ else if (!strcmp (argv[i], "-Wundef"))
+ opts->warn_undef = 1;
+ else if (!strcmp (argv[i], "-Wno-undef"))
+ opts->warn_undef = 0;
else if (!strcmp (argv[i], "-Wimport"))
opts->warn_import = 1;
else if (!strcmp (argv[i], "-Wno-import"))
if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
{
if (i+1 == argc)
- fatal ("Filename missing after %s option", argv[i]);
+ goto missing_filename;
opts->deps_file = argv[++i];
}
else
case 'D':
opts->dump_macros = dump_definitions;
break;
+ case 'I':
+ opts->dump_includes = 1;
+ break;
}
}
}
if (argv[i][2] != 0)
push_pending (pfile, "-D", argv[i] + 2);
else if (i + 1 == argc)
- fatal ("Macro name missing after -D option");
+ {
+ cpp_fatal (pfile, "Macro name missing after -D option");
+ return argc;
+ }
else
i++, push_pending (pfile, "-D", argv[i]);
break;
if (argv[i][2] != 0)
p = argv[i] + 2;
else if (i + 1 == argc)
- fatal ("Assertion missing after -A option");
+ {
+ cpp_fatal (pfile, "Assertion missing after -A option");
+ return argc;
+ }
else
p = argv[++i];
if (argv[i][2] != 0)
push_pending (pfile, "-U", argv[i] + 2);
else if (i + 1 == argc)
- fatal ("Macro name missing after -U option");
+ {
+ cpp_fatal (pfile, "Macro name missing after -U option", NULL);
+ return argc;
+ }
else
push_pending (pfile, "-U", argv[i+1]), i++;
break;
if (argv[i][2] != 0)
dirtmp->fname = argv[i] + 2;
else if (i + 1 == argc)
- fatal ("Directory name missing after -I option");
+ goto missing_dirname;
else
dirtmp->fname = argv[++i];
dirtmp->got_name_map = 0;
#endif
break;
+ case 'r':
+ if (!strcmp (argv[i], "-remap"))
+ opts->remap = 1;
+ break;
+
case 'u':
/* Sun compiler passes undocumented switch "-undef".
Let's assume it means to inhibit the predefined symbols. */
if (opts->deps_file)
{
if (ferror (deps_stream) || fclose (deps_stream) != 0)
- fatal ("I/O error on output");
+ cpp_fatal (pfile, "I/O error on output");
}
}
}
}
+
+/* Free resources used by PFILE.
+ This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology). */
+
+void
+cpp_cleanup (pfile)
+ cpp_reader *pfile;
+{
+ int i;
+ while ( CPP_BUFFER (pfile) != CPP_NULL_BUFFER (pfile))
+ cpp_pop_buffer (pfile);
+
+ if (pfile->token_buffer)
+ {
+ free (pfile->token_buffer);
+ pfile->token_buffer = NULL;
+ }
+
+ if (pfile->deps_buffer)
+ {
+ free (pfile->deps_buffer);
+ pfile->deps_buffer = NULL;
+ pfile->deps_allocated_size = 0;
+ }
+
+ while (pfile->if_stack)
+ {
+ IF_STACK_FRAME *temp = pfile->if_stack;
+ pfile->if_stack = temp->next;
+ free (temp);
+ }
+
+ while (pfile->dont_repeat_files)
+ {
+ struct file_name_list *temp = pfile->dont_repeat_files;
+ pfile->dont_repeat_files = temp->next;
+ free (temp->fname);
+ free (temp);
+ }
+
+ while (pfile->all_include_files)
+ {
+ struct file_name_list *temp = pfile->all_include_files;
+ pfile->all_include_files = temp->next;
+ free (temp->fname);
+ free (temp);
+ }
+
+ for (i = IMPORT_HASH_SIZE; --i >= 0; )
+ {
+ register struct import_file *imp = pfile->import_hash_table[i];
+ while (imp)
+ {
+ struct import_file *next = imp->next;
+ free (imp->name);
+ free (imp);
+ imp = next;
+ }
+ pfile->import_hash_table[i] = 0;
+ }
+
+ for (i = ASSERTION_HASHSIZE; --i >= 0; )
+ {
+ while (pfile->assertion_hashtab[i])
+ delete_assertion (pfile->assertion_hashtab[i]);
+ }
+
+ cpp_hash_cleanup (pfile);
+}
\f
static int
do_assert (pfile, keyword, buf, limit)
/* If no token list was specified, then eliminate this assertion
entirely. */
- if (! tokens_specified) {
- struct tokenlist_list *next;
- for (tail = hp->value; tail; tail = next) {
- next = tail->next;
- free_token_list (tail->tokens);
- free (tail);
- }
+ if (! tokens_specified)
delete_assertion (hp);
- } else {
+ else {
/* If a list of tokens was given, then delete any matching list. */
tail = hp->value;
}
}
\f
-/* Get the file-mode and data size of the file open on FD
- and store them in *MODE_POINTER and *SIZE_POINTER. */
-
-static int
-file_size_and_mode (fd, mode_pointer, size_pointer)
- int fd;
- int *mode_pointer;
- long int *size_pointer;
-{
- struct stat sbuf;
-
- if (fstat (fd, &sbuf) < 0) return (-1);
- if (mode_pointer) *mode_pointer = sbuf.st_mode;
- if (size_pointer) *size_pointer = sbuf.st_size;
- return 0;
-}
-
/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
- retrying if necessary. Return a negative value if an error occurs,
+ retrying if necessary. If MAX_READ_LEN is defined, read at most
+ that bytes at a time. Return a negative value if an error occurs,
otherwise return the actual number of bytes read,
which must be LEN unless end-of-file was reached. */
char *ptr;
int len;
{
- int left = len;
+ int left, rcount, nchars;
+
+ left = len;
while (left > 0) {
- int nchars = read (desc, ptr, left);
+ rcount = left;
+#ifdef MAX_READ_LEN
+ if (rcount > MAX_READ_LEN)
+ rcount = MAX_READ_LEN;
+#endif
+ nchars = read (desc, ptr, rcount);
if (nchars < 0)
{
#ifdef EINTR
}
static char *
+xcalloc (number, size)
+ unsigned number, size;
+{
+ register unsigned total = number * size;
+ register char *ptr = (char *) xmalloc (total);
+ bzero (ptr, total);
+ return ptr;
+}
+
+static char *
savestring (input)
char *input;
{
return output;
}
\f
-/* Return the line at which an error occurred.
- The error is not necessarily associated with the current spot
- in the input stack, so LINE says where. LINE will have been
- copied from ip->lineno for the current input level.
- If the current level is for a file, we return LINE.
- But if the current level is not for a file, LINE is meaningless.
- In that case, we return the lineno of the innermost file. */
+/* Initialize PMARK to remember the current position of PFILE. */
-static int
-line_for_error (line)
- int line;
-{
-#if 0
- int i;
- int line1 = line;
-
- for (i = indepth; i >= 0; ) {
- if (instack[i].fname != 0)
- return line1;
- i--;
- if (i < 0)
- return 0;
- line1 = instack[i].lineno;
- }
- abort ();
- /*NOTREACHED*/
-#endif
- return 0;
-}
-\f
-/* Initialize PMARK to remember the current position of PFILE. */
void
parse_set_mark (pmark, pfile)
struct parse_marker *pmark;
pmark->position = pbuf->cur - pbuf->buf;
}
-/* Cleanup PMARK - we no longer need it. */
+/* Cleanup PMARK - we no longer need it. */
+
void
parse_clear_mark (pmark)
struct parse_marker *pmark;
{
struct parse_marker **pp = &pmark->buf->marks;
for (; ; pp = &(*pp)->next) {
- if (*pp == NULL) fatal ("internal error", "in parse_set_mark");
+ if (*pp == NULL) abort ();
if (*pp == pmark) break;
}
*pp = pmark->next;
}
-/* Backup the current position of PFILE to that saved in PMARK. */
+/* Backup the current position of PFILE to that saved in PMARK. */
void
parse_goto_mark (pmark, pfile)
{
cpp_buffer *pbuf = CPP_BUFFER (pfile);
if (pbuf != pmark->buf)
- fatal ("internal error %s", "parse_goto_mark");
+ cpp_fatal (pfile, "internal error %s", "parse_goto_mark");
pbuf->cur = pbuf->buf + pmark->position;
}
/* Reset PMARK to point to the current position of PFILE. (Same
- as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster. */
+ as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster. */
void
parse_move_mark (pmark, pfile)
{
cpp_buffer *pbuf = CPP_BUFFER (pfile);
if (pbuf != pmark->buf)
- fatal ("internal error %s", "parse_move_mark");
+ cpp_fatal (pfile, "internal error %s", "parse_move_mark");
pmark->position = pbuf->cur - pbuf->buf;
}
}
void
-cpp_error_with_line (pfile, line, msg, arg1, arg2, arg3)
+cpp_error_with_line (pfile, line, column, msg, arg1, arg2, arg3)
cpp_reader *pfile;
- int line;
+ int line, column;
char *msg;
char *arg1, *arg2, *arg3;
{
cpp_print_containing_files (pfile);
if (ip != NULL)
- cpp_file_line_for_message (pfile, ip->nominal_fname, line, -1);
+ cpp_file_line_for_message (pfile, ip->nominal_fname, line, column);
cpp_message (pfile, 1, msg, arg1, arg2, arg3);
}
-void
-cpp_warning_with_line (pfile, line, msg, arg1, arg2, arg3)
+static void
+cpp_warning_with_line (pfile, line, column, msg, arg1, arg2, arg3)
cpp_reader *pfile;
- int line;
+ int line, column;
char *msg;
char *arg1, *arg2, *arg3;
{
ip = cpp_file_buffer (pfile);
if (ip != NULL)
- cpp_file_line_for_message (pfile, ip->nominal_fname, line, -1);
+ cpp_file_line_for_message (pfile, ip->nominal_fname, line, column);
cpp_message (pfile, 0, msg, arg1, arg2, arg3);
}
void
-cpp_pedwarn_with_line (pfile, line, msg, arg1, arg2, arg3)
+cpp_pedwarn_with_line (pfile, line, column, msg, arg1, arg2, arg3)
cpp_reader *pfile;
int line;
char *msg;
char *arg1, *arg2, *arg3;
{
if (CPP_OPTIONS (pfile)->pedantic_errors)
- cpp_error_with_line (pfile, line, msg, arg1, arg2, arg3);
+ cpp_error_with_line (pfile, column, line, msg, arg1, arg2, arg3);
else
- cpp_warning_with_line (pfile, line, msg, arg1, arg2, arg3);
+ cpp_warning_with_line (pfile, line, column, msg, arg1, arg2, arg3);
}
/* Report a warning (or an error if pedantic_errors)
msg, arg1, arg2, arg3);
}
-/* This defines "errno" properly for VMS, and gives us EACCES. */
+/* This defines "errno" properly for VMS, and gives us EACCES. */
#include <errno.h>
#ifndef errno
extern int errno;
#ifndef VMS
#ifndef HAVE_STRERROR
extern int sys_nerr;
-#if defined(bsd4_4)
-extern const char *const sys_errlist[];
-#else
extern char *sys_errlist[];
-#endif
-#else /* HAVE_STERRROR */
+#else /* HAVE_STRERROR */
char *strerror ();
#endif
#else /* VMS */
char *strerror (int,...);
#endif
-/*
- * my_strerror - return the descriptive text associated with an `errno' code.
- */
+/* my_strerror - return the descriptive text associated with an
+ `errno' code. */
char *
my_strerror (errnum)
if (ip != NULL)
cpp_file_line_for_message (pfile, ip->nominal_fname, ip->lineno, -1);
- cpp_message (pfile, 1, "%s: %s\n", name, my_strerror (errno));
+ cpp_message (pfile, 1, "%s: %s", name, my_strerror (errno));
}
void
cpp_reader *pfile;
char *name;
{
- cpp_message (pfile, 1, "%s: %s: %s\n", progname, name, my_strerror (errno));
+ cpp_message (pfile, 1, "%s: %s: %s", progname, name, my_strerror (errno));
}
/* TODO:
*
* Possibly different enum token codes for each C/C++ token.
*
- * Better error messages for non-terminated strings and comments.
- *
* Should clean up remaining directives to that do_XXX functions
* only take two arguments and all have command_reads_line.
*
*
* Support -dM flag (dump_all_macros).
*
- * -include should be made to return results incrementally.
- * (current implementation only works when cpp is used as main program)
- *
+ * Support for_lint flag.
*/