#include "config.h"
#include "system.h"
#include <signal.h>
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
#endif
typedef unsigned char U_CHAR;
#include "pcp.h"
#include "intl.h"
#include "prefix.h"
#include "genindex.h"
int c_language = -1;
#ifdef MULTIBYTE_CHARS
#include "mbchar.h"
#include <locale.h>
#endif
#ifndef GET_ENV_PATH_LIST
#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
#ifndef STANDARD_INCLUDE_DIR
# define STANDARD_INCLUDE_DIR "/usr/include"
#endif
#ifndef PATH_SEPARATOR
# define PATH_SEPARATOR ':'
#endif
#ifndef DIR_SEPARATOR
# define DIR_SEPARATOR '/'
#endif
#ifdef REPORT_EVENT
#include <stdarg.h>
#include "apple/make-support.h"
#endif
#ifdef OBJECT_SUFFIX
# define HAVE_OBJECT_SUFFIX
#else
# define OBJECT_SUFFIX ".o"
#endif
#ifdef ENABLE_NEWLINE_MAPPING
int flag_map_newline_to_cr;
#endif
#ifdef VMS
#include <descrip.h>
#include <ssdef.h>
#include <syidef.h>
#define open(fname,mode,prot) VMS_open (fname,mode,prot)
#define fopen(fname,mode) VMS_fopen (fname,mode)
#define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
#define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
static int VMS_fstat (), VMS_stat ();
static int VMS_open ();
static FILE *VMS_fopen ();
static FILE *VMS_freopen ();
static int hack_vms_include_specification ();
#define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
#define INO_T_HASH(a) 0
#define INCLUDE_LEN_FUDGE 12
#endif
#if (defined (_WIN32) && ! defined (__CYGWIN__) && ! defined (_UWIN)) \
|| defined (__MSDOS__)
#define INO_T_EQ(a, b) 0
#endif
#ifndef INO_T_EQ
#define INO_T_EQ(a, b) ((a) == (b))
#endif
#ifndef INO_T_HASH
#define INO_T_HASH(a) (a)
#endif
#ifndef INCLUDE_LEN_FUDGE
#define INCLUDE_LEN_FUDGE 0
#endif
extern char *version_string;
HOST_WIDEST_INT parse_escape PROTO((char **, HOST_WIDEST_INT));
HOST_WIDEST_INT parse_c_expression PROTO((char *, int));
static char *progname;
static int cplusplus;
static int cplusplus_comments;
static int objc;
static int lang_asm;
static int max_include_len;
static int for_lint = 0;
static int put_out_comments = 0;
static int no_trigraphs = 0;
static int print_deps = 0;
static int print_deps_missing_files = 0;
static int print_include_names = 0;
static int no_line_directives;
static int output_conditionals;
static enum {dump_none, dump_only, dump_names, dump_definitions}
dump_macros = dump_none;
static int debug_output = 0;
static int dump_includes;
static FILE *pcp_outfile;
static int pcp_inside_if;
static int no_precomp = 1;
int pedantic;
static int pedantic_errors;
static int inhibit_warnings = 0;
static int warn_comments;
static int warn_stringify;
static int warn_trigraphs;
static int warn_undef;
#ifdef NEXT_OBJC_RUNTIME
static int warn_import = 0;
#else
static int warn_import = 1;
#endif
static int warnings_are_errors;
int traditional;
int c89;
int c9x;
static int no_output;
static int remap;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
static int warn_pragma_once;
#ifdef NEXT_SEMANTICS
static int no_rtf = 0;
#endif
#endif
static int no_record_file;
static int done_initializing = 0;
static int multiline_string_line = 0;
#ifdef APPLE_CPP_HEADER_MAPS
static struct hmap_header_map * header_map = NULL;
#endif
#ifdef APPLE_CPP_INCLUSION_LOGS
static unsigned num_opens = 0;
static unsigned num_stats = 0;
static FILE * inclusion_log_file = NULL;
#endif
#define INPUT_STACK_MAX 400
static struct file_buf {
char *fname;
char *nominal_fname;
size_t nominal_fname_len;
struct include_file *inc;
struct file_name_list *dir;
#ifdef NEXT_CPP_SERVER
struct file_name_list *file;
U_CHAR *beg_of_line;
U_CHAR *output_written_to;
#endif
int lineno;
int length;
U_CHAR *buf;
U_CHAR *bufp;
struct hashnode *macro;
struct if_stack *if_stack;
U_CHAR *free_ptr;
char system_header_p;
} instack[INPUT_STACK_MAX];
static int last_error_tick;
static int input_file_stack_tick;
static int indepth = -1;
#define CHECK_DEPTH(code) \
if (indepth >= (INPUT_STACK_MAX - 1)) \
{ \
error_with_line (line_for_error (instack[indepth].lineno), \
"macro or `#include' recursion too deep"); \
code; \
}
static int system_include_depth = 0;
typedef struct file_buf FILE_BUF;
#define OUTBUF_SIZE 10
static FILE_BUF outbuf;
#define check_expand(OBUF, NEEDED) \
(((OBUF)->length - ((OBUF)->bufp - (OBUF)->buf) <= (NEEDED)) \
? grow_outbuf ((OBUF), (NEEDED)) : 0)
#ifdef NEXT_CPP_SERVER
#if !defined (NEXT_PDO) || defined (_WIN32)
#include <sys/dir.h>
#endif
#include <string.h>
#include <sys/fcntl.h>
static int segregate_output = 0;
static int mark_expansions = 0;
static int serverized = 0;
static int timings = 0;
static int outbuf_stat_info_recorded = 0;
static FILE_BUF sys_header_outbuf;
static FILE_BUF user_header_outbuf;
static struct hashnode *free_undefined_macros = 0;
static struct file_name_list *all_input_files = 0;
static struct file_name_list *all_output_files = 0;
static void add_to_negative_cache ();
static int found_in_negative_cache ();
static void add_version_of_header ();
static int duplicate_version_of_header ();
static int aggressive_skip_if_group ();
static void dump_memory_statistics ();
static void clear_import ();
static void clear_all_macros();
static void enable_macros_from_header();
static void init_output_file_buf();
static void start();
static void stop();
static void display(FILE * strm, int addNewLine);
#define IMPORT_HASH_SIZE 1403
static struct import_file *import_hash_table[IMPORT_HASH_SIZE];
static int import_hash ();
#endif
struct file_name_list
{
struct file_name_list *next;
int c_system_include_path;
struct file_name_map *name_map;
int got_name_map;
struct stat st;
#ifdef NEXT_CPP_SERVER
int length;
U_CHAR *buf;
int header_output;
int has_explicit_context_dependency;
int ever_included;
int macro_count;
int macro_index;
struct hashnode **macro_list;
U_CHAR *position_after_last_include;
U_CHAR *position_of_first_ifndef;
U_CHAR *position_of_last_endif;
unsigned int relative_position_of_file_start;
unsigned int file_length;
struct file_name_list *versions;
#endif
char fname[1];
};
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
#endif
static struct default_include {
char *fname;
char *component;
int cplusplus;
int cxx_aware;
int included;
} include_defaults_array[]
#ifdef INCLUDE_DEFAULTS
= INCLUDE_DEFAULTS;
#else
= {
#ifdef LOCAL_GPLUSPLUS_INCLUDE_DIR
{ LOCAL_GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0 },
#endif
{ GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, 0 },
#ifdef CROSS_COMPILE
#ifdef LOCAL_CROSS_INCLUDE_DIR
{ LOCAL_CROSS_INCLUDE_DIR, 0, 0, 1, 0 },
#endif
{ GCC_INCLUDE_DIR, "GCC", 0, 0, 0 },
{ CROSS_INCLUDE_DIR, "GCC", 0, 0, 0 },
#ifdef TOOL_INCLUDE_DIR
{ TOOL_INCLUDE_DIR, "BINUTILS", 0, 0, 0 },
#endif
#else
#ifdef LOCAL_INCLUDE_DIR
{ LOCAL_INCLUDE_DIR, 0, 0, 1, 0 },
#endif
#ifdef TOOL_INCLUDE_DIR
{ TOOL_INCLUDE_DIR, "BINUTILS", 0, 0, 0 },
#endif
{ GCC_INCLUDE_DIR, "GCC", 0, 0, 0 },
#ifdef SYSTEM_INCLUDE_DIR
{ SYSTEM_INCLUDE_DIR, 0, 0, 0, 0 },
#endif
#ifndef STANDARD_INCLUDE_COMPONENT
#define STANDARD_INCLUDE_COMPONENT 0
#endif
{ STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 0 },
#endif
{ 0, 0, 0, 0, 0 }
};
#endif
#ifdef NEXT_FRAMEWORKS
static struct default_include framework_defaults_array [] = {
#ifdef OPENSTEP
{"/LocalLibrary/Frameworks", 0, 0},
{"/NextLibrary/Frameworks", 0, 0},
#elif defined(MACOSX)
{"/Library/Frameworks", 0, 0},
{"/System/Library/Frameworks", 0, 0},
#else
{"/Local/Library/Frameworks", 0, 0},
#ifdef NEXT_PDO
{"/Library/Frameworks", 0},
#else
{"/System/Library/Frameworks", 0, 0},
#endif
#endif
{NULL, 0, 0}
};
static struct default_include *framework_defaults=framework_defaults_array;
static struct file_name_list *framework = 0;
struct framework_header {char * dirName; int dirNameLen; };
static struct framework_header framework_header_dirs[] = {
{ "PrivateHeaders", 14 },
{ "Headers", 7 },
{ NULL, 0 }
};
#endif
static struct default_include *include_defaults = include_defaults_array;
static struct file_name_list *include = 0;
static struct file_name_list *first_bracket_include = 0;
#ifdef NEXT_FRAMEWORKS
static struct file_name_list *first_bracket_framework = 0;
#endif
static struct file_name_list *first_system_include = 0;
static struct file_name_list *last_include = 0;
#ifdef NEXT_FRAMEWORKS
static struct file_name_list *last_framework = 0;
#endif
static struct file_name_list *after_include = 0;
static struct file_name_list *last_after_include = 0;
static struct file_name_list *before_system = 0;
static struct file_name_list *last_before_system = 0;
static char *include_prefix;
struct include_file {
struct include_file *next;
struct include_file *next_ino;
char *fname;
U_CHAR *control_macro;
int deps_output;
struct stat st;
};
#define INCLUDE_HASHSIZE 61
static struct include_file *include_hashtab[INCLUDE_HASHSIZE];
static struct include_file *include_ino_hashtab[INCLUDE_HASHSIZE];
static STRINGDEF *stringlist;
static STRINGDEF **stringlist_tailp = &stringlist;
typedef struct macrodef MACRODEF;
struct macrodef
{
struct definition *defn;
U_CHAR *symnam;
int symlen;
};
enum sharp_token_type {
NO_SHARP_TOKEN = 0,
SHARP_TOKEN = '#',
WHITE_SHARP_TOKEN,
PERCENT_COLON_TOKEN = '%',
WHITE_PERCENT_COLON_TOKEN
};
typedef struct definition DEFINITION;
struct definition {
int nargs;
int length;
int predefined;
U_CHAR *expansion;
int line;
char *file;
size_t file_len;
char rest_args;
struct reflist {
struct reflist *next;
enum sharp_token_type stringify;
enum sharp_token_type raw_before;
enum sharp_token_type raw_after;
char rest_args;
int nchars;
int argno;
} *pattern;
union {
U_CHAR *argnames;
} args;
};
union hashval {
char *cpval;
DEFINITION *defn;
KEYDEF *keydef;
};
static char rest_extension[] = "...";
#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)
static char va_args_name[] = "__VA_ARGS__";
#define VA_ARGS_NAME_LENGTH (sizeof (va_args_name) - 1)
enum node_type {
T_DEFINE = 1,
T_INCLUDE,
T_INCLUDE_NEXT,
T_IMPORT,
T_IFDEF,
T_IFNDEF,
T_IF,
T_ELSE,
T_PRAGMA,
T_ELIF,
T_UNDEF,
T_LINE,
T_ERROR,
T_WARNING,
T_ENDIF,
T_SCCS,
T_IDENT,
T_ASSERT,
T_UNASSERT,
T_SPECLINE,
T_DATE,
T_FILE,
T_BASE_FILE,
T_INCLUDE_LEVEL,
T_VERSION,
T_SIZE_TYPE,
T_PTRDIFF_TYPE,
T_WCHAR_TYPE,
T_USER_LABEL_PREFIX_TYPE,
T_REGISTER_PREFIX_TYPE,
T_IMMEDIATE_PREFIX_TYPE,
T_TIME,
T_CONST,
T_MACRO,
T_DISABLED,
T_SPEC_DEFINED,
#ifdef APPLE_EXTENSION
T_SPEC_OPTION,
#endif
T_PCSTRING,
T_UNUSED
};
struct hashnode {
struct hashnode *next;
struct hashnode *prev;
struct hashnode **bucket_hdr;
enum node_type type;
int length;
U_CHAR *name;
union hashval value;
#ifdef NEXT_CPP_SERVER
int defined_within_module;
struct file_name_list *owner;
#endif
};
typedef struct hashnode HASHNODE;
#define HASHSIZE 1403
static HASHNODE *hashtab[HASHSIZE];
#define HASHSTEP(old, c) ((old << 2) + c)
#define MAKE_POS(v) (v & 0x7fffffff)
#ifndef SIZE_TYPE
#define SIZE_TYPE "long unsigned int"
#endif
#ifndef PTRDIFF_TYPE
#define PTRDIFF_TYPE "long int"
#endif
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
char * wchar_type = WCHAR_TYPE;
#undef WCHAR_TYPE
#ifndef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
#endif
char * user_label_prefix = USER_LABEL_PREFIX;
#undef USER_LABEL_PREFIX
#ifndef REGISTER_PREFIX
#define REGISTER_PREFIX ""
#endif
#ifndef IMMEDIATE_PREFIX
#define IMMEDIATE_PREFIX ""
#endif
struct tokenlist_list {
struct tokenlist_list *next;
struct arglist *tokens;
};
struct assertion_hashnode {
struct assertion_hashnode *next;
struct assertion_hashnode *prev;
struct assertion_hashnode **bucket_hdr;
int length;
U_CHAR *name;
struct tokenlist_list *value;
};
typedef struct assertion_hashnode ASSERTION_HASHNODE;
#define ASSERTION_HASHSIZE 37
static ASSERTION_HASHNODE *assertion_hashtab[ASSERTION_HASHSIZE];
static int assertions_flag;
#define DO_PROTO PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *))
struct directive {
int length;
int (*func) DO_PROTO;
char *name;
enum node_type type;
};
#define IS_INCLUDE_DIRECTIVE_TYPE(t) \
((int) T_INCLUDE <= (int) (t) && (int) (t) <= (int) T_IMPORT)
static int do_assert DO_PROTO;
static int do_define DO_PROTO;
static int do_elif DO_PROTO;
static int do_else DO_PROTO;
static int do_endif DO_PROTO;
static int do_error DO_PROTO;
static int do_ident DO_PROTO;
static int do_if DO_PROTO;
static int do_include DO_PROTO;
static int do_line DO_PROTO;
static int do_pragma DO_PROTO;
#ifdef SCCS_DIRECTIVE
static int do_sccs DO_PROTO;
#endif
static int do_unassert DO_PROTO;
static int do_undef DO_PROTO;
static int do_warning DO_PROTO;
static int do_xifdef DO_PROTO;
static struct directive directive_table[] = {
{ 6, do_define, "define", T_DEFINE},
{ 2, do_if, "if", T_IF},
{ 5, do_xifdef, "ifdef", T_IFDEF},
{ 6, do_xifdef, "ifndef", T_IFNDEF},
{ 5, do_endif, "endif", T_ENDIF},
{ 4, do_else, "else", T_ELSE},
{ 4, do_elif, "elif", T_ELIF},
{ 4, do_line, "line", T_LINE},
{ 7, do_include, "include", T_INCLUDE},
{ 12, do_include, "include_next", T_INCLUDE_NEXT},
{ 6, do_include, "import", T_IMPORT},
{ 5, do_undef, "undef", T_UNDEF},
{ 5, do_error, "error", T_ERROR},
{ 7, do_warning, "warning", T_WARNING},
#ifdef SCCS_DIRECTIVE
{ 4, do_sccs, "sccs", T_SCCS},
#endif
{ 6, do_pragma, "pragma", T_PRAGMA},
{ 5, do_ident, "ident", T_IDENT},
{ 6, do_assert, "assert", T_ASSERT},
{ 8, do_unassert, "unassert", T_UNASSERT},
{ -1, 0, "", T_UNUSED},
};
U_CHAR *directive_start;
U_CHAR is_idchar[256];
U_CHAR is_idstart[256];
static U_CHAR is_hor_space[256];
U_CHAR is_space[256];
#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
static int errors = 0;
static char *out_fname;
static int ignore_escape_flag = 1;
struct if_stack {
struct if_stack *next;
char *fname;
size_t fname_len;
int lineno;
int if_succeeded;
U_CHAR *control_macro;
enum node_type type;
};
typedef struct if_stack IF_STACK_FRAME;
static IF_STACK_FRAME *if_stack = NULL;
static char *deps_buffer;
static int deps_allocated_size;
static int deps_size;
static int deps_column;
static int ignore_srcdir;
static int safe_read PROTO((int, char *, int));
static void safe_write PROTO((int, char *, int));
static void eprint_string PROTO((const char *, size_t));
int main PROTO((int, char **));
static void path_include PROTO((char *));
static U_CHAR *index0 PROTO((U_CHAR *, int, size_t));
static void trigraph_pcp PROTO((FILE_BUF *));
static void newline_fix PROTO((U_CHAR *));
static void name_newline_fix PROTO((U_CHAR *));
static char *get_lintcmd PROTO((U_CHAR *, U_CHAR *, U_CHAR **, int *, int *));
static void rescan PROTO((FILE_BUF *, int));
static FILE_BUF expand_to_temp_buffer PROTO((U_CHAR *, U_CHAR *, int, int));
static int handle_directive PROTO((FILE_BUF *, FILE_BUF *));
static struct tm *timestamp PROTO((void));
static void special_symbol PROTO((HASHNODE *, FILE_BUF *));
static int is_system_include PROTO((char *));
static char *base_name PROTO((char *));
static int absolute_filename PROTO((char *));
static size_t simplify_filename PROTO((char *));
static char *read_filename_string PROTO((int, FILE *));
static struct file_name_map *read_name_map PROTO((char *));
static int open_include_file PROTO((char *, struct file_name_list *, U_CHAR *, struct include_file **));
static char *remap_include_file PROTO((char *, struct file_name_list *));
static int lookup_ino_include PROTO((struct include_file *));
static void finclude PROTO((int, struct include_file *, FILE_BUF *, int, struct file_name_list *));
static void record_control_macro PROTO((struct include_file *, U_CHAR *));
static char *check_precompiled PROTO((int, struct stat *, char *, char **));
static int check_preconditions PROTO((char *));
static void pcfinclude PROTO((U_CHAR *, U_CHAR *, FILE_BUF *));
static void pcstring_used PROTO((HASHNODE *));
static void write_output PROTO((const char *));
#ifdef NEXT_CPP_SERVER
static int write_header_output ();
static time_t file_modtime ();
static void handle_file_modification();
#endif
static void pass_thru_directive PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *));
static MACRODEF create_definition PROTO((U_CHAR *, U_CHAR *, FILE_BUF *));
static int check_macro_name PROTO((U_CHAR *, int));
static int compare_defs PROTO((DEFINITION *, DEFINITION *));
static int comp_def_part PROTO((int, U_CHAR *, int, U_CHAR *, int, int));
static DEFINITION *collect_expansion PROTO((U_CHAR *, U_CHAR *, int, struct arglist *));
#ifdef APPLE_EXTENSION
static int check__option PROTO((U_CHAR *, int));
#endif
int check_assertion PROTO((U_CHAR *, int, int, struct arglist *));
static int compare_token_lists PROTO((struct arglist *, struct arglist *));
static struct arglist *read_token_list PROTO((U_CHAR **, U_CHAR *, int *));
static void free_token_list PROTO((struct arglist *));
static ASSERTION_HASHNODE *assertion_install PROTO((U_CHAR *, int, int));
static ASSERTION_HASHNODE *assertion_lookup PROTO((U_CHAR *, int, int));
static void delete_assertion PROTO((ASSERTION_HASHNODE *));
static void do_once PROTO((void));
static HOST_WIDEST_INT eval_if_expression PROTO((U_CHAR *, int));
static void conditional_skip PROTO((FILE_BUF *, int, enum node_type, U_CHAR *, FILE_BUF *));
static void skip_if_group PROTO((FILE_BUF *, int, FILE_BUF *));
static void validate_else PROTO((U_CHAR *, U_CHAR *));
static U_CHAR *skip_to_end_of_comment PROTO((FILE_BUF *, int *, int));
static U_CHAR *skip_quoted_string PROTO((U_CHAR *, U_CHAR *, int, int *, int *, int *));
static char *quote_string PROTO((char *, char *, size_t));
static U_CHAR *skip_paren_group PROTO((FILE_BUF *));
enum file_change_code {same_file, enter_file, leave_file
#ifdef NEXT_CPP_SERVER
, enter_expansion, leave_expansion
#endif
};
static void output_line_directive PROTO((FILE_BUF *, FILE_BUF *, int, enum file_change_code));
static void macroexpand PROTO((HASHNODE *, FILE_BUF *));
#ifdef NEXT_SEMANTICS
static void buf_convert_rtf ();
static const char * rtf_to_ascii ();
#endif
struct argdata;
static int macarg PROTO((struct argdata *, int));
static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, struct hashnode *, int *, int *, int *, int));
static int discard_comments PROTO((U_CHAR *, int, int));
static int change_newlines PROTO((U_CHAR *, int));
static char *my_strerror PROTO((int));
static void notice PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
static void vnotice PROTO((const char *, va_list));
void error PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
void verror PROTO((const char *, va_list));
static void error_from_errno PROTO((char *));
void warning PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
static void vwarning PROTO((const char *, va_list));
static void error_with_line PVPROTO((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
static void verror_with_line PROTO((int, const char *, va_list));
static void vwarning_with_line PROTO((int, const char *, va_list));
static void warning_with_line PVPROTO((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
void pedwarn PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
void pedwarn_with_line PVPROTO((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
static void pedwarn_with_file_and_line PVPROTO((const char *, size_t, int, const char *, ...)) ATTRIBUTE_PRINTF_4;
static void pedwarn_strange_white_space PROTO((int));
static void print_containing_files PROTO((void));
static int line_for_error PROTO((int));
static int grow_outbuf PROTO((FILE_BUF *, int));
static HASHNODE *install PROTO((U_CHAR *, int, enum node_type, char *, int));
HASHNODE *lookup PROTO((U_CHAR *, int, int));
static void delete_macro PROTO((HASHNODE *));
static int hashf PROTO((U_CHAR *, int, int));
static void dump_single_macro PROTO((HASHNODE *, FILE *));
static void dump_all_macros PROTO((void));
static void dump_defn_1 PROTO((U_CHAR *, int, int, FILE *));
static void dump_arg_n PROTO((DEFINITION *, int, FILE *));
static void initialize_char_syntax PROTO((void));
static void initialize_builtins PROTO((FILE_BUF *, FILE_BUF *));
static void make_definition PROTO((char *));
static void make_undef PROTO((char *, FILE_BUF *));
static void make_assertion PROTO((const char *, const char *));
static struct file_name_list *new_include_prefix PROTO((struct file_name_list *, const char *, const char *, const char *));
static void append_include_chain PROTO((struct file_name_list *, struct file_name_list *));
#ifdef NEXT_FRAMEWORKS
static void append_framework_chain ();
static char *savestring ();
#endif
static int quote_string_for_make PROTO((char *, const char *));
static void deps_output PROTO((const char *, int));
void fatal PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
void fancy_abort PROTO((void)) ATTRIBUTE_NORETURN;
static void perror_with_name PROTO((char *));
static void pfatal_with_name PROTO((char *)) ATTRIBUTE_NORETURN;
static void pipe_closed PROTO((int)) ATTRIBUTE_NORETURN;
static void memory_full PROTO((void)) ATTRIBUTE_NORETURN;
static void print_help PROTO((void));
#ifdef APPLE_CPP_HEADER_MAPS
static struct hmap_header_map * hmap_load_header_map ();
static void hmap_free_header_map ();
static void hmap_lookup ();
#endif
#ifdef APPLE_CPP_INCLUSION_LOGS
static void ilog_printf (const char * format, ...);
static void ilog_write (const char * chars, unsigned length);
#define open(fname,mode,prot) ( num_opens++, open(fname,mode,prot) )
#define stat(fname,sbuf) ( num_stats++, stat(fname,sbuf) )
#define fopen(fname,mode) ( num_opens++, fopen(fname,mode) )
#define fstat(file,sbf) ( num_stats++, fstat(file,sbf) )
#endif
static int
safe_read (desc, ptr, len)
int desc;
char *ptr;
int len;
{
int left, rcount, nchars;
left = len;
while (left > 0) {
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
if (errno == EINTR)
continue;
#endif
return nchars;
}
if (nchars == 0)
break;
#ifdef NEXT_SEMANTICS
{
int chars_left;
char *p, *q;
for (chars_left = nchars, p = ptr;
chars_left && (q = memchr (p, '\r', chars_left));
p = q)
{
*q++ = '\n';
chars_left -= q - p;
if (chars_left && *q == '\n')
break;
}
if (chars_left && q)
{
nchars--;
for (p = q++; --chars_left; )
{
if (*q == '\r')
if (--chars_left)
if (*++q == '\n')
nchars--;
else
*p++ = '\n';
else
{
*p++ = '\n';
break;
}
*p++ = *q++;
}
}
}
#endif
ptr += nchars;
left -= nchars;
}
return len - left;
}
static void
safe_write (desc, ptr, len)
int desc;
char *ptr;
int len;
{
int wcount, written;
while (len > 0) {
wcount = len;
#ifdef MAX_WRITE_LEN
if (wcount > MAX_WRITE_LEN)
wcount = MAX_WRITE_LEN;
#endif
written = write (desc, ptr, wcount);
if (written < 0)
{
#ifdef EINTR
if (errno == EINTR)
continue;
#endif
pfatal_with_name (out_fname);
}
ptr += written;
len -= written;
}
}
static void
eprint_string (string, length)
const char *string;
size_t length;
{
size_t segment_length;
do {
fprintf(stderr, "%s", string);
length -= (segment_length = strlen(string));
if (length > 0)
{
fputc('\0', stderr);
length -= 1;
string += segment_length + 1;
}
} while (length > 0);
}
static void
print_help ()
{
printf ("Usage: %s [switches] input output\n", progname);
printf ("Switches:\n");
printf (" -include <file> Include the contents of <file> before other files\n");
printf (" -imacros <file> Accept definition of marcos in <file>\n");
printf (" -iprefix <path> Specify <path> as a prefix for next two options\n");
printf (" -iwithprefix <dir> Add <dir> to the end of the system include paths\n");
printf (" -iwithprefixbefore <dir> Add <dir> to the end of the main include paths\n");
printf (" -isystem <dir> Add <dir> to the start of the system include paths\n");
printf (" -idirafter <dir> Add <dir> to the end of the system include paths\n");
printf (" -I <dir> Add <dir> to the end of the main include paths\n");
printf (" -nostdinc Do not search the system include directories\n");
printf (" -nostdinc++ Do not search the system include directories for C++\n");
printf (" -o <file> Put output into <file>\n");
printf (" -pedantic Issue all warnings demanded by strict ANSI C\n");
printf (" -traditional Follow K&R pre-processor behaviour\n");
printf (" -trigraphs Support ANSI C trigraphs\n");
printf (" -lang-c Assume that the input sources are in C\n");
printf (" -lang-c89 Assume that the input is C89; depricated\n");
printf (" -lang-c++ Assume that the input sources are in C++\n");
printf (" -lang-objc Assume that the input sources are in ObjectiveC\n");
printf (" -lang-objc++ Assume that the input sources are in ObjectiveC++\n");
printf (" -lang-asm Assume that the input sources are in assembler\n");
printf (" -lang-chill Assume that the input sources are in Chill\n");
printf (" -std=<std name> Specify the conformance standard; one of:\n");
printf (" gnu89, gnu9x, c89, c9x, iso9899:1990,\n");
printf (" iso9899:199409, iso9899:199x\n");
printf (" -+ Allow parsing of C++ style features\n");
printf (" -w Inhibit warning messages\n");
printf (" -Wtrigraphs Warn if trigraphs are encountered\n");
printf (" -Wno-trigraphs Do not warn about trigraphs\n");
printf (" -Wcomment{s} Warn if one comment starts inside another\n");
printf (" -Wno-comment{s} Do not warn about comments\n");
printf (" -Wtraditional Warn if a macro argument is/would be turned into\n");
printf (" a string if -traditional is specified\n");
printf (" -Wno-traditional Do not warn about stringification\n");
printf (" -Wundef Warn if an undefined macro is used by #if\n");
printf (" -Wno-undef Do not warn about testing undefined macros\n");
printf (" -Wimport Warn about the use of the #import directive\n");
printf (" -Wno-import Do not warn about the use of #import\n");
printf (" -Werror Treat all warnings as errors\n");
printf (" -Wno-error Do not treat warnings as errors\n");
printf (" -Wall Enable all preprocessor warnings\n");
printf (" -M Generate make dependencies\n");
printf (" -MM As -M, but ignore system header files\n");
printf (" -MD As -M, but put output in a .d file\n");
printf (" -MMD As -MD, but ignore system header files\n");
printf (" -MG Treat missing header file as generated files\n");
printf (" -g Include #define and #undef directives in the output\n");
printf (" -D<macro> Define a <macro> with string '1' as its value\n");
printf (" -D<macro>=<val> Define a <macro> with <val> as its value\n");
printf (" -A<question> (<answer>) Assert the <answer> to <question>\n");
printf (" -U<macro> Undefine <macro> \n");
printf (" -u or -undef Do not predefine any macros\n");
printf (" -v Display the version number\n");
printf (" -H Print the name of header files as they are used\n");
printf (" -C Do not discard comments\n");
printf (" -dM Display a list of macro definitions active at end\n");
printf (" -dD Preserve macro definitions in output\n");
printf (" -dN As -dD except that only the names are preserved\n");
printf (" -dI Include #include directives in the output\n");
printf (" -ifoutput Describe skipped code blocks in output \n");
printf (" -P Do not generate #line directives\n");
printf (" -$ Do not include '$' in identifiers\n");
printf (" -remap Remap file names when including files.\n");
printf (" -h or --help Display this information\n");
#ifdef APPLE_CPP_INCLUSION_LOGS
printf (" -inclusion-log-file <file> Log #include information to <file>\n");
#endif
}
int
main (argc, argv)
int argc;
char **argv;
{
struct stat st;
char *in_fname;
char *cp;
int f, i;
FILE_BUF *fp;
char **pend_files;
char **pend_defs;
char **pend_undefs;
char **pend_assertions;
char **pend_includes;
#ifdef NEXT_CPP_SERVER
#define MAX_INPUT_ARGS 128
#define MAX_INPUT_CHARS 4096
char command[MAX_INPUT_CHARS+1];
struct file_name_list *include_ptr;
int max_argc = argc;
char * header_fname;
char * requested_cwd;
char actual_cwd[1024];
#endif
char **pend_assertion_options;
int no_standard_includes = 0;
int no_standard_cplusplus_includes = 0;
int missing_newline = 0;
int inhibit_output = 0;
int verbose = 0;
char *deps_file = 0;
char *deps_mode = "a";
FILE *deps_stream = 0;
char *deps_target = 0;
#if defined (RLIMIT_STACK) && defined (HAVE_GETRLIMIT) && defined (HAVE_SETRLIMIT)
{
struct rlimit rlim;
getrlimit (RLIMIT_STACK, &rlim);
rlim.rlim_cur = rlim.rlim_max;
setrlimit (RLIMIT_STACK, &rlim);
}
#endif
#ifdef SIGPIPE
signal (SIGPIPE, pipe_closed);
#endif
#ifdef HAVE_LC_MESSAGES
setlocale (LC_MESSAGES, "");
#endif
(void) bindtextdomain (PACKAGE, localedir);
(void) textdomain (PACKAGE);
progname = base_name (argv[0]);
#ifdef VMS
{
char *p;
char *s = progname = xstrdup (progname);
if ((p = rindex (s, ';')) != 0) *p = '\0';
if ((p = rindex (s, '.')) != 0
&& (p[1] == 'e' || p[1] == 'E')
&& (p[2] == 'x' || p[2] == 'X')
&& (p[3] == 'e' || p[3] == 'E')
&& !p[4])
*p = '\0';
}
#endif
pend_files = (char **) xmalloc (argc * sizeof (char *));
pend_defs = (char **) xmalloc (argc * sizeof (char *));
pend_undefs = (char **) xmalloc (argc * sizeof (char *));
pend_assertions = (char **) xmalloc (argc * sizeof (char *));
pend_includes = (char **) xmalloc (argc * sizeof (char *));
pend_assertion_options = (char **) xmalloc (argc * sizeof (char *));
in_fname = NULL;
out_fname = NULL;
initialize_char_syntax ();
no_line_directives = 0;
no_trigraphs = 1;
dump_macros = dump_none;
no_output = 0;
cplusplus = 0;
cplusplus_comments = 1;
#ifdef NEXT_CPP_SERVER
#define FAILURE \
if (serverized) \
goto processCommand; \
else \
return FAILURE_EXIT_CODE
#define BAILOUT(name) { \
if (serverized) { \
perror_with_name (name); \
goto finishRequest; \
} else { \
pfatal_with_name (name); \
} \
}
init_output_file_buf(&outbuf);
init_output_file_buf(&sys_header_outbuf);
init_output_file_buf(&user_header_outbuf);
if (argc > 1 && !strcmp(argv[1],"-serverize")) {
serverized = 1;
segregate_output = 1;
dump_macros = dump_definitions;
#if defined (NEXT_PDO) && !defined (_WIN32)
if (!getcwd(actual_cwd, 1024))
#else
if (!getwd(actual_cwd))
#endif
pfatal_with_name(actual_cwd);
argv = (char **) xmalloc(sizeof(char *) * MAX_INPUT_ARGS);
fprintf(stderr,"Starting serverized cpp process. Enter commands:\n");
}
processCommand:
while (serverized) {
int preprocess = 0;
char *tok;
if (!fgets(command, MAX_INPUT_CHARS, stdin)) {
fprintf(stderr,"End of server commands. Exiting...\n");
#ifdef PROFILE
chdir(getenv("HOME"));
#endif
exit(FAILURE_EXIT_CODE);
}
argc = 0;
for (tok = strtok(command," \t\n");
tok && (argc < MAX_INPUT_ARGS);
tok = strtok(NULL," \t\n"))
argv[argc++] = tok;
if (!argc)
goto processCommand;
else if (argc > max_argc) {
max_argc = argc;
pend_files = (char **) xrealloc (pend_files, argc * sizeof (char *));
pend_defs = (char **) xrealloc (pend_defs, argc * sizeof (char *));
pend_undefs = (char **) xrealloc (pend_undefs, argc * sizeof (char *));
pend_assertions = (char **) xrealloc (pend_assertions,
argc * sizeof (char *));
pend_includes = (char **) xrealloc (pend_includes,
argc * sizeof (char *));
pend_assertion_options = (char **) xrealloc (pend_assertion_options,
argc * sizeof (char *));
}
switch (argv[0][0]) {
case 'c':
if (!strcmp(argv[0],"cpp"))
preprocess = 1;
break;
case 'm':
if (!strcmp(argv[0],"modtime"))
if (argc > 2) {
time_t lastModTime = file_modtime (argv[2]);
fprintf(stderr, "modtime is %d\n");
} else {
fprintf(stderr,"bad modtime argument: <file name>\n");
}
break;
case 'n':
if (!strcmp(argv[0],"notice_file_modification"))
if (argc > 1)
handle_file_modification(argv[1]);
else
fprintf(stderr,
"bad notice_file_modification argument: <file name>\n");
break;
case 's':
if (!strcmp(argv[0],"stats"))
dump_memory_statistics();
break;
case 't':
if (!strcmp(argv[0],"terminate"))
exit(0);
else if (!strcmp(argv[0],"timings"))
if ((argc > 1) && !strcmp(argv[1],"on"))
timings = 1;
break;
case 'w':
if (!strcmp(argv[0],"write_sys_headers")) {
if (argc > 2) {
int write_all = (strcmp(argv[1], "all") == 0) ? 1 : 0;
out_fname = argv[2];
write_header_output (out_fname, &sys_header_outbuf, write_all, 1);
} else {
fprintf(stderr,
"bad write_sys_headers arguments: <all|new> <file name>\n");
}
} else if (!strcmp(argv[0],"write_user_headers")) {
if (argc > 1) {
int write_all = (strcmp(argv[1], "all") == 0) ? 1 : 0;
out_fname = argv[2];
write_header_output (out_fname, &user_header_outbuf, write_all,1);
} else {
fprintf(stderr,
"bad write_user_headers arguments: <all|new> <file name>\n");
}
}
break;
}
if (preprocess)
break;
}
errors = 0;
in_fname = out_fname = header_fname = requested_cwd = NULL;
outbuf_stat_info_recorded = 0;
#endif
bzero ((char *) pend_files, argc * sizeof (char *));
bzero ((char *) pend_defs, argc * sizeof (char *));
bzero ((char *) pend_undefs, argc * sizeof (char *));
bzero ((char *) pend_assertions, argc * sizeof (char *));
bzero ((char *) pend_includes, argc * sizeof (char *));
#ifdef MULTIBYTE_CHARS
setlocale (LC_CTYPE, "");
literal_codeset = getenv ("LANG");
#endif
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
if (out_fname != NULL)
{
print_help ();
fatal ("Too many arguments");
}
else if (in_fname != NULL)
out_fname = argv[i];
else
in_fname = argv[i];
} else {
switch (argv[i][1]) {
#ifdef NEXT_SEMANTICS
case 'a':
if (!strcmp (argv[i], "-arch"))
i++;
break;
case 'O':
if (! strcmp (argv[i], "-ObjC++"))
;
break;
case 'c':
if (! strcmp (argv[i], "-c++-comments"))
cplusplus_comments = 1;
break;
#endif
case 'i':
if (!strcmp (argv[i], "-include")) {
int temp = i;
if (i + 1 == argc)
fatal ("Filename missing after `-include' option");
else
simplify_filename (pend_includes[temp] = argv[++i]);
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else
#endif
if (!strcmp (argv[i], "-imacros")) {
int temp = i;
if (i + 1 == argc)
fatal ("Filename missing after `-imacros' option");
else
simplify_filename (pend_files[temp] = argv[++i]);
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else
#endif
if (!strcmp (argv[i], "-iprefix")) {
if (i + 1 == argc)
fatal ("Filename missing after `-iprefix' option");
else
include_prefix = argv[++i];
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else
#endif
if (!strcmp (argv[i], "-ifoutput")) {
output_conditionals = 1;
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else
#endif
if (!strcmp (argv[i], "-isystem")) {
struct file_name_list *dirtmp;
if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR,
"", argv[++i])))
break;
dirtmp->c_system_include_path = 1;
if (before_system == 0)
before_system = dirtmp;
else
last_before_system->next = dirtmp;
last_before_system = dirtmp;
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else
#endif
if (!strcmp (argv[i], "-iwithprefix")) {
struct file_name_list *dirtmp;
char *prefix;
if (include_prefix != 0)
prefix = include_prefix;
else {
prefix = xstrdup (GCC_INCLUDE_DIR);
if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
prefix[strlen (prefix) - 7] = 0;
}
if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR,
prefix, argv[++i])))
break;
if (after_include == 0)
after_include = dirtmp;
else
last_after_include->next = dirtmp;
last_after_include = dirtmp;
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else
#endif
if (!strcmp (argv[i], "-iwithprefixbefore")) {
struct file_name_list *dirtmp;
char *prefix;
if (include_prefix != 0)
prefix = include_prefix;
else {
prefix = xstrdup (GCC_INCLUDE_DIR);
if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
prefix[strlen (prefix) - 7] = 0;
}
dirtmp = new_include_prefix (NULL_PTR, NULL_PTR, prefix, argv[++i]);
append_include_chain (dirtmp, dirtmp);
}
#ifdef APPLE_CPP_INCLUSION_LOGS
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else
#endif
if (!strcmp (argv[i], "-inclusion-log-file")) {
if (i + 1 == argc)
fatal ("File name missing after `-inclusion-log-file' option");
else {
const char * ilog_name = argv[++i];
inclusion_log_file = ((ilog_name[0] != '-' || ilog_name[1] != '\0')
? fopen (ilog_name, "w")
: fdopen (dup (fileno (stdout)), "w"));
if (!inclusion_log_file)
perror(ilog_name);
}
}
#endif
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else
#endif
if (!strcmp (argv[i], "-idirafter")) {
struct file_name_list *dirtmp;
if (! (dirtmp = new_include_prefix (NULL_PTR, NULL_PTR,
"", argv[++i])))
break;
if (after_include == 0)
after_include = dirtmp;
else
last_after_include->next = dirtmp;
last_after_include = dirtmp;
}
#ifdef NEXT_CPP_SERVER
else if (!strcmp (argv[i], "-in_directory")) {
if (i + 1 == argc)
fatal ("Filename missing after -output_headers option");
requested_cwd = argv[++i];
}
#endif
#ifdef NEXT_OBJC_RUNTIME
else if (argv[i][2] != 0)
pend_files[i] = argv[i] + 2;
else if (i + 1 == argc)
fatal ("Filename missing after -i option");
else
pend_files[i] = argv[i+1], i++;
#endif
break;
case 'o':
#ifdef NEXT_CPP_SERVER
if (!strcmp (argv[i], "-output_headers")) {
if (i + 1 == argc)
fatal ("Filename missing after -output_headers option");
header_fname = argv[++i];
} else {
#endif
if (out_fname != NULL)
fatal ("Output filename specified twice");
if (i + 1 == argc)
fatal ("Filename missing after -o option");
out_fname = argv[++i];
if (!strcmp (out_fname, "-"))
out_fname = "";
#ifdef NEXT_CPP_SERVER
}
#endif
break;
case 'p':
if (!strcmp (argv[i], "-pedantic"))
pedantic = 1;
else if (!strcmp (argv[i], "-pedantic-errors")) {
pedantic = 1;
pedantic_errors = 1;
#ifdef NEXT_PDO
} else if (!strcmp (argv[i], "-precomp")) {
fatal ("-precomp option not supported");
exit (SUCCESS_EXIT_CODE);
#endif
} else if (!strcmp (argv[i], "-pcp")) {
char *pcp_fname;
if (i + 1 == argc)
fatal ("Filename missing after -pcp option");
pcp_fname = argv[++i];
pcp_outfile
= ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
? fopen (pcp_fname, "w")
: stdout);
if (pcp_outfile == 0)
#ifdef NEXT_CPP_SERVER
BAILOUT (pcp_fname);
#else
pfatal_with_name (pcp_fname);
#endif
no_precomp = 1;
}
break;
case 't':
if (!strcmp (argv[i], "-traditional")) {
traditional = 1;
cplusplus_comments = 0;
} else if (!strcmp (argv[i], "-trigraphs")) {
no_trigraphs = 0;
}
break;
case 'l':
if (! strcmp (argv[i], "-lang-c"))
cplusplus = 0, cplusplus_comments = 1, c89 = 0, c9x = 1, objc = 0;
else if (! strcmp (argv[i], "-lang-c89"))
cplusplus = 0, cplusplus_comments = 0, c89 = 1, c9x = 0, objc = 0;
else if (! strcmp (argv[i], "-lang-c++"))
cplusplus = 1, cplusplus_comments = 1, c89 = 0, c9x = 0, objc = 0;
else if (! strcmp (argv[i], "-lang-objc"))
cplusplus = 0, cplusplus_comments = 1, c89 = 0, c9x = 0, objc = 1;
else if (! strcmp (argv[i], "-lang-objc++"))
cplusplus = 1, cplusplus_comments = 1, c89 = 0, c9x = 0, objc = 1;
else if (! strcmp (argv[i], "-lang-asm"))
lang_asm = 1;
else if (! strcmp (argv[i], "-lint"))
for_lint = 1;
break;
case '+':
cplusplus = 1, cplusplus_comments = 1;
break;
case 's':
if (!strcmp (argv[i], "-std=iso9899:1990")
|| !strcmp (argv[i], "-std=iso9899:199409")
|| !strcmp (argv[i], "-std=c89")
|| !strcmp (argv[i], "-std=gnu89"))
cplusplus = 0, cplusplus_comments = 0, c89 = 1, c9x = 0, objc = 0;
else if (!strcmp (argv[i], "-std=iso9899:199x")
|| !strcmp (argv[i], "-std=c9x")
|| !strcmp (argv[i], "-std=gnu9x"))
cplusplus = 0, cplusplus_comments = 1, c89 = 0, c9x = 1, objc = 0;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else if (!strcmp (argv[i], "-smart"))
;
#ifdef NEXT_CPP_SERVER
else if (!strcmp (argv[i], "-segregate-output"))
segregate_output = 1;
break;
case 'm':
if (!strcmp (argv[i], "-mark-expansions"))
mark_expansions = 1;
#endif
break;
#ifdef APPLE_CPP_HEADER_MAPS
case 'h':
if (!strcmp (argv[i], "-header-mapfile"))
{
if (i + 1 == argc)
fatal ("filename missing after `-header-mapfile' option");
else if (header_map != NULL)
fatal ("more than one `-header-mapfile' option specified; "
"only one is allowed");
else
header_map = hmap_load_header_map (argv [i++ + 1]);
}
break;
#endif
#endif
break;
case 'w':
inhibit_warnings = 1;
break;
case 'W':
if (!strcmp (argv[i], "-Wtrigraphs"))
warn_trigraphs = 1;
else if (!strcmp (argv[i], "-Wno-trigraphs"))
warn_trigraphs = 0;
else if (!strcmp (argv[i], "-Wcomment"))
warn_comments = 1;
else if (!strcmp (argv[i], "-Wno-comment"))
warn_comments = 0;
else if (!strcmp (argv[i], "-Wcomments"))
warn_comments = 1;
else if (!strcmp (argv[i], "-Wno-comments"))
warn_comments = 0;
else if (!strcmp (argv[i], "-Wtraditional"))
warn_stringify = 1;
else if (!strcmp (argv[i], "-Wno-traditional"))
warn_stringify = 0;
else if (!strcmp (argv[i], "-Wundef"))
warn_undef = 1;
else if (!strcmp (argv[i], "-Wno-undef"))
warn_undef = 0;
else if (!strcmp (argv[i], "-Wimport"))
warn_import = 1;
else if (!strcmp (argv[i], "-Wno-import"))
warn_import = 0;
else if (!strcmp (argv[i], "-Werror"))
warnings_are_errors = 1;
else if (!strcmp (argv[i], "-Wno-error"))
warnings_are_errors = 0;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else if (!strcmp (argv[i], "-Wall") || !strcmp (argv[i], "-Wmost"))
#else
else if (!strcmp (argv[i], "-Wall"))
#endif
{
warn_trigraphs = 1;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
if (!strcmp (argv[i], "-Wmost"))
warn_pragma_once = 0;
else
warn_pragma_once = 1;
#endif
#if defined (NEXT_PDO) && !defined (_WIN32)
if (!strcmp (argv[i], "-Wmost"))
warn_comments = 0;
else
#endif
warn_comments = 1;
}
break;
case 'f':
if (!strcmp (argv[i], "-fleading-underscore"))
user_label_prefix = "_";
else if (!strcmp (argv[i], "-fno-leading-underscore"))
user_label_prefix = "";
#ifdef NEXT_SEMANTICS
else if (! strcmp (argv[i], "-fdump-syms"))
flag_dump_symbols = 1;
else if (! strncmp (argv[i], "-fgen-index=", 12))
{
if (argv[i][12])
{
index_host_name = &argv[i][12];
flag_gen_index = 1;
}
else
error ("Missing argument to -fgen-index");
}
#endif
#ifdef ENABLE_NEWLINE_MAPPING
else if (!strcmp (argv[i], "-fmap-newline-to-cr"))
flag_map_newline_to_cr = 1;
else if (!strcmp (argv[i], "-fno-map-newline-to-cr"))
flag_map_newline_to_cr = 0;
#endif
break;
case 'M':
if (!strcmp (argv[i], "-MG"))
{
print_deps_missing_files = 1;
break;
}
if (!strcmp (argv[i], "-M"))
print_deps = 2;
else if (!strcmp (argv[i], "-MM"))
print_deps = 1;
else if (!strcmp (argv[i], "-MD"))
print_deps = 2;
else if (!strcmp (argv[i], "-MMD"))
print_deps = 1;
if (!strcmp (argv[i], "-MD")
|| !strcmp (argv[i], "-MMD")) {
if (i + 1 == argc)
fatal ("Filename missing after %s option", argv[i]);
i++;
deps_file = argv[i];
deps_mode = "w";
} else {
deps_stream = stdout;
inhibit_output = 1;
}
break;
case 'd':
{
char *p = argv[i] + 2;
char c;
while ((c = *p++)) {
switch (c) {
case 'M':
dump_macros = dump_only;
no_output = 1;
break;
case 'N':
dump_macros = dump_names;
break;
case 'D':
dump_macros = dump_definitions;
break;
case 'I':
dump_includes = 1;
break;
}
}
}
break;
case 'g':
if (argv[i][2] == '3')
debug_output = 1;
break;
case '-':
if (strcmp (argv[i], "--help") != 0)
return i;
print_help ();
exit (0);
break;
case 'v':
notice ("GNU CPP version %s", version_string);
#ifdef TARGET_VERSION
TARGET_VERSION;
#endif
fprintf (stderr, "\n");
verbose = 1;
break;
case 'H':
print_include_names = 1;
break;
case 'D':
if (argv[i][2] != 0)
pend_defs[i] = argv[i] + 2;
else if (i + 1 == argc)
fatal ("Macro name missing after -D option");
else
i++, pend_defs[i] = argv[i];
break;
case 'A':
{
char *p;
if (argv[i][2] != 0)
p = argv[i] + 2;
else if (i + 1 == argc)
fatal ("Assertion missing after -A option");
else
p = argv[++i];
if (!strcmp (p, "-")) {
int j;
for (j = 0; j < i; j++)
pend_defs[j] = pend_assertions[j] = 0;
} else {
pend_assertions[i] = p;
pend_assertion_options[i] = "-A";
}
}
break;
case 'U':
if (argv[i][2] != 0)
pend_undefs[i] = argv[i] + 2;
else if (i + 1 == argc)
fatal ("Macro name missing after -U option");
else
pend_undefs[i] = argv[i+1], i++;
break;
case 'C':
put_out_comments = 1;
break;
case 'E':
break;
case 'P':
no_line_directives = 1;
break;
case '$':
is_idchar['$'] = is_idstart['$'] = 0;
break;
case 'I':
{
struct file_name_list *dirtmp;
if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) {
ignore_srcdir = 1;
first_bracket_include = 0;
}
else {
dirtmp = new_include_prefix (last_include, NULL_PTR, "",
argv[i][2] ? argv[i] + 2 : argv[++i]);
append_include_chain (dirtmp, dirtmp);
}
}
break;
#ifdef NEXT_FRAMEWORKS
case 'F':
{
struct file_name_list *dirtmp;
if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) {
ignore_srcdir = 1;
first_bracket_framework = 0;
}
else {
char *file_name;
if (argv[i][2] != 0)
file_name = argv[i] + 2;
else if (i + 1 == argc)
fatal ("Directory name missing after -I option");
else
file_name = argv[++i];
dirtmp = (struct file_name_list *)
xmalloc (sizeof (struct file_name_list) + strlen (file_name));
dirtmp->next = 0;
dirtmp->c_system_include_path = 0;
strcpy (dirtmp->fname, file_name);
dirtmp->got_name_map = 0;
append_framework_chain (dirtmp, dirtmp);
}
}
break;
#endif
case 'n':
if (!strcmp (argv[i], "-nostdinc"))
no_standard_includes = 1;
else if (!strcmp (argv[i], "-nostdinc++"))
no_standard_cplusplus_includes = 1;
else if (!strcmp (argv[i], "-noprecomp"))
no_precomp = 1;
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
if (!strcmp (argv[i], "-no-c++-comments"))
cplusplus_comments = 0;
#endif
break;
case 'r':
if (!strcmp (argv[i], "-remap"))
remap = 1;
break;
case '\0':
if (in_fname == NULL) {
in_fname = "";
break;
} else if (out_fname == NULL) {
out_fname = "";
break;
}
default:
fatal ("Invalid option `%s'", argv[i]);
}
}
}
if (!flag_gen_index)
{
index_port_string = getenv ("PB_INDEX_SOCKET_PORT");
if (index_port_string && *index_port_string)
{
index_port_number = atoi (index_port_string);
flag_gen_index = 1;
index_host_name = getenv ("PB_INDEX_SOCKET_HOSTNAME");
if (index_host_name && *index_host_name)
{ }
else
{
index_host_name = NULL;
}
}
else
flag_gen_index = 0;
}
if (flag_dump_symbols)
{
flag_dump_symbols = 0;
flag_gen_index = 0;
flag_gen_index_original = 0;
}
if (flag_gen_index)
{
flag_gen_index_original = 1;
index_header_list_filename = getenv ("PB_INDEXED_HEADERS_FILE");
if (index_header_list_filename && *index_header_list_filename)
flag_check_indexed_header_list = read_indexed_header_list ();
index_socket_fd = connect_to_socket(index_host_name, index_port_number);
if (index_socket_fd == -1)
{
warning ("Can not open socket. Indexing information is not produced");
}
else
{
int length;
char * buf = NULL;
if (in_fname)
length = strlen (in_fname);
else
length = 1;
buf = (char *) malloc (sizeof (char) * (40 + length));
sprintf (buf, "pbxindex-begin v1.0 0x%08lX %02u/%02u %s\n",
(unsigned long) getppid(), 1, 2, in_fname ? in_fname : " ");
write (index_socket_fd, buf, strlen (buf));
free (buf);
}
}
#ifdef NEXT_CPP_SERVER
if (serverized && requested_cwd && strcmp(actual_cwd, requested_cwd) != 0) {
if (chdir(requested_cwd) == 0)
strcpy(actual_cwd, requested_cwd);
}
#endif
GET_ENV_PATH_LIST (cp, "CPATH");
if (cp && ! no_standard_includes)
path_include (cp);
#ifdef NEXT_CPP_SERVER
if (timings)
start();
#else
outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE);
outbuf.bufp = outbuf.buf;
outbuf.length = OUTBUF_SIZE;
#endif
fp = &instack[++indepth];
if (in_fname == NULL)
in_fname = "";
fp->nominal_fname = fp->fname = in_fname;
fp->nominal_fname_len = strlen (in_fname);
fp->lineno = 0;
if (cplusplus)
wchar_type = "__wchar_t";
initialize_builtins (fp, &outbuf);
for (i = 1; i < argc; i++) {
if (pend_undefs[i]) {
if (debug_output)
output_line_directive (fp, &outbuf, 0, same_file);
make_undef (pend_undefs[i], &outbuf);
}
if (pend_defs[i]) {
if (debug_output)
output_line_directive (fp, &outbuf, 0, same_file);
make_definition (pend_defs[i]);
}
if (pend_assertions[i])
make_assertion (pend_assertion_options[i], pend_assertions[i]);
}
done_initializing = 1;
{
char *epath = 0;
switch ((objc << 1) + cplusplus)
{
case 0:
GET_ENV_PATH_LIST (epath, "C_INCLUDE_PATH");
break;
case 1:
GET_ENV_PATH_LIST (epath, "CPLUS_INCLUDE_PATH");
break;
case 2:
GET_ENV_PATH_LIST (epath, "OBJC_INCLUDE_PATH");
break;
case 3:
GET_ENV_PATH_LIST (epath, "OBJCPLUS_INCLUDE_PATH");
break;
}
if (epath) {
int num_dirs;
char *startp, *endp;
for (num_dirs = 1, startp = epath; *startp; startp++)
if (*startp == PATH_SEPARATOR)
num_dirs++;
include_defaults
= (struct default_include *) xmalloc ((num_dirs
* sizeof (struct default_include))
+ sizeof (include_defaults_array));
startp = endp = epath;
num_dirs = 0;
while (1) {
char c = *endp++;
if (c == PATH_SEPARATOR || !c) {
endp[-1] = 0;
include_defaults[num_dirs].fname
= startp == endp ? "." : xstrdup (startp);
endp[-1] = c;
include_defaults[num_dirs].component = 0;
include_defaults[num_dirs].cplusplus = cplusplus;
include_defaults[num_dirs].cxx_aware = 1;
num_dirs++;
if (!c)
break;
startp = endp;
}
}
bcopy ((char *) include_defaults_array,
(char *) &include_defaults[num_dirs],
sizeof (include_defaults_array));
}
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
{
struct default_include *fix_includes = include_defaults;
char* next_root = getenv ("NEXT_ROOT");
int i = 0;
if (next_root && next_root[strlen (next_root) - 1] == '/')
next_root[strlen (next_root) - 1] = '\0';
if (next_root && *next_root)
{
while (fix_includes[i].fname)
{
char* new_fname =
(char *) xmalloc (strlen (next_root)
+ strlen (fix_includes[i].fname) + 1);
sprintf (new_fname, "%s%s", next_root, fix_includes[i].fname);
if (new_fname && *new_fname)
fix_includes[i].fname = new_fname;
i++;
}
}
}
#endif
append_include_chain (before_system, last_before_system);
first_system_include = before_system;
if (!no_standard_includes) {
#ifdef NEXT_FRAMEWORKS
int hdr;
#endif
struct default_include *p = include_defaults;
char *specd_prefix = include_prefix;
char *default_prefix = xstrdup (GCC_INCLUDE_DIR);
int default_len = 0;
if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
default_len = strlen (default_prefix) - 7;
default_prefix[default_len] = 0;
}
if (specd_prefix != 0 && default_len != 0)
for (p = include_defaults; p->fname; p++) {
if (!p->cplusplus || (cplusplus && !no_standard_cplusplus_includes)) {
if (!strncmp (p->fname, default_prefix, default_len)) {
struct file_name_list *new
= new_include_prefix (NULL_PTR, NULL_PTR, specd_prefix,
p->fname + default_len);
if (new) {
new->c_system_include_path = !p->cxx_aware;
append_include_chain (new, new);
if (first_system_include == 0)
first_system_include = new;
p->included = 1;
}
}
}
}
for (p = include_defaults; p->fname; p++) {
if (!p->cplusplus || (cplusplus && !no_standard_cplusplus_includes)) {
struct file_name_list *new
= new_include_prefix (NULL_PTR, p->component, "", p->fname);
if (new) {
new->c_system_include_path = !p->cxx_aware;
append_include_chain (new, new);
if (first_system_include == 0)
first_system_include = new;
p->included = 1;
}
}
}
#ifdef NEXT_FRAMEWORKS
for (hdr=0; framework_defaults_array[hdr].fname; hdr++) {
struct stat dummy;
char *next_root = getenv ("NEXT_ROOT");
if (next_root)
{
char *new_name =
(char *)xmalloc (strlen (next_root)
+ strlen (framework_defaults_array[hdr].fname)+1);
if (next_root[strlen (next_root)-1] == '/')
next_root[strlen(next_root)-1] = '\0';
sprintf (new_name, "%s%s", next_root,
framework_defaults_array[hdr].fname);
framework_defaults_array[hdr].fname = new_name;
}
if (stat(framework_defaults_array[hdr].fname, &dummy) == 0) {
struct file_name_list *new
= (struct file_name_list *) xmalloc (sizeof (struct file_name_list)
+ strlen (framework_defaults_array[hdr].fname));
new->c_system_include_path = !framework_defaults_array[hdr].cxx_aware;
strcpy (new->fname, framework_defaults_array[hdr].fname);
new->got_name_map = 0;
append_framework_chain (new, new);
}
}
free (default_prefix);
#endif
}
append_include_chain (after_include, last_after_include);
if (first_system_include == 0)
first_system_include = after_include;
if (verbose) {
struct file_name_list *p;
notice ("#include \"...\" search starts here:\n");
for (p = include; p; p = p->next) {
if (p == first_bracket_include)
notice ("#include <...> search starts here:\n");
if (!p->fname[0])
fprintf (stderr, " .\n");
else if (!strcmp (p->fname, "/") || !strcmp (p->fname, "//"))
fprintf (stderr, " %s\n", p->fname);
else
fprintf (stderr, " %.*s\n", (int) strlen (p->fname) - 1, p->fname);
}
notice ("End of search list.\n");
{
struct default_include * d;
notice ("The following default directories have been omitted from the search path:\n");
for (d = include_defaults; d->fname; d++)
if (! d->included)
fprintf (stderr, " %s\n", d->fname);
notice ("End of omitted list.\n");
}
}
if (print_deps_missing_files && (print_deps == 0 || !inhibit_output))
fatal ("-MG must be specified with one of -M or -MM");
if (print_deps == 0
&& (getenv ("SUNPRO_DEPENDENCIES") != 0
|| getenv ("DEPENDENCIES_OUTPUT") != 0)) {
char *spec = getenv ("DEPENDENCIES_OUTPUT");
char *s;
char *output_file;
if (spec == 0) {
spec = getenv ("SUNPRO_DEPENDENCIES");
print_deps = 2;
}
else
print_deps = 1;
s = spec;
while (*s != 0 && *s != ' ') s++;
if (*s != 0) {
deps_target = s + 1;
output_file = xmalloc (s - spec + 1);
bcopy (spec, output_file, s - spec);
output_file[s - spec] = 0;
}
else {
deps_target = 0;
output_file = spec;
}
deps_file = output_file;
deps_mode = "a";
}
if (print_deps) {
deps_allocated_size = 200;
deps_buffer = xmalloc (deps_allocated_size);
deps_buffer[0] = 0;
deps_size = 0;
deps_column = 0;
if (deps_target) {
deps_output (deps_target, ':');
} else if (*in_fname == 0) {
deps_output ("-", ':');
} else {
char *p, *q;
int len;
q = base_name (in_fname);
p = (char *) alloca (strlen(q) + 8);
strcpy (p, q);
len = strlen (p);
q = p + len;
if (len >= 2
&& p[len - 2] == '.'
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
&& index("cCsSmM", p[len - 1]))
#else
&& index("cCsSm", p[len - 1]))
#endif
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);
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
else if (len >= 3
&& p[len - 3] == '.'
&& p[len - 2] == 'm'
&& p[len - 1] == 'm')
q = p + (len - 3);
#endif
strcpy (q, OBJECT_SUFFIX);
deps_output (p, ':');
deps_output (in_fname, ' ');
}
}
no_output++; no_record_file++;
for (i = 1; i < argc; i++)
if (pend_files[i]) {
struct include_file *inc;
int fd = open_include_file (pend_files[i], NULL_PTR, NULL_PTR, &inc);
if (fd < 0) {
perror_with_name (pend_files[i]);
return FATAL_EXIT_CODE;
}
finclude (fd, inc, &outbuf, 0, NULL_PTR);
}
no_output--; no_record_file--;
if (in_fname == NULL || *in_fname == 0) {
in_fname = "";
f = 0;
} else if ((f = open (in_fname, O_RDONLY, 0666)) < 0)
goto perror;
if (fstat (f, &st) != 0)
pfatal_with_name (in_fname);
fp->nominal_fname = fp->fname = in_fname;
fp->nominal_fname_len = strlen (in_fname);
fp->lineno = 1;
fp->system_header_p = 0;
if (! S_ISREG (st.st_mode)) {
int size;
int bsize;
int cnt;
if (S_ISDIR (st.st_mode))
fatal ("Input file `%s' is a directory", in_fname);
bsize = 2000;
size = 0;
fp->buf = (U_CHAR *) xmalloc (bsize + 2);
for (;;) {
cnt = safe_read (f, (char *) fp->buf + size, bsize - size);
#ifdef NEXT_CPP_SERVER
if (cnt < 0) BAILOUT (in_fname);
if (cnt == 0) break;
#else
if (cnt < 0) goto perror;
#endif
size += cnt;
if (size != bsize) break;
bsize *= 2;
fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
}
fp->length = size;
} else {
size_t s = (size_t) st.st_size;
if (s != st.st_size || s + 2 < s)
memory_full ();
fp->buf = (U_CHAR *) xmalloc (s + 2);
fp->length = safe_read (f, (char *) fp->buf, s);
if (fp->length < 0) goto perror;
}
fp->bufp = fp->buf;
fp->if_stack = if_stack;
if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n')
|| (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) {
fp->buf[fp->length++] = '\n';
missing_newline = 1;
}
fp->buf[fp->length] = '\0';
if (!no_trigraphs)
trigraph_pcp (fp);
#ifdef NEXT_SEMANTICS
if (!no_rtf)
buf_convert_rtf (fp);
#endif
#ifdef NEXT_CPP_SERVER
if (!out_fname || !strcmp (out_fname, "") || !strcmp (out_fname, "stdout"))
if (serverized)
fatal("Can't output to stdout when serverized.");
else
#else
if (!out_fname || !strcmp (out_fname, ""))
#endif
out_fname = "stdout";
#ifndef NEXT_CPP_SERVER
else if (!flag_dump_symbols) {
if (!freopen (out_fname, "w", stdout))
pfatal_with_name (out_fname);
}
#endif
output_line_directive (fp, &outbuf, 0, same_file);
if (flag_dump_symbols)
printf ("+Fm %s\n", in_fname);
if (flag_gen_index)
dump_symbol_info ("+Fm ", in_fname, -1);
no_record_file++;
for (i = 1; i < argc; i++)
if (pend_includes[i]) {
struct include_file *inc;
int fd = open_include_file (pend_includes[i], NULL_PTR, NULL_PTR, &inc);
if (fd >= 0)
#ifdef NEXT_CPP_SERVER
finclude (fd, inc, &outbuf, 0, 0, 0, 0);
#else
finclude (fd, inc, &outbuf, 0, NULL_PTR);
#endif
else if (fd != -2) {
perror_with_name (pend_includes[i]);
#ifdef NEXT_CPP_SERVER
FAILURE;
#else
return FATAL_EXIT_CODE;
#endif
}
}
no_record_file--;
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf("\"%s\" {\n", in_fname);
#endif
rescan (&outbuf, 0);
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf("} [%i stat()s, %i open()s]\n", num_stats, num_opens);
#endif
if (flag_dump_symbols)
printf ("*Fm %s\n", in_fname);
if (flag_gen_index)
dump_symbol_info ("*Fm ", in_fname, -1);
if (missing_newline)
fp->lineno--;
if (pedantic && missing_newline)
pedwarn ("file does not end in newline");
if (flag_gen_index)
{
char buf[16] = "pbxindex-end ?\n";
if (index_buffer_count != 0)
flush_index_buffer ();
write (index_socket_fd, &buf[0], strlen (&buf[0]));
if (close (index_socket_fd) < 0)
{
warning ("Can not close the socket used to put indexing information");
}
}
if (dump_macros == dump_only)
dump_all_macros ();
else if (! inhibit_output) {
#ifdef NEXT_CPP_SERVER
write_output (&outbuf, out_fname, 1);
#else
write_output (out_fname);
#endif
}
if (print_deps) {
if (errors == 0) {
if (deps_file && ! (deps_stream = fopen (deps_file, deps_mode)))
#ifdef NEXT_CPP_SERVER
BAILOUT (deps_file);
#else
pfatal_with_name (deps_file);
#endif
fputs (deps_buffer, deps_stream);
putc ('\n', deps_stream);
if (deps_file) {
if (ferror (deps_stream) || fclose (deps_stream) != 0)
fatal ("I/O error on output");
}
}
}
#ifdef NEXT_CPP_SERVER
finishRequest:
if (serverized) {
int wrote_headers = 0;
if (header_fname)
wrote_headers =
write_header_output (header_fname, &sys_header_outbuf, 0, 0);
if (timings) {
stop();
fprintf(stderr, "Preprocessed %s%s into %s\n in ",
wrote_headers ? "(loading new headers) " : "",
in_fname, out_fname);
display(stderr, 1);
} else {
fprintf(stderr, "Preprocessed %s%s into %s\n",
wrote_headers ? "(loading new headers) " : "",
in_fname, out_fname);
}
fflush(stderr);
indepth = -1;
clear_all_macros();
clear_import();
outbuf.bufp = outbuf.buf;
bzero (outbuf.bufp, outbuf.length);
outbuf.lineno = 0;
close (f);
free (fp->buf);
fp->buf = fp->bufp = NULL;
free_undefined_macros = 0;
include_ptr = include;
while (include_ptr) {
struct file_name_list * next_include = include_ptr->next;
free (include_ptr);
include_ptr = next_include;
}
first_bracket_include = 0;
first_system_include = 0;
include = 0;
last_include = 0;
after_include = 0;
last_after_include = 0;
#ifdef NEXT_FRAMEWORKS
include_ptr = framework;
while (include_ptr) {
struct file_name_list * next_include = include_ptr->next;
free (include_ptr);
include_ptr = next_include;
}
first_bracket_framework = 0;
framework = 0;
last_framework = 0;
#endif
done_initializing = 0;
goto processCommand;
}
#endif
#ifdef APPLE_CPP_INCLUSION_LOGS
if (inclusion_log_file && inclusion_log_file != stdout
&& (ferror (inclusion_log_file) || fclose (inclusion_log_file) != 0))
fatal ("I/O error on `-inclusion-log-file' output");
#endif
if (pcp_outfile && pcp_outfile != stdout
&& (ferror (pcp_outfile) || fclose (pcp_outfile) != 0))
fatal ("I/O error on `-pcp' output");
if (ferror (stdout) || fclose (stdout) != 0)
fatal ("I/O error on output");
if (errors)
exit (FATAL_EXIT_CODE);
exit (SUCCESS_EXIT_CODE);
#ifndef NEXT_CPP_SERVER
perror:
#endif
pfatal_with_name (in_fname);
return 0;
}
static void
path_include (path)
char *path;
{
char *p;
p = path;
if (*p)
while (1) {
char *q = p;
char c;
struct file_name_list *dirtmp;
while ((c = *q++) != PATH_SEPARATOR && c)
continue;
q[-1] = 0;
dirtmp = new_include_prefix (last_include, NULL_PTR,
"", p == q ? "." : p);
q[-1] = c;
append_include_chain (dirtmp, dirtmp);
p = q;
if (! c)
break;
}
}
static U_CHAR *
index0 (s, c, n)
U_CHAR *s;
int c;
size_t n;
{
char *p = (char *) s;
for (;;) {
char *q = index (p, c);
if (q)
return (U_CHAR *) q;
else {
size_t l = strlen (p);
if (l == n)
return 0;
l++;
p += l;
n -= l;
}
}
}
static void
trigraph_pcp (buf)
FILE_BUF *buf;
{
register U_CHAR c, *fptr, *bptr, *sptr, *lptr;
int len;
fptr = bptr = sptr = buf->buf;
lptr = fptr + buf->length;
while ((sptr = index0 (sptr, '?', (size_t) (lptr - sptr))) != NULL) {
if (*++sptr != '?')
continue;
switch (*++sptr) {
case '=':
c = '#';
break;
case '(':
c = '[';
break;
case '/':
c = '\\';
break;
case ')':
c = ']';
break;
case '\'':
c = '^';
break;
case '<':
c = '{';
break;
case '!':
c = '|';
break;
case '>':
c = '}';
break;
case '-':
c = '~';
break;
case '?':
sptr--;
continue;
default:
continue;
}
len = sptr - fptr - 2;
if (bptr != fptr && len > 0)
bcopy ((char *) fptr, (char *) bptr, len);
bptr += len;
*bptr++ = c;
fptr = ++sptr;
}
len = buf->length - (fptr - buf->buf);
if (bptr != fptr && len > 0)
bcopy ((char *) fptr, (char *) bptr, len);
buf->length -= fptr - bptr;
buf->buf[buf->length] = '\0';
if (warn_trigraphs && fptr != bptr)
warning_with_line (0, "%lu trigraph(s) encountered",
(unsigned long) (fptr - bptr) / 2);
}
static void
newline_fix (bp)
U_CHAR *bp;
{
register U_CHAR *p = bp;
while (p[0] == '\\' && p[1] == '\n')
p += 2;
if (*p != '/' && *p != '*')
return;
while (*p == '*' || *p == '/')
*bp++ = *p++;
while (bp < p) {
*bp++ = '\\';
*bp++ = '\n';
}
}
static void
name_newline_fix (bp)
U_CHAR *bp;
{
register U_CHAR *p = bp;
while (p[0] == '\\' && p[1] == '\n')
p += 2;
if (!is_idchar[*p])
return;
while (is_idchar[*p])
*bp++ = *p++;
while (bp < p) {
*bp++ = '\\';
*bp++ = '\n';
}
}
static char *
get_lintcmd (ibp, limit, argstart, arglen, cmdlen)
register U_CHAR *ibp;
register U_CHAR *limit;
U_CHAR **argstart;
int *arglen, *cmdlen;
{
HOST_WIDEST_INT linsize;
register U_CHAR *numptr;
*arglen = 0;
SKIP_WHITE_SPACE (ibp);
if (ibp >= limit) return NULL;
linsize = limit - ibp;
if ((linsize >= 10) && !bcmp (ibp, "NOTREACHED", 10)) {
*cmdlen = 10;
return "NOTREACHED";
}
if ((linsize >= 8) && !bcmp (ibp, "ARGSUSED", 8)) {
*cmdlen = 8;
return "ARGSUSED";
}
if ((linsize >= 11) && !bcmp (ibp, "LINTLIBRARY", 11)) {
*cmdlen = 11;
return "LINTLIBRARY";
}
if ((linsize >= 7) && !bcmp (ibp, "VARARGS", 7)) {
*cmdlen = 7;
ibp += 7; linsize -= 7;
if ((linsize == 0) || ! ISDIGIT (*ibp)) return "VARARGS";
for (numptr = *argstart = ibp; (numptr < limit) && ISDIGIT (*numptr);
numptr++);
*arglen = numptr - *argstart;
return "VARARGS";
}
return NULL;
}
static void
rescan (op, output_marks)
FILE_BUF *op;
int output_marks;
{
register U_CHAR c;
register int ident_length = 0;
register int hash = 0;
FILE_BUF *ip;
register U_CHAR *ibp;
register U_CHAR *limit;
register U_CHAR *obp;
int redo_char = 0;
int concatenated = 0;
int start_line;
U_CHAR *beg_of_line;
#define POPMACRO \
do { ip->macro->type = T_MACRO; \
if (ip->free_ptr) free (ip->free_ptr); \
--indepth; } while (0)
#ifndef NEXT_CPP_SERVER
#define RECACHE \
do { ip = &instack[indepth]; \
ibp = ip->bufp; \
limit = ip->buf + ip->length; \
op->bufp = obp; \
check_expand (op, limit - ibp); \
beg_of_line = 0; \
obp = op->bufp; } while (0)
#else
#define RECACHE \
do { ip = &instack[indepth]; \
ibp = ip->bufp; \
limit = ip->buf + ip->length; \
op->bufp = obp; \
check_expand (op, limit - ibp); \
beg_of_line = ip->beg_of_line; \
obp = op->bufp; } while (0)
#endif
if (no_output && instack[indepth].fname != 0)
#ifndef NEXT_CPP_SERVER
skip_if_group (&instack[indepth], 1, NULL);
#else
skip_if_group (&instack[indepth], 1, op);
else if (segregate_output &&
(instack[indepth].file && instack[indepth].file->header_output))
skip_if_group (&instack[indepth], 1, op);
#endif
obp = op->bufp;
RECACHE;
beg_of_line = ibp;
if (*limit != 0)
abort ();
while (1) {
c = *ibp++;
*obp++ = c;
switch (c) {
case '\\':
if (*ibp == '\n' && !ip->macro) {
++ibp;
++ip->lineno;
--obp;
break;
}
if (!traditional)
goto randomchar;
if (ident_length > 0)
goto specialchar;
if (ibp < limit)
*obp++ = *ibp++;
break;
case '%':
if (ident_length || ip->macro || traditional)
goto randomchar;
while (*ibp == '\\' && ibp[1] == '\n') {
ibp += 2;
++ip->lineno;
}
if (*ibp != ':')
break;
case '#':
if (assertions_flag) {
if (ident_length)
goto specialchar;
obp[-1] = '#';
SKIP_WHITE_SPACE (ibp);
while (is_idchar[*ibp])
*obp++ = *ibp++;
SKIP_WHITE_SPACE (ibp);
if (*ibp == '(') {
ip->bufp = ibp;
#ifdef NEXT_CPP_SERVER
skip_paren_group (ip, op);
#else
skip_paren_group (ip);
#endif
bcopy ((char *) ibp, (char *) obp, ip->bufp - ibp);
obp += ip->bufp - ibp;
ibp = ip->bufp;
}
break;
}
if (ip->macro != 0)
goto randomchar;
if (! ip->fname) {
if (ip->buf != beg_of_line)
warning ("preprocessing directive not recognized within macro arg");
goto randomchar;
}
if (ident_length)
goto specialchar;
if (beg_of_line == 0)
goto randomchar;
{
U_CHAR *bp;
bp = beg_of_line;
if (!traditional) {
while (1) {
if (is_hor_space[*bp])
bp++;
else if (*bp == '\\' && bp[1] == '\n')
bp += 2;
else if (*bp == '/' && bp[1] == '*') {
bp += 2;
while (1)
{
if (*bp == '*')
{
if (bp[1] == '/')
{
bp += 2;
break;
}
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (bp, limit - bp);
if (length > 1)
bp += (length - 1);
#endif
}
bp++;
}
}
else break;
}
if (c == '%') {
if (bp[0] != '%')
break;
while (bp[1] == '\\' && bp[2] == '\n')
bp += 2;
if (bp + 1 != ibp)
break;
bp++;
ibp++;
}
}
if (bp + 1 != ibp)
goto randomchar;
}
--obp;
ip->bufp = ibp;
op->bufp = obp;
if (! handle_directive (ip, op)) {
#ifdef USE_C_ALLOCA
alloca (0);
#endif
if (no_output && instack[indepth].fname) {
#ifdef NEXT_CPP_SERVER
skip_if_group (&instack[indepth], 1, op);
#else
skip_if_group (&instack[indepth], 1, 0);
#endif
RECACHE;
beg_of_line = ibp;
break;
}
#ifdef NEXT_CPP_SERVER
else if (segregate_output &&
(instack[indepth].file &&
instack[indepth].file->header_output)) {
skip_if_group (&instack[indepth], 1, op);
RECACHE;
beg_of_line = ibp;
break;
}
#endif
*obp++ = '#';
SKIP_WHITE_SPACE (ibp);
if (is_idstart[*ibp])
{
*obp++ = *ibp++;
while (is_idchar[*ibp])
*obp++ = *ibp++;
}
goto randomchar;
}
#ifdef USE_C_ALLOCA
alloca (0);
#endif
if (no_output && instack[indepth].fname)
#ifndef NEXT_CPP_SERVER
skip_if_group (&instack[indepth], 1, 0);
#else
skip_if_group (&instack[indepth], 1, op);
else if (segregate_output && (instack[indepth].file &&
instack[indepth].file->header_output))
skip_if_group (&instack[indepth], 1, op);
#endif
obp = op->bufp;
RECACHE;
beg_of_line = ibp;
break;
case '\"':
case '\'':
if (ident_length) {
if (! (ident_length == 1 && hash == HASHSTEP (0, 'L')))
goto specialchar;
ident_length = hash = 0;
}
start_line = ip->lineno;
while (1) {
if (ibp >= limit) {
if (ip->macro != 0) {
POPMACRO;
RECACHE;
continue;
}
if (!traditional) {
error_with_line (line_for_error (start_line),
"unterminated string or character constant");
if (multiline_string_line) {
error_with_line (multiline_string_line,
"possible real start of unterminated constant");
multiline_string_line = 0;
}
}
break;
}
*obp++ = *ibp;
switch (*ibp++) {
case '\n':
++ip->lineno;
++op->lineno;
if (traditional) {
beg_of_line = ibp;
goto while2end;
}
if (c == '\'') {
error_with_line (line_for_error (start_line),
"unterminated character constant");
goto while2end;
}
if (multiline_string_line == 0) {
if (pedantic)
pedwarn_with_line (line_for_error (start_line),
"string constant runs past end of line");
multiline_string_line = ip->lineno - 1;
}
break;
case '\\':
if (*ibp == '\n') {
if (ip->macro)
*obp++ = '\n';
else
--obp;
++ibp;
++ip->lineno;
} else {
if (!ip->macro) {
while (*ibp == '\\' && ibp[1] == '\n') {
ibp += 2;
++ip->lineno;
}
}
*obp++ = *ibp++;
}
break;
case '\"':
case '\'':
if (ibp[-1] == c)
goto while2end;
break;
#ifdef MULTIBYTE_CHARS
default:
{
int length;
--ibp;
length = local_mblen (ibp, limit - ibp);
if (length > 0)
{
--obp;
bcopy (ibp, obp, length);
obp += length;
ibp += length;
}
else
++ibp;
}
break;
#endif
}
}
while2end:
break;
case '/':
if (ip->macro != 0)
goto randomchar;
if (*ibp == '\\' && ibp[1] == '\n')
newline_fix (ibp);
if (*ibp != '*'
&& !(cplusplus_comments && *ibp == '/'))
goto randomchar;
if (ident_length)
goto specialchar;
if (*ibp == '/') {
start_line = ip->lineno;
if (! put_out_comments)
obp[-1] = ' ';
{
U_CHAR *before_bp = ibp;
while (++ibp < limit) {
if (*ibp == '\n')
{
if (put_out_comments) {
bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
obp += ibp - before_bp;
}
break;
}
if (*ibp == '\\')
{
if (ibp + 1 < limit && ibp[1] == '\n')
{
if (warn_comments)
warning ("multiline `//' comment");
++ip->lineno;
if (!put_out_comments)
*obp++ = '\n';
++op->lineno;
++ibp;
}
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (ibp, limit - ibp);
if (length > 1)
ibp += (length - 1);
#endif
}
}
break;
}
}
start_line = ip->lineno;
++ibp;
if (for_lint) {
U_CHAR *argbp;
int cmdlen, arglen;
char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
if (lintcmd != NULL) {
op->bufp = obp;
check_expand (op, cmdlen + arglen + 14);
obp = op->bufp;
obp[-1] = '\n';
bcopy ("#pragma lint ", (char *) obp, 13);
obp += 13;
bcopy (lintcmd, (char *) obp, cmdlen);
obp += cmdlen;
if (arglen != 0) {
*(obp++) = ' ';
bcopy (argbp, (char *) obp, arglen);
obp += arglen;
}
op->bufp = obp;
output_line_directive (ip, op, 0, same_file);
check_expand (op, limit - ibp + 2);
obp = op->bufp;
*(obp++) = '/';
}
}
if (! put_out_comments) {
if (traditional)
obp--;
else
obp[-1] = ' ';
}
else
*obp++ = '*';
{
U_CHAR *before_bp = ibp;
for (;;) {
switch (*ibp++) {
case '*':
if (ibp[-2] == '/' && warn_comments)
warning ("`/*' within comment");
if (*ibp == '\\' && ibp[1] == '\n')
newline_fix (ibp);
if (*ibp == '/')
goto comment_end;
break;
case '\n':
++ip->lineno;
if (!put_out_comments)
*obp++ = '\n';
++op->lineno;
break;
case 0:
if (limit < ibp) {
error_with_line (line_for_error (start_line),
"unterminated comment");
goto limit_reached;
}
break;
#ifdef MULTIBYTE_CHARS
default:
{
int length;
length = local_mblen (ibp, limit - ibp);
if (length > 1)
ibp += (length - 1);
}
break;
#endif
}
}
comment_end:
ibp++;
if (put_out_comments) {
bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
obp += ibp - before_bp;
}
}
break;
case '$':
if (! is_idchar['$'])
goto randomchar;
if (pedantic)
pedwarn ("`$' in identifier");
goto letter;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (ident_length == 0) {
for (;;) {
if (!ip->macro) {
while (ibp[0] == '\\' && ibp[1] == '\n') {
++ip->lineno;
ibp += 2;
}
}
c = *ibp++;
if (!is_idchar[c] && c != '.') {
--ibp;
break;
}
*obp++ = c;
if (c == 'e' || c == 'E' || c == 'p' || c == 'P') {
if (!ip->macro) {
while (ibp[0] == '\\' && ibp[1] == '\n') {
++ip->lineno;
ibp += 2;
}
}
if (*ibp == '+' || *ibp == '-') {
*obp++ = *ibp++;
if (traditional || (c89 && (c == 'p' || c == 'P')))
break;
}
}
}
break;
}
case '_':
case 'a': case 'b': case 'c': case 'd': case 'e': 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 's': case 't': case 'u': case 'v': case 'w': case 'x':
case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E': 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 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z':
letter:
ident_length++;
hash = HASHSTEP (hash, c);
break;
case '\n':
if (ip->fname == 0 && *ibp == '-') {
if (! concatenated) {
ident_length = 0;
hash = 0;
}
ibp++;
if (!output_marks) {
obp--;
} else {
*obp++ = '-';
}
break;
}
else if (ip->macro != 0) {
if (is_space[*ibp]) {
if (ident_length > 0)
goto specialchar;
if (!output_marks) {
obp[-1] = *ibp++;
if (obp[-1] == '\n')
op->lineno++;
} else {
*obp++ = *ibp++;
}
} else abort ();
break;
}
if (ident_length > 0)
goto specialchar;
beg_of_line = ibp;
++ip->lineno;
++op->lineno;
if (ip->lineno != op->lineno) {
op->bufp = obp;
output_line_directive (ip, op, 1, same_file);
check_expand (op, limit - ibp);
obp = op->bufp;
}
break;
case 0:
if (ibp <= limit)
goto randomchar;
limit_reached:
if (ip->macro != 0) {
obp--;
ibp--;
if (traditional && ident_length
&& ! is_idchar[*instack[indepth - 1].bufp]) {
redo_char = 1;
goto randomchar;
}
POPMACRO;
RECACHE;
#ifdef NEXT_CPP_SERVER
if (mark_expansions && instack[indepth].beg_of_line) {
output_line_command (&instack[indepth], op, 0, leave_expansion);
obp = op->bufp;
}
#endif
break;
}
if (ident_length == 0) {
obp--;
ibp--;
op->bufp = obp;
ip->bufp = ibp;
goto ending;
}
specialchar:
ibp--;
obp--;
redo_char = 1;
default:
randomchar:
if (ident_length > 0) {
register HASHNODE *hp;
if (!pcp_outfile || pcp_inside_if) {
for (hp = hashtab[MAKE_POS (hash) % HASHSIZE]; hp != NULL;
hp = hp->next) {
if (hp->length == ident_length) {
int obufp_before_macroname;
int op_lineno_before_macroname;
register int i = ident_length;
register U_CHAR *p = hp->name;
register U_CHAR *q = obp - i;
int disabled;
if (! redo_char)
q--;
do {
if (*p++ != *q++)
goto hashcollision;
} while (--i);
#ifdef NEXT_CPP_SERVER
if (hp->type == T_MACRO && !hp->defined_within_module)
break;
#endif
if (! redo_char) {
ibp--;
obp--;
}
obufp_before_macroname = (obp - op->buf) - ident_length;
op_lineno_before_macroname = op->lineno;
if (hp->type == T_PCSTRING) {
pcstring_used (hp);
break;
}
disabled = hp->type == T_DISABLED;
if (disabled) {
#if 0
if (traditional)
error ("recursive use of macro `%s'", hp->name);
#endif
if (output_marks) {
check_expand (op, limit - ibp + 2);
*obp++ = '\n';
*obp++ = '-';
}
break;
}
if ((hp->type == T_MACRO || hp->type == T_DISABLED)
&& hp->value.defn->nargs >= 0)
{
U_CHAR *old_ibp = ibp;
U_CHAR *old_obp = obp;
int old_iln = ip->lineno;
int old_oln = op->lineno;
while (1) {
if (ibp == limit && ip->macro != 0) {
POPMACRO;
RECACHE;
old_ibp = ibp;
old_obp = obp;
old_iln = ip->lineno;
old_oln = op->lineno;
}
else if (is_space[*ibp]) {
*obp++ = *ibp++;
if (ibp[-1] == '\n') {
if (ip->macro == 0) {
++ip->lineno;
++op->lineno;
} else if (!output_marks) {
obp--;
if (*ibp == '-')
ibp++;
else {
if (*ibp == '\n')
++op->lineno;
*obp++ = *ibp++;
}
} else {
*obp++ = *ibp++;
}
}
}
else if (ip->macro)
break;
else if (*ibp == '/') {
if (ibp[1] == '\\' && ibp[2] == '\n')
newline_fix (ibp + 1);
if (ibp[1] == '*') {
if (put_out_comments) {
*obp++ = '/';
*obp++ = '*';
} else if (! traditional) {
*obp++ = ' ';
}
for (ibp += 2; ibp < limit; ibp++) {
if (ibp[0] == '*') {
if (ibp[1] == '\\' && ibp[2] == '\n')
newline_fix (ibp + 1);
if (ibp[1] == '/') {
ibp += 2;
if (put_out_comments) {
*obp++ = '*';
*obp++ = '/';
}
break;
}
}
else if (*ibp == '\n') {
++ip->lineno;
++op->lineno;
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (ibp, limit - ibp);
if (length > 1)
{
if (put_out_comments)
{
bcopy (ibp, obp, length - 1);
obp += length - 1;
}
ibp += (length - 1);
}
#endif
}
if (put_out_comments)
*obp++ = *ibp;
}
} else if (ibp[1] == '/' && cplusplus_comments) {
if (put_out_comments) {
*obp++ = '/';
*obp++ = '/';
} else if (! traditional) {
*obp++ = ' ';
}
for (ibp += 2; ; ibp++)
{
if (*ibp == '\n')
break;
if (*ibp == '\\' && ibp[1] == '\n')
{
if (put_out_comments)
*obp++ = *ibp++;
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (ibp, limit - ibp);
if (length > 1)
{
if (put_out_comments)
{
bcopy (ibp, obp, length - 1);
obp += length - 1;
}
ibp += (length - 1);
}
#endif
}
if (put_out_comments)
*obp++ = *ibp;
}
} else
break;
}
else if (ibp[0] == '\\' && ibp[1] == '\n') {
ibp += 2;
++ip->lineno;
}
else break;
}
if (*ibp != '(') {
ibp = old_ibp;
obp = old_obp;
ip->lineno = old_iln;
op->lineno = old_oln;
break;
}
}
obp = op->buf + obufp_before_macroname;
if (output_marks)
op->lineno = op_lineno_before_macroname;
else {
int newlines = op->lineno - op_lineno_before_macroname;
while (0 < newlines--)
*obp++ = '\n';
}
if (!traditional && obp != op->buf) {
switch (obp[-1]) {
case '!': case '%': case '&': case '*':
case '+': case '-': case '.': case '/':
case ':': case '<': case '=': case '>':
case '^': case '|':
if (output_marks)
*obp++ = '\n';
*obp++ = ' ';
}
}
ip->bufp = ibp;
op->bufp = obp;
#ifdef NEXT_CPP_SERVER
{
U_CHAR *start_exp = ip->bufp - ident_length;
#endif
macroexpand (hp, op);
#ifdef NEXT_CPP_SERVER
if (mark_expansions &&
(hp->type == T_DISABLED || hp->type == T_MACRO) &&
(indepth == 1 ||
(instack[indepth-1].fname && instack[indepth-1].file))) {
char *save_name = instack[indepth-1].nominal_fname;
char save_char = *ip->bufp;
instack[indepth-1].beg_of_line = beg_of_line;
instack[indepth-1].nominal_fname = start_exp;
*ip->bufp = '\0';
output_line_command (&instack[indepth-1], op, 0,
enter_expansion);
instack[indepth-1].nominal_fname = save_name;
*ip->bufp = save_char;
}
}
#endif
obp = op->bufp;
RECACHE;
break;
}
hashcollision:
;
}
}
ident_length = hash = 0;
redo_char = 0;
concatenated = 0;
}
}
}
ending:
if (if_stack != ip->if_stack)
{
char *str;
switch (if_stack->type)
{
case T_IF:
str = "if";
break;
case T_IFDEF:
str = "ifdef";
break;
case T_IFNDEF:
str = "ifndef";
break;
case T_ELSE:
str = "else";
break;
case T_ELIF:
str = "elif";
break;
default:
abort ();
}
error_with_line (line_for_error (if_stack->lineno),
"unterminated `#%s' conditional", str);
}
if_stack = ip->if_stack;
}
static FILE_BUF
expand_to_temp_buffer (buf, limit, output_marks, assertions)
U_CHAR *buf, *limit;
int output_marks, assertions;
{
register FILE_BUF *ip;
FILE_BUF obuf;
int length = limit - buf;
U_CHAR *buf1;
int odepth = indepth;
int save_assertions_flag = assertions_flag;
assertions_flag = assertions;
if (length < 0)
abort ();
buf1 = (U_CHAR *) alloca (length + 1);
{
register U_CHAR *p1 = buf;
register U_CHAR *p2 = buf1;
while (p1 != limit)
*p2++ = *p1++;
}
buf1[length] = 0;
obuf.length = length * 2 + 100;
obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length);
obuf.nominal_fname = 0;
obuf.inc = 0;
obuf.dir = 0;
obuf.fname = 0;
obuf.macro = 0;
obuf.if_stack = 0;
obuf.free_ptr = 0;
obuf.system_header_p = 0;
CHECK_DEPTH ({return obuf;});
++indepth;
ip = &instack[indepth];
ip->fname = 0;
ip->nominal_fname = 0;
ip->nominal_fname_len = 0;
ip->inc = 0;
ip->system_header_p = 0;
ip->macro = 0;
ip->free_ptr = 0;
ip->length = length;
ip->buf = ip->bufp = buf1;
ip->if_stack = if_stack;
#ifdef NEXT_CPP_SERVER
ip->dir = ip->file = 0;
ip->beg_of_line = 0;
#endif
ip->lineno = obuf.lineno = 1;
rescan (&obuf, output_marks);
--indepth;
if (indepth != odepth)
abort ();
obuf.length = obuf.bufp - obuf.buf;
assertions_flag = save_assertions_flag;
return obuf;
}
static int
handle_directive (ip, op)
FILE_BUF *ip, *op;
{
register U_CHAR *bp, *cp;
register struct directive *kt;
register int ident_length;
U_CHAR *resume_p;
int copy_directive = 0;
U_CHAR *ident, *after_ident;
bp = ip->bufp;
directive_start = bp - 1;
ignore_escape_flag = 1;
while (1) {
if (is_hor_space[*bp]) {
if (*bp != ' ' && *bp != '\t' && pedantic)
pedwarn_strange_white_space (*bp);
bp++;
} else if (*bp == '/') {
if (bp[1] == '\\' && bp[2] == '\n')
newline_fix (bp + 1);
if (! (bp[1] == '*' || (cplusplus_comments && bp[1] == '/')))
break;
ip->bufp = bp + 2;
#ifdef NEXT_CPP_SERVER
skip_to_end_of_comment (ip, op, &ip->lineno, 0);
#else
skip_to_end_of_comment (ip, &ip->lineno, 0);
#endif
bp = ip->bufp;
} else if (*bp == '\\' && bp[1] == '\n') {
bp += 2; ip->lineno++;
} else break;
}
cp = bp;
while (1) {
if (is_idchar[*cp])
cp++;
else {
if (*cp == '\\' && cp[1] == '\n')
name_newline_fix (cp);
if (is_idchar[*cp])
cp++;
else break;
}
}
ident_length = cp - bp;
ident = bp;
after_ident = cp;
if (ident_length == 0 && *after_ident == '\n') {
ip->bufp = after_ident;
return 1;
}
if (ident_length == 0 || !is_idstart[*ident]) {
U_CHAR *p = ident;
while (is_idchar[*p]) {
if (*p < '0' || *p > '9')
break;
p++;
}
if (p != ident && !is_idchar[*p]) {
static struct directive line_directive_table[] = {
{ 4, do_line, "line", T_LINE},
};
if (pedantic)
pedwarn ("`#' followed by integer");
after_ident = ident;
kt = line_directive_table;
ignore_escape_flag = 0;
goto old_linenum;
}
if (p == ident) {
while (*p == '#' || is_hor_space[*p]) p++;
if (*p == '\n') {
if (pedantic && !lang_asm)
warning ("invalid preprocessing directive");
return 0;
}
}
if (!lang_asm)
error ("invalid preprocessing directive name");
return 0;
}
for (kt = directive_table; kt->length > 0; kt++) {
if (kt->length == ident_length && !bcmp (kt->name, ident, ident_length)) {
register U_CHAR *buf;
register U_CHAR *limit;
int unterminated;
int junk;
int *already_output;
int keep_comments;
old_linenum:
limit = ip->buf + ip->length;
unterminated = 0;
already_output = 0;
keep_comments = traditional && kt->type == T_DEFINE;
#if !defined (NEXT_SEMANTICS) && !defined (NEXT_PDO)
if (kt->type == T_IMPORT
&& !(objc || lookup ((U_CHAR *) "__NeXT__", -1, -1)))
break;
#endif
buf = bp = after_ident;
while (bp < limit) {
register U_CHAR c = *bp++;
switch (c) {
case '\\':
if (bp < limit) {
if (*bp == '\n') {
ip->lineno++;
copy_directive = 1;
bp++;
} else if (traditional)
bp++;
}
break;
case '"':
if (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)) {
while (bp < limit && *bp != '\n') {
if (*bp == '"') {
bp++;
break;
}
if (*bp == '\\' && bp[1] == '\n') {
ip->lineno++;
copy_directive = 1;
bp++;
}
bp++;
}
break;
}
case '\'':
bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, ©_directive, &unterminated);
if (unterminated) {
if (traditional) {
ip->bufp = bp;
goto endloop1;
}
ip->bufp = bp;
return 1;
}
break;
case '<':
if (! IS_INCLUDE_DIRECTIVE_TYPE (kt->type))
break;
while (bp < limit && *bp != '>' && *bp != '\n') {
if (*bp == '\\' && bp[1] == '\n') {
ip->lineno++;
copy_directive = 1;
bp++;
}
bp++;
}
break;
case '/':
if (*bp == '\\' && bp[1] == '\n')
newline_fix (bp);
if (*bp == '*'
|| (cplusplus_comments && *bp == '/')) {
U_CHAR *obp = bp - 1;
ip->bufp = bp + 1;
#ifdef NEXT_CPP_SERVER
skip_to_end_of_comment (ip, op, &ip->lineno, 0);
#else
skip_to_end_of_comment (ip, &ip->lineno, 0);
#endif
bp = ip->bufp;
if (!put_out_comments) {
U_CHAR *p;
for (p = bp; *p == ' ' || *p == '\t'; p++)
continue;
if (*p == '\n') {
bp = obp;
goto endloop1;
}
}
if (! keep_comments)
copy_directive++;
}
break;
case '\f':
case '\r':
case '\v':
if (pedantic)
pedwarn_strange_white_space (c);
break;
case '\n':
--bp;
ip->bufp = bp;
goto endloop1;
}
}
ip->bufp = bp;
endloop1:
resume_p = ip->bufp;
if (!no_output && put_out_comments
&& ((kt->type == T_DEFINE || kt->type == T_UNDEF)
? dump_macros == dump_definitions
: IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes
: kt->type == T_PRAGMA)) {
int len;
check_expand (op, kt->length + 2);
if (op->bufp > op->buf && op->bufp[-1] != '\n') {
op->lineno++;
*op->bufp++ = '\n';
}
*op->bufp++ = '#';
bcopy (kt->name, op->bufp, kt->length);
op->bufp += kt->length;
len = (bp - buf);
check_expand (op, len);
bcopy (buf, (char *) op->bufp, len);
op->bufp += len;
while (--len >= 0)
if (buf[len] == '\n')
op->lineno++;
already_output = &junk;
}
if (copy_directive) {
register U_CHAR *xp = buf;
cp = (U_CHAR *) alloca (bp - buf + 5);
buf = cp;
while (xp < bp) {
register U_CHAR c = *xp++;
*cp++ = c;
switch (c) {
case '\n':
abort ();
break;
case '<':
if (! IS_INCLUDE_DIRECTIVE_TYPE (kt->type))
break;
while (xp < bp && c != '>') {
c = *xp++;
if (c == '\\' && xp < bp && *xp == '\n')
xp++;
else
*cp++ = c;
}
break;
case '\\':
if (*xp == '\n') {
xp++;
cp--;
if (cp != buf && is_hor_space[cp[-1]]) {
while (cp - 1 != buf && is_hor_space[cp[-2]])
cp--;
SKIP_WHITE_SPACE (xp);
} else if (is_hor_space[*xp]) {
*cp++ = *xp++;
SKIP_WHITE_SPACE (xp);
}
} else if (traditional && xp < bp) {
*cp++ = *xp++;
}
break;
case '\'':
case '\"':
{
int backslash_newlines_p;
register U_CHAR *bp1
= skip_quoted_string (xp - 1, bp, ip->lineno,
NULL_PTR, &backslash_newlines_p,
NULL_PTR);
if (backslash_newlines_p)
while (xp != bp1)
{
if (xp[0] == '\\' && xp[1] == '\n')
xp += 2;
else
*cp++ = *xp++;
}
else
while (xp != bp1)
*cp++ = *xp++;
}
break;
case '/':
if (*xp == '*'
|| (cplusplus_comments && *xp == '/')) {
ip->bufp = xp + 1;
#ifdef NEXT_CPP_SERVER
skip_to_end_of_comment (ip, op, already_output, 0);
#else
skip_to_end_of_comment (ip, already_output, 0);
#endif
if (keep_comments)
while (xp != ip->bufp)
*cp++ = *xp++;
else if (traditional)
cp--;
else
cp[-1] = ' ';
xp = ip->bufp;
}
}
}
*cp = 0;
} else
cp = bp;
ip->bufp = resume_p;
if (!no_output && already_output == 0
&& (kt->type == T_DEFINE ? (int) dump_names <= (int) dump_macros
: IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes
: kt->type == T_PRAGMA)) {
int len;
check_expand (op, kt->length + 1);
*op->bufp++ = '#';
bcopy (kt->name, (char *) op->bufp, kt->length);
op->bufp += kt->length;
if (kt->type == T_DEFINE && dump_macros == dump_names) {
U_CHAR *xp = buf;
U_CHAR *yp;
SKIP_WHITE_SPACE (xp);
yp = xp;
while (is_idchar[*xp]) xp++;
len = (xp - yp);
check_expand (op, len + 1);
*op->bufp++ = ' ';
bcopy (yp, (char *) op->bufp, len);
} else {
len = (cp - buf);
check_expand (op, len);
bcopy (buf, (char *) op->bufp, len);
}
op->bufp += len;
}
(*kt->func) (buf, cp, op, kt);
#ifdef NEXT_CPP_SERVER
if (segregate_output
&& (ip->file && !ip->file->header_output)) {
if (kt->func == do_include)
ip->file->position_after_last_include = ip->bufp;
else if (kt->func == do_if || kt->func == do_xifdef) {
ip->file->has_explicit_context_dependency = 1;
if (kt->type == T_IFNDEF && !ip->file->position_of_first_ifndef)
ip->file->position_of_first_ifndef = directive_start;
}
}
#endif
check_expand (op, ip->length - (ip->bufp - ip->buf));
return 1;
}
}
return 0;
}
static struct tm *
timestamp ()
{
static struct tm *timebuf;
if (!timebuf) {
time_t t = time ((time_t *) 0);
timebuf = localtime (&t);
}
return timebuf;
}
static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
static void
special_symbol (hp, op)
HASHNODE *hp;
FILE_BUF *op;
{
char *buf;
int i, len;
int true_indepth;
FILE_BUF *ip = NULL;
struct tm *timebuf;
int paren = 0;
if (pcp_outfile && pcp_inside_if
&& hp->type != T_SPEC_DEFINED && hp->type != T_CONST)
error ("Predefined macro `%s' used inside `#if' during precompilation",
hp->name);
for (i = indepth; i >= 0; i--)
if (instack[i].fname != NULL) {
ip = &instack[i];
break;
}
if (ip == NULL) {
error ("cccp error: not in any file?!");
return;
}
switch (hp->type) {
case T_FILE:
case T_BASE_FILE:
{
FILE_BUF *p = hp->type == T_FILE ? ip : &instack[0];
char *string = p->nominal_fname;
if (string)
{
size_t string_len = p->nominal_fname_len;
buf = (char *) alloca (3 + 4 * string_len);
quote_string (buf, string, string_len);
}
else
buf = "\"\"";
break;
}
case T_INCLUDE_LEVEL:
true_indepth = 0;
for (i = indepth; i >= 0; i--)
if (instack[i].fname != NULL)
true_indepth++;
buf = (char *) alloca (8);
sprintf (buf, "%d", true_indepth - 1);
break;
case T_VERSION:
buf = (char *) alloca (3 + strlen (version_string));
sprintf (buf, "\"%s\"", version_string);
break;
#ifndef NO_BUILTIN_SIZE_TYPE
case T_SIZE_TYPE:
buf = SIZE_TYPE;
break;
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
case T_PTRDIFF_TYPE:
buf = PTRDIFF_TYPE;
break;
#endif
case T_WCHAR_TYPE:
buf = wchar_type;
break;
case T_USER_LABEL_PREFIX_TYPE:
buf = user_label_prefix;
break;
case T_REGISTER_PREFIX_TYPE:
buf = REGISTER_PREFIX;
break;
case T_IMMEDIATE_PREFIX_TYPE:
buf = IMMEDIATE_PREFIX;
break;
case T_CONST:
buf = hp->value.cpval;
#ifdef STDC_0_IN_SYSTEM_HEADERS
if (ip->system_header_p
&& hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0
&& !lookup ((U_CHAR *) "__STRICT_ANSI__", -1, -1))
buf = "0";
#endif
if (pcp_inside_if && pcp_outfile)
fprintf (pcp_outfile, "#define %s %s\n", hp->name, buf);
break;
case T_SPECLINE:
buf = (char *) alloca (10);
sprintf (buf, "%d", ip->lineno);
break;
case T_DATE:
case T_TIME:
buf = (char *) alloca (20);
timebuf = timestamp ();
if (hp->type == T_DATE)
sprintf (buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
timebuf->tm_mday, timebuf->tm_year + 1900);
else
sprintf (buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
timebuf->tm_sec);
break;
case T_SPEC_DEFINED:
#ifdef APPLE_EXTENSION
case T_SPEC_OPTION:
#endif
buf = " 0 ";
ip = &instack[indepth];
SKIP_WHITE_SPACE (ip->bufp);
if (*ip->bufp == '(') {
paren++;
ip->bufp++;
SKIP_WHITE_SPACE (ip->bufp);
}
if (!is_idstart[*ip->bufp])
goto oops;
if (ip->bufp[0] == 'L' && (ip->bufp[1] == '\'' || ip->bufp[1] == '"'))
goto oops;
#ifdef APPLE_EXTENSION
if (hp->type == T_SPEC_OPTION) {
U_CHAR *iptr = ip->bufp,
*optr;
U_CHAR *kwd;
if (!paren)
goto oops;
kwd = (char *)alloca(strlen(ip->bufp));
optr = kwd;
while (is_idchar[*iptr])
*optr++ = *iptr++;
*optr = 0;
SKIP_WHITE_SPACE (iptr);
if (*iptr != ')')
goto oops;
if (check__option(kwd, optr - kwd))
buf = " 1 ";
}
else
#endif
if ((hp = lookup (ip->bufp, -1, -1))) {
if (pcp_outfile && pcp_inside_if
&& (hp->type == T_CONST
|| (hp->type == T_MACRO && hp->value.defn->predefined)))
fprintf (pcp_outfile, "#define %s\n", hp->name);
buf = " 1 ";
}
else
if (pcp_outfile && pcp_inside_if) {
U_CHAR *cp = ip->bufp;
fprintf (pcp_outfile, "#undef ");
while (is_idchar[*cp])
fputc (*cp++, pcp_outfile);
putc ('\n', pcp_outfile);
}
while (is_idchar[*ip->bufp])
++ip->bufp;
SKIP_WHITE_SPACE (ip->bufp);
if (paren) {
if (*ip->bufp != ')')
goto oops;
++ip->bufp;
}
break;
oops:
#ifdef APPLE_EXTENSION
error ((hp->type == T_SPEC_DEFINED) ? "`defined' without an identifier"
: "malformed `__option(identifier)'");
#else
error ("`defined' without an identifier");
#endif
break;
default:
error ("cccp error: invalid special hash type");
abort ();
}
len = strlen (buf);
check_expand (op, len);
bcopy (buf, (char *) op->bufp, len);
op->bufp += len;
return;
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
struct import_file {
#ifdef NEXT_CPP_SERVER
struct file_name_list *name;
int visited_within_module;
time_t modtime;
#else
char *name;
#endif
ino_t inode;
dev_t dev;
#if defined (_WIN32) && defined (NEXT_PDO)
_off_t size;
time_t mtime;
time_t ctime;
#endif
struct import_file *next;
};
typedef enum {
NON_EXISTENT_HEADER,
GOOD_HEADER,
REDUNDANT_HEADER
} header_type;
#ifdef NEXT_CPP_SERVER
static header_type try_include_file (path, importing, pf, pimpfile, pstatbuf)
const char * path;
int importing;
int * pf;
struct import_file ** pimpfile;
struct stat * pstatbuf;
{
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" trying %s...", path);
#endif
if (found_in_negative_cache(path)) {
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" not found (by negative cache)\n");
#endif
return NON_EXISTENT_HEADER;
} else {
struct import_file * impfile = 0;
int f = -1;
if (importing) {
f = lookup_import (path, pstatbuf, &impfile);
} else {
redundant_include_p (path, &impfile);
if (impfile)
f = -2;
else
f = open (path, O_RDONLY, 0666);
}
if (f == -2) {
if ((importing && impfile->visited_within_module)
|| (!importing
&& ((!segregate_output && impfile->name->control_macro)
|| (segregate_output && impfile->name->control_macro
&& impfile->visited_within_module))))
{
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" FOUND (redundant header)\n");
#endif
if (flag_dump_symbols)
printf ("+Fi %s\n", path);
if (flag_gen_index)
dump_symbol_info ("+Fi ", path, -1);
return REDUNDANT_HEADER;
}
}
else if (f == -1) {
add_to_negative_cache(savestring(path));
}
else if (!importing) {
if (impfile && impfile->name->control_macro &&
lookup (impfile->name->control_macro, -1, -1))
{
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" FOUND (redundant header)\n");
#endif
if (flag_dump_symbols)
printf ("+Fi %s\n", path);
if (flag_gen_index)
dump_symbol_info ("+Fi ", path, -1);
return REDUNDANT_HEADER;
}
}
if (impfile) {
*pf = f;
*pimpfile = impfile;
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" FOUND\n");
#endif
if (flag_dump_symbols)
printf ("+Fi %s\n", path);
if (flag_gen_index)
dump_symbol_info ("+Fi ", path, -1);
return GOOD_HEADER;
}
if (f >= 0) {
if (!importing)
fstat (f, pstatbuf);
*pf = f;
*pimpfile = impfile;
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" FOUND\n");
#endif
if (flag_dump_symbols)
printf ("+Fi %s\n", path);
if (flag_gen_index)
dump_symbol_info ("+Fi ", path, -1);
return GOOD_HEADER;
}
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" not found\n");
#endif
return NON_EXISTENT_HEADER;
}
}
#endif
#endif
#ifdef APPLE_CPP_HEADER_MAPS
#define HMAP_SAME_ENDIANNESS_MAGIC (((((('h' << 8) | 'm') << 8) | 'a') << 8) | 'p')
#define HMAP_OPPOSITE_ENDIANNESS_MAGIC (((((('p' << 8) | 'a') << 8) | 'm') << 8) | 'h')
#define HMAP_NOT_A_KEY 0x00000000
#if !defined(uint32)
typedef unsigned short uint16;
typedef unsigned long uint32;
#endif
struct hmap_bucket
{
uint32 key;
struct {
uint32 prefix;
uint32 suffix;
} value;
};
struct hmap_header_map
{
uint32 magic;
uint16 version;
uint16 _reserved;
uint32 strings_offset;
uint32 count;
uint32 capacity;
uint32 max_value_length;
struct hmap_bucket buckets[0];
char strings[0];
};
static inline uint32 hmap_hash_string (str_beg, str_end)
const char * str_beg;
const char * str_end;
{
register const char * sp;
register unsigned hash_code = 0;
for (sp = str_beg; sp < str_end; sp++)
hash_code += tolower(*(const unsigned char *)sp) * 13;
return hash_code;
}
static inline unsigned hmap_compare_strings (str1_beg, str1_end, str2)
const char * str1_beg;
const char * str1_end;
const char * str2;
{
register const char * s1p;
register const char * s2p;
for (s1p = str1_beg, s2p = str2; s1p < str1_end && *s2p != '\0'; s1p++, s2p++)
{
if (tolower(*s1p) != tolower(*s2p))
return 0;
}
return (s1p == str1_end && *s2p == '\0');
}
static struct hmap_header_map * hmap_load_header_map (filename)
const char * filename;
{
struct hmap_header_map * headermap = NULL;
if (filename != NULL && filename[0] != '\0')
{
FILE * f;
struct stat f_info;
f = fopen(filename, "rb");
if (f != NULL)
{
if (fstat(fileno(f), &f_info) == 0)
{
unsigned headermap_size = f_info.st_size;
headermap = (struct hmap_header_map *)xmalloc(headermap_size);
if (fread(headermap, 1, headermap_size, f) != headermap_size)
{
perror(filename);
free(headermap);
headermap = NULL;
}
if (headermap->magic == HMAP_OPPOSITE_ENDIANNESS_MAGIC)
{
fprintf(stderr, "headermap \"%s\" has incompatible endianness\n",
filename);
free(headermap);
headermap = NULL;
}
else if (headermap->magic != HMAP_SAME_ENDIANNESS_MAGIC)
{
fprintf(stderr, "\"%s\" is not a headermap file (bad magic: 0x%08lx)\n",
filename, headermap->magic);
free(headermap);
headermap = NULL;
}
}
else
perror(filename);
fclose(f);
}
else
perror(filename);
}
return headermap;
}
static void hmap_free_header_map (headermap)
struct hmap_header_map * headermap;
{
if (headermap != NULL)
free(headermap);
}
static void hmap_lookup (headermap, filename_beg, filename_end)
struct hmap_header_map * headermap;
char ** filename_beg;
char ** filename_end;
{
if (headermap != NULL && *filename_beg != NULL && *filename_end != NULL)
{
register const char * strings;
register struct hmap_bucket * buckets;
register uint32 bucket_mask;
register uint32 i;
register uint32 key_offset;
strings = ((const char *)headermap) + headermap->strings_offset;
buckets = headermap->buckets;
bucket_mask = headermap->capacity-1;
i = hmap_hash_string(*filename_beg, *filename_end) & bucket_mask;
while ((key_offset = buckets[i].key) != HMAP_NOT_A_KEY)
{
if (hmap_compare_strings(*filename_beg, *filename_end, strings+key_offset))
{
static char * hmap_path_result_buffer = NULL;
register const char * sp;
register char * dp;
if (hmap_path_result_buffer == NULL)
hmap_path_result_buffer = xmalloc(headermap->max_value_length+1);
dp = hmap_path_result_buffer;
sp = strings+buckets[i].value.prefix;
while (*sp != '\0')
*dp++ = *sp++;
sp = strings+buckets[i].value.suffix;
while (*sp != '\0')
*dp++ = *sp++;
*dp = '\0';
*filename_beg = hmap_path_result_buffer;
*filename_end = dp;
}
i = (i + 1) & bucket_mask;
}
}
}
#endif
#ifdef APPLE_CPP_INCLUSION_LOGS
static void ilog_printf (const char * format, ...)
{
va_list ap;
va_start(ap, format);
if (inclusion_log_file)
vfprintf(inclusion_log_file, format, ap);
va_end(ap);
}
static void ilog_write (const char * chars, unsigned length)
{
if (inclusion_log_file)
fwrite(chars, 1, length, inclusion_log_file);
}
#endif
static int
do_include (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword;
{
U_CHAR *importing = keyword->type == T_IMPORT ? (U_CHAR *) "" : (U_CHAR *) 0;
int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
#ifdef NEXT_OBJC_RUNTIME
static int import_warning = 1;
#else
static int import_warning = 0;
#endif
char *fname;
char *pcftry;
char *pcfname;
char *fbeg, *fend;
U_CHAR *fin;
#ifdef NEXT_FRAMEWORKS
# define MAX_FILENAME_LEN 256
char extendedPath[MAX_FILENAME_LEN];
U_CHAR *bufptr;
int hasSlash;
#endif
struct file_name_list *search_start = include;
struct file_name_list *dsp;
struct file_name_list *searchptr = 0;
size_t flen;
int f = -3;
struct include_file *inc = 0;
int retried = 0;
int angle_brackets = 0;
#ifdef VMS
int vaxc_include = 0;
#endif
int pcf = -1;
char *pcfbuf;
char *pcfbuflimit;
int pcfnum;
#ifdef APPLE_CPP_HEADER_MAPS
int filename_already_mapped = 0;
#endif
#ifdef NEXT_OBJC_RUNTIME
U_CHAR *partial = NULL;
int plen = 0;
#endif
#ifdef NEXT_CPP_SERVER
header_type hdr_result;
struct stat shared_stat_f;
#endif
#if defined (NEXT_CPP_SERVER) || defined (NEXT_FRAMEWORKS)
struct import_file *impfile = 0;
#endif
if (pedantic && !instack[indepth].system_header_p)
{
if (importing)
pedwarn ("ANSI C does not allow `#import'");
if (skip_dirs)
pedwarn ("ANSI C does not allow `#include_next'");
}
if (importing && warn_import && !inhibit_warnings
&& !instack[indepth].system_header_p && !import_warning) {
import_warning = 1;
warning ("using `#import' is not recommended");
notice ("The fact that a certain header file need not be processed more than once\n\
should be indicated in the header file, not where it is used.\n\
The best way to do this is with a conditional of this form:\n\
\n\
#ifndef _FOO_H_INCLUDED\n\
#define _FOO_H_INCLUDED\n\
... <real contents of file> ...\n\
#endif /* Not _FOO_H_INCLUDED */\n\
\n\
Then users can use `#include' any number of times.\n\
GNU C automatically avoids processing the file more than once\n\
when it is equipped with such a conditional.\n");
}
get_filename:
fin = buf;
SKIP_WHITE_SPACE (fin);
while (limit != fin && is_hor_space[limit[-1]]) limit--;
fbeg = fend = (char *) alloca (limit - fin);
switch (*fin++) {
case '\"':
{
FILE_BUF *fp;
{
for (;;) {
for (;;) {
if (fin == limit)
goto invalid_include_file_name;
*fend = *fin++;
if (*fend == '"')
break;
fend++;
}
if (fin == limit)
break;
while (fin != limit && is_hor_space[*fin]) fin++;
if (fin != limit && *fin == '\"')
fin++;
else
goto fail;
}
}
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" %s \"", importing ? "#import" : "#include");
ilog_write(fbeg, fend-fbeg);
ilog_printf("\":\n");
#endif
if (ignore_srcdir) break;
for (fp = &instack[indepth]; fp >= instack; fp--)
{
int n;
char *nam;
if ((nam = fp->nominal_fname) != NULL) {
dsp = ((struct file_name_list *)
alloca (sizeof (struct file_name_list)
+ fp->nominal_fname_len));
strcpy (dsp->fname, nam);
simplify_filename (dsp->fname);
nam = base_name (dsp->fname);
*nam = 0;
#ifdef VMS
if (nam == dsp->fname)
{
*nam++ = '.';
*nam++ = '/';
*nam = 0;
}
#endif
dsp->next = search_start;
if (!search_start || strcmp (dsp->fname, search_start->fname)) {
search_start = dsp;
n = nam - dsp->fname;
if (n + INCLUDE_LEN_FUDGE > max_include_len)
max_include_len = n + INCLUDE_LEN_FUDGE;
}
dsp[0].got_name_map = 0;
break;
}
}
break;
}
case '<':
while (fin != limit && *fin != '>')
*fend++ = *fin++;
if (*fin == '>' && fin + 1 == limit) {
angle_brackets = 1;
#ifdef NEXT_FRAMEWORKS
flen = fend -fbeg;
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" %s <", importing ? "#import" : "#include");
ilog_write(fbeg, fend-fbeg);
ilog_printf(">:\n");
#endif
hasSlash = 0;
for (bufptr = (U_CHAR *) fbeg; bufptr != (U_CHAR *) fend; bufptr++)
if (*bufptr == '/') {
hasSlash++;
break;
}
if (hasSlash) {
#ifdef APPLE_CPP_HEADER_MAPS
char *old_fbeg = fbeg, *old_fend = fend;
hmap_lookup (header_map, &fbeg, &fend);
#ifdef APPLE_CPP_INCLUSION_LOGS
if (fbeg != old_fbeg)
{
ilog_printf (" remapping ");
ilog_write (fbeg, old_fend - old_fbeg);
ilog_printf (" to ");
ilog_write (fbeg, fend - fbeg);
ilog_printf ("\n");
}
#endif
filename_already_mapped = TRUE;
#endif
extendedPath[0] = '\0';
for (searchptr = framework;
f < 0 && searchptr != 0;
searchptr = searchptr->next) {
U_CHAR *end, *headerNameTo, *headerNameFrom;
int index;
#ifdef APPLE_CPP_HEADER_MAPS
if (*fbeg == '/') {
memcpy(extendedPath, fbeg, fend-fbeg);
extendedPath[fend-fbeg] = '\0';
} else {
#endif
strcpy(extendedPath, searchptr->fname);
end = &extendedPath[strlen(extendedPath)];
*end++ = '/';
for (bufptr = (U_CHAR *) fbeg;
*bufptr != '/' && bufptr != (U_CHAR *) fend;
bufptr++)
*end++ = *bufptr;
strncpy(end, ".framework/", 11); end += 11;
#ifdef APPLE_CPP_HEADER_MAPS
}
#endif
for (index = 0; framework_header_dirs[index].dirName; index++) {
#ifdef APPLE_CPP_HEADER_MAPS
if (*fbeg != '/') {
#endif
strncpy(end,
framework_header_dirs[index].dirName,
framework_header_dirs[index].dirNameLen);
headerNameTo = end + framework_header_dirs[index].dirNameLen;
for (headerNameFrom = bufptr; headerNameFrom != (U_CHAR *) fend; headerNameFrom++)
*headerNameTo++ = *headerNameFrom;
*headerNameTo = '\0';
#ifdef APPLE_CPP_HEADER_MAPS
}
#endif
#ifdef NEXT_CPP_SERVER
hdr_result = try_include_file(extendedPath, importing, &f, &impfile, &shared_stat_f);
if (hdr_result == REDUNDANT_HEADER)
return 0;
else if (hdr_result == GOOD_HEADER)
break;
#if 0
if (!found_in_negative_cache(extendedPath)) {
impfile = 0;
if (importing)
f = lookup_import (extendedPath, &shared_stat_f, &impfile);
else {
redundant_include_p (extendedPath, &impfile);
if (!impfile)
f = open (extendedPath, O_RDONLY, 0666);
else
f = -2;
}
if (f == -2) {
if (segregate_output &&
impfile->visited_within_module &&
impfile->name &&
!impfile->name->has_explicit_context_dependency) {
return 0;
}
}
else if (f == -1) {
add_to_negative_cache(savestring(extendedPath));
}
else if (!importing) {
if (impfile && impfile->name->control_macro &&
lookup (impfile->name->control_macro, -1, -1))
return 0;
}
if (f >= 0 || impfile) {
if (!importing)
fstat (f, &shared_stat_f);
break;
}
}
#endif 0
#else
{
char *xp = xmalloc (strlen (extendedPath) + 1);
strcpy (xp, extendedPath);
f = open_include_file (xp, searchptr, importing, &inc);
}
if (f == -2)
return 0;
#ifdef EACCES
else if (f == -1 && errno == EACCES)
warning ("Header file %s exists, but is not readable",
extendedPath);
#endif
else if (f >= 0)
break;
#endif
}
}
if ( f == -1 )
{
int i;
for (i=indepth; i >= 0; i--)
{
const char* parent_include = instack[i].fname;
if (parent_include != NULL)
{
int header_dir_index;
struct file_name_list* a_framework;
const char* parent_end = NULL;
for (a_framework = framework; a_framework;
a_framework = a_framework->next)
if (!strncmp (parent_include, a_framework->fname,
strlen (a_framework->fname)))
parent_end =
&parent_include[strlen(a_framework->fname)];
if ( parent_end != NULL )
{
int flen = strlen (".framework/");
for ( ; *parent_end != '\0'; ++parent_end)
if (!strncmp (parent_end, ".framework/", flen))
{
char* p;
const char* src_ptr;
char* p_end;
parent_end += flen;
strncpy (extendedPath, parent_include,
parent_end - parent_include);
p = &extendedPath[parent_end - parent_include];
strcpy (p, "Frameworks/");
p += strlen ("Frameworks/");
for (src_ptr = fbeg;
(*src_ptr != '/') && (src_ptr != fend);
*p++ = *src_ptr++)
;
strcpy (p, ".framework/");
p += strlen (".framework/");
p_end = p;
for (header_dir_index = 0;
framework_header_dirs[header_dir_index].dirName;
header_dir_index++)
{
const char *fname_ptr;
p = p_end;
strcpy (p, framework_header_dirs[header_dir_index].dirName);
p += framework_header_dirs[header_dir_index].dirNameLen;
for (fname_ptr = src_ptr;
(*fname_ptr != '\0') && (fname_ptr != fend);
fname_ptr++)
*p++ = *fname_ptr;
*p = '\0';
{
char *xp =
xmalloc (strlen (extendedPath) + 1);
strcpy (xp, extendedPath);
f = open_include_file (xp, searchptr,
importing, &inc);
}
if (f == -2)
return 0;
#ifdef EACCES
else if (f == -1 && errno == EACCES)
warning ("Header file %s exists, but is not readable", extendedPath);
#endif
else if (f >= 0)
goto found_recursive;
}
}
}
}
}
found_recursive:
break;
}
}
#endif
search_start = first_bracket_include;
break;
}
goto fail;
default:
#ifdef VMS
if (retried && (--fin, ISALPHA(*(U_CHAR *) (fin)))) {
while (fin != limit && (!ISSPACE(*fin)))
*fend++ = *fin++;
warning ("VAX-C-style include specification found, use '#include <filename.h>' !");
vaxc_include = 1;
if (fin == limit) {
angle_brackets = 1;
search_start = first_bracket_include;
break;
}
}
#endif
fail:
if (! retried) {
FILE_BUF trybuf;
U_CHAR *src;
int errors_before_expansion = errors;
trybuf = expand_to_temp_buffer (buf, limit, 1, 0);
if (errors != errors_before_expansion) {
free (trybuf.buf);
goto invalid_include_file_name;
}
src = trybuf.buf;
buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
limit = buf;
while (src != trybuf.bufp) {
switch ((*limit++ = *src++)) {
case '\n':
limit--;
src++;
break;
case '\'':
case '\"':
{
U_CHAR *src1 = skip_quoted_string (src - 1, trybuf.bufp, 0,
NULL_PTR, NULL_PTR, NULL_PTR);
while (src != src1)
*limit++ = *src++;
}
break;
}
}
*limit = 0;
free (trybuf.buf);
retried = 1;
goto get_filename;
}
invalid_include_file_name:
error ("`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
return 0;
}
if (skip_dirs) {
FILE_BUF *fp;
for (fp = &instack[indepth]; fp >= instack; fp--)
if (fp->fname != NULL) {
if (fp->dir)
search_start = fp->dir->next;
break;
}
}
*fend = 0;
flen = simplify_filename (fbeg);
if (flen == 0)
{
error ("empty file name in `#%s'", keyword->name);
return 0;
}
#ifdef NEXT_FRAMEWORKS
if (f > 0 || impfile) {
fname = savestring(extendedPath);
goto found_in_framework;
}
#endif
fname = xmalloc (max_include_len + flen + 1);
system_include_depth += angle_brackets;
if (absolute_filename (fbeg)) {
strcpy (fname, fbeg);
f = open_include_file (fname, NULL_PTR, importing, &inc);
} else {
struct bypass_dir {
struct bypass_dir *next;
char *fname;
struct file_name_list *searchptr;
} **bypass_slot = 0;
for (searchptr = search_start; searchptr; searchptr = searchptr->next) {
#ifdef APPLE_CPP_HEADER_MAPS
char *old_fbeg = fbeg, *old_fend = fend;
if (searchptr == first_bracket_include
&& header_map != NULL && !filename_already_mapped)
hmap_lookup (header_map, &fbeg, &fend);
if (fbeg != old_fbeg)
{
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf (" remapping ");
ilog_write (fbeg, old_fend - old_fbeg);
ilog_printf (" to ");
ilog_write (fbeg, fend - fbeg);
ilog_printf ("\n");
#endif
flen = fend - fbeg;
free (fname);
fname = (char *) xmalloc (max_include_len + flen + 4);
fname[0] = '\0';
}
else
{
#endif
if (searchptr == first_bracket_include) {
static struct bypass_dir *bypass_hashtab[INCLUDE_HASHSIZE];
struct bypass_dir *p;
bypass_slot = &bypass_hashtab[hashf ((U_CHAR *) fbeg, flen,
INCLUDE_HASHSIZE)];
for (p = *bypass_slot; p; p = p->next)
if (!strcmp (fbeg, p->fname)) {
searchptr = p->searchptr;
bypass_slot = 0;
break;
}
}
#ifdef VMS
if (searchptr->fname[0])
{
strcpy (fname, searchptr->fname);
if (fname[strlen (fname) - 1] == ':')
{
char *slashp;
slashp = strchr (fbeg, '/');
if (slashp == 0)
strcat (fname, "[000000]");
}
strcat (fname, fbeg);
hack_vms_include_specification (fname, vaxc_include);
}
else
{
strcpy (fname, fbeg);
if (vaxc_include && index(fname,'.')==NULL)
strcat (fname, ".h");
}
#else
strcpy (fname, searchptr->fname);
#ifdef APPLE_CPP_HEADER_MAPS
}
#endif
strcat (fname, fbeg);
#endif
f = open_include_file (fname, searchptr, importing, &inc);
if (f != -1) {
if (bypass_slot && searchptr != first_bracket_include) {
struct bypass_dir *p
= (struct bypass_dir *) xmalloc (sizeof (struct bypass_dir));
p->next = *bypass_slot;
p->fname = fname + strlen (searchptr->fname);
p->searchptr = searchptr;
*bypass_slot = p;
}
break;
}
#ifdef VMS
if (errno == EACCES)
break;
#else
if (errno != ENOENT && errno != ENOTDIR)
break;
#endif
}
}
#ifdef NEXT_FRAMEWORKS
found_in_framework:
#endif
#ifdef NEXT_CPP_SERVER
if (f < 0 && !impfile) {
#else
if (f < 0) {
#endif
if (f == -2) {
} else if (print_deps_missing_files
&& (system_include_depth != 0) < print_deps)
{
if (angle_brackets)
{
if (search_start) {
char *p = (char *) alloca (strlen (search_start->fname)
+ strlen (fbeg) + 1);
strcpy (p, search_start->fname);
strcat (p, fbeg);
deps_output (p, ' ');
}
}
else
{
deps_output (fbeg, ' ');
}
}
else if (0 < print_deps && print_deps <= (system_include_depth != 0))
warning ("No include path in which to find %s", fbeg);
else if (f != -3)
error_from_errno (fbeg);
else
error ("No include path in which to find %s", fbeg);
} else {
pcftry = (char *) alloca (strlen (fname) + 30);
pcfbuf = 0;
pcfnum = 0;
if (!no_precomp)
{
do {
sprintf (pcftry, "%s%d", fname, pcfnum++);
pcf = open (pcftry, O_RDONLY, 0666);
if (pcf != -1)
{
struct stat s;
if (fstat (pcf, &s) != 0)
pfatal_with_name (pcftry);
if (! INO_T_EQ (inc->st.st_ino, s.st_ino)
|| inc->st.st_dev != s.st_dev)
{
pcfbuf = check_precompiled (pcf, &s, fname, &pcfbuflimit);
close (pcf);
}
else
{
close (pcf);
break;
}
}
} while (pcf != -1 && !pcfbuf);
}
if (pcfbuf) {
pcfname = xmalloc (strlen (pcftry) + 1);
strcpy (pcfname, pcftry);
#ifndef NEXT_CPP_SERVER
pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) fname, op);
#else
pcfinclude (pcfbuf, pcfbuflimit, ptr->fname, op);
#endif
}
else
finclude (f, inc, op, is_system_include (fname), searchptr);
}
system_include_depth -= angle_brackets;
return 0;
}
static int
is_system_include (filename)
register char *filename;
{
struct file_name_list *searchptr;
for (searchptr = first_system_include; searchptr;
searchptr = searchptr->next)
if (! strncmp (searchptr->fname, filename, strlen (searchptr->fname)))
return searchptr->c_system_include_path + 1;
return 0;
}
static char *
base_name (fname)
char *fname;
{
char *s = fname;
char *p;
#if defined (__MSDOS__) || defined (_WIN32)
if (ISALPHA (s[0]) && s[1] == ':') s += 2;
#endif
#ifdef VMS
if ((p = rindex (s, ':'))) s = p + 1;
if ((p = rindex (s, ']'))) s = p + 1;
if ((p = rindex (s, '>'))) s = p + 1;
if (s != fname)
return s;
#endif
if ((p = rindex (s, '/'))) s = p + 1;
#ifdef DIR_SEPARATOR
if ((p = rindex (s, DIR_SEPARATOR))) s = p + 1;
#endif
return s;
}
static int
absolute_filename (filename)
char *filename;
{
#if defined (__MSDOS__) \
|| (defined (_WIN32) && !defined (__CYGWIN__) && !defined (_UWIN))
if (ISALPHA (filename[0]) && filename[1] == ':') filename += 2;
#endif
#if defined (__CYGWIN__)
if (ISALPHA (filename[0]) && filename[1] == ':') return 1;
#endif
#ifdef VMS
if (index (filename, ':') != 0) return 1;
#endif
if (filename[0] == '/') return 1;
#ifdef DIR_SEPARATOR
if (filename[0] == DIR_SEPARATOR) return 1;
#endif
return 0;
}
static inline
int
is_dir_separator(ch)
char ch;
{
return (ch == DIR_SEPARATOR)
#if defined (DIR_SEPARATOR_2)
|| (ch == DIR_SEPARATOR_2)
#endif
;
}
static size_t
simplify_filename (filename)
char *filename;
{
register char *from = filename;
register char *to = filename;
char *to0;
if (is_dir_separator (*from))
{
*to++ = DIR_SEPARATOR;
if (is_dir_separator (*++from))
{
if (is_dir_separator (*++from))
{
while (is_dir_separator (*++from))
continue;
}
else
{
*to++ = DIR_SEPARATOR;
}
}
}
to0 = to;
for (;;)
{
#ifndef VMS
if (from[0] == '.' && from[1] == '/')
from += 2;
else
#endif
{
while (!is_dir_separator (*to++ = *from++))
{
if (!to[-1])
{
to -= filename <= to - 3 && to[-3] == DIR_SEPARATOR && to[-2] == '.';
while (to0 < --to && to[-1] == DIR_SEPARATOR)
continue;
*to = 0;
return to - filename;
}
}
#if defined(DIR_SEPARATOR_2)
to[-1] = DIR_SEPARATOR;
#endif
}
while (is_dir_separator (*from))
from++;
}
}
struct file_name_map
{
struct file_name_map *map_next;
char *map_from;
char *map_to;
};
#define FILE_NAME_MAP_FILE "header.gcc"
static char *
read_filename_string (ch, f)
int ch;
FILE *f;
{
char *alloc, *set;
int len;
len = 20;
set = alloc = xmalloc (len + 1);
if (! is_space[ch])
{
*set++ = ch;
while ((ch = getc (f)) != EOF && ! is_space[ch])
{
if (set - alloc == len)
{
len *= 2;
alloc = xrealloc (alloc, len + 1);
set = alloc + len / 2;
}
*set++ = ch;
}
}
*set = '\0';
ungetc (ch, f);
return alloc;
}
static struct file_name_map *
read_name_map (dirname)
char *dirname;
{
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;
size_t dirlen;
for (map_list_ptr = 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;
map_list_ptr = ((struct file_name_map_list *)
xmalloc (sizeof (struct file_name_map_list)));
map_list_ptr->map_list_name = xstrdup (dirname);
map_list_ptr->map_list_map = NULL;
dirlen = strlen (dirname);
name = (char *) alloca (dirlen + strlen (FILE_NAME_MAP_FILE) + 1);
strcpy (name, dirname);
strcat (name, FILE_NAME_MAP_FILE);
f = fopen (name, "r");
if (!f)
map_list_ptr->map_list_map = NULL;
else
{
int ch;
while ((ch = getc (f)) != EOF)
{
char *from, *to;
struct file_name_map *ptr;
size_t tolen;
if (is_space[ch])
continue;
from = read_filename_string (ch, f);
while ((ch = getc (f)) != EOF && is_hor_space[ch])
;
to = read_filename_string (ch, f);
simplify_filename (from);
tolen = simplify_filename (to);
ptr = ((struct file_name_map *)
xmalloc (sizeof (struct file_name_map)));
ptr->map_from = from;
if (absolute_filename (to))
ptr->map_to = to;
else
{
ptr->map_to = xmalloc (dirlen + tolen + 1);
strcpy (ptr->map_to, dirname);
strcat (ptr->map_to, to);
free (to);
}
ptr->map_next = map_list_ptr->map_list_map;
map_list_ptr->map_list_map = ptr;
while ((ch = getc (f)) != '\n')
if (ch == EOF)
break;
}
fclose (f);
}
map_list_ptr->map_list_next = map_list;
map_list = map_list_ptr;
return map_list_ptr->map_list_map;
}
static int
open_include_file (filename, searchptr, importing, pinc)
char *filename;
struct file_name_list *searchptr;
U_CHAR *importing;
struct include_file **pinc;
{
char *fname = remap ? remap_include_file (filename, searchptr) : filename;
int fd = -2;
struct include_file **phead = &include_hashtab[hashf ((U_CHAR *) fname,
strlen (fname),
INCLUDE_HASHSIZE)];
struct include_file *inc, *head = *phead;
for (inc = head; inc; inc = inc->next)
if (!strcmp (fname, inc->fname))
break;
#ifdef NEXT_SEMANTICS
if (inc && importing)
fd = -2;
else
#endif
if (!inc
|| ! inc->control_macro
|| (inc->control_macro[0] && ! lookup (inc->control_macro, -1, -1))) {
fd = open (fname, O_RDONLY, 0);
if (fd < 0)
{
#ifdef VMS
if (!hack_vms_include_specification (fname, 0))
return fd;
fd = open (fname, O_RDONLY, 0);
if (fd < 0)
#endif
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" open_include('%s') Failed.\n", fname);
#endif
return fd;
}
#ifdef APPLE_CPP_INCLUSION_LOGS
ilog_printf(" open_include('%s') Success!\n", fname);
#endif
if (!inc) {
inc = (struct include_file *) xmalloc (sizeof (struct include_file));
inc->next = head;
inc->fname = fname;
inc->control_macro = 0;
inc->deps_output = 0;
if (fstat (fd, &inc->st) != 0)
pfatal_with_name (fname);
*phead = inc;
if (lookup_ino_include (inc)
&& inc->control_macro
&& (!inc->control_macro[0] || lookup (inc->control_macro, -1, -1))) {
close (fd);
fd = -2;
}
}
if (! inc->deps_output && (system_include_depth != 0) < print_deps) {
inc->deps_output = 1;
deps_output (fname, ' ');
}
if (print_include_names)
fprintf (stderr, "%*s%s\n", indepth, "", fname);
}
if (importing)
inc->control_macro = importing;
*pinc = inc;
return fd;
}
static char *
remap_include_file (filename, searchptr)
char *filename;
struct file_name_list *searchptr;
{
register struct file_name_map *map;
register char *from;
if (searchptr)
{
if (! searchptr->got_name_map)
{
searchptr->name_map = read_name_map (searchptr->fname);
searchptr->got_name_map = 1;
}
from = filename + strlen (searchptr->fname);
for (map = searchptr->name_map; map; map = map->map_next)
if (! strcmp (map->map_from, from))
return map->map_to;
}
from = base_name (filename);
if (from != filename || !searchptr)
{
char *dir = (char *) alloca (from - filename + 1);
bcopy (filename, dir, from - filename);
dir[from - filename] = '\0';
for (map = read_name_map (dir); map; map = map->map_next)
if (! strcmp (map->map_from, from))
return map->map_to;
}
return filename;
}
static int
lookup_ino_include (inc)
struct include_file *inc;
{
int hash = ((unsigned) (inc->st.st_dev + INO_T_HASH (inc->st.st_ino))
% INCLUDE_HASHSIZE);
struct include_file *i = include_ino_hashtab[hash];
inc->next_ino = i;
include_ino_hashtab[hash] = inc;
for (; i; i = i->next_ino)
if (INO_T_EQ (inc->st.st_ino, i->st.st_ino)
&& inc->st.st_dev == i->st.st_dev) {
inc->control_macro = i->control_macro;
return 1;
}
return 0;
}
static void
#ifndef NEXT_CPP_SERVER
finclude (f, inc, op, system_header_p, dirptr)
#else
finclude (f, inc, op, system_header_p, dirptr, fileptr, sb)
struct file_name_list *fileptr;
struct stat *sb;
#endif
int f;
struct include_file *inc;
FILE_BUF *op;
int system_header_p;
struct file_name_list *dirptr;
{
char *fname = inc->fname;
int i;
FILE_BUF *fp;
int missing_newline = 0;
#ifdef NEXT_CPP_SERVER
int check_for_duplicate = 0;
U_CHAR *position_of_file_start;
unsigned int file_length;
#ifdef SEPARATE_USER_AND_SYS_HEADERS
FILE_BUF * header_buf = system_header_p ? &sys_header_outbuf
: &user_header_outbuf;
#else
FILE_BUF * header_buf = &sys_header_outbuf;
#endif
#endif
CHECK_DEPTH (return;);
if (flag_gen_index)
dump_symbol_info ("+Fi ", fname, -1);
if (flag_check_indexed_header_list)
process_header_indexing (fname, PB_INDEX_BEGIN);
if (flag_dump_symbols)
printf ("+Fm %s\n", fname);
if (flag_gen_index)
dump_symbol_info ("+Fm ", fname, -1);
fp = &instack[indepth + 1];
bzero ((char *) fp, sizeof (FILE_BUF));
fp->nominal_fname = fp->fname = fname;
fp->nominal_fname_len = strlen (fname);
fp->inc = inc;
fp->length = 0;
fp->lineno = 1;
fp->if_stack = if_stack;
fp->system_header_p = system_header_p;
fp->dir = dirptr;
#ifdef NEXT_CPP_SERVER
fp->file = fileptr;
if (fileptr && fileptr->buf && fileptr->length) {
fp->buf = fileptr->buf;
fp->length = fileptr->length;
if (fileptr->control_macro && fileptr->position_of_first_ifndef)
fp->bufp = fileptr->position_of_first_ifndef;
else
fp->bufp = fileptr->buf;
goto dorescan;
}
#endif
if (S_ISREG (inc->st.st_mode)) {
size_t s = (size_t) inc->st.st_size;
if (s != inc->st.st_size || s + 2 < s)
memory_full ();
fp->buf = (U_CHAR *) xmalloc (s + 2);
fp->bufp = fp->buf;
fp->length = safe_read (f, (char *) fp->buf, s);
if (fp->length < 0) goto nope;
}
else if (S_ISDIR (inc->st.st_mode)) {
error ("directory `%s' specified in #include", fname);
close (f);
return;
} else {
int bsize = 2000;
int st_size = 0;
fp->buf = (U_CHAR *) xmalloc (bsize + 2);
for (;;) {
i = safe_read (f, (char *) fp->buf + st_size, bsize - st_size);
if (i < 0)
goto nope;
st_size += i;
if (st_size != bsize)
break;
bsize *= 2;
fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
}
fp->bufp = fp->buf;
fp->length = st_size;
}
if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n')
|| (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) {
fp->buf[fp->length++] = '\n';
missing_newline = 1;
}
fp->buf[fp->length] = '\0';
close (f);
#ifdef NEXT_CPP_SERVER
dorescan:
if (fileptr) {
fileptr->buf = fp->buf;
fileptr->length = fp->length;
}
#endif
indepth++;
input_file_stack_tick++;
if (!no_trigraphs)
trigraph_pcp (fp);
#ifdef NEXT_SEMANTICS
if (!no_rtf)
buf_convert_rtf (fp);
#endif
#ifdef NEXT_CPP_SERVER
if (segregate_output) {
output_line_command (fp, &outbuf, 0, enter_file);
if (fileptr->header_output &&
fileptr->has_explicit_context_dependency &&
(fileptr->control_macro == 0 && fileptr->ever_included)) {
check_for_duplicate = 1;
fileptr->header_output = 0;
}
position_of_file_start = header_buf->bufp;
output_line_command (fp, header_buf, 0, enter_file);
rescan (header_buf, 0);
} else
#endif
{
output_line_directive (fp, op, 0, enter_file);
rescan (op, 0);
}
if (missing_newline)
fp->lineno--;
if (pedantic && missing_newline)
pedwarn ("file does not end in newline");
if (flag_dump_symbols)
printf ("*Fm %s\n", fname);
if (flag_gen_index)
dump_symbol_info ("*Fm ", fname, -1);
if (flag_check_indexed_header_list)
process_header_indexing (fname, PB_INDEX_END);
indepth--;
input_file_stack_tick++;
#ifdef NEXT_CPP_SERVER
if (segregate_output) {
file_length = header_buf->bufp - position_of_file_start;
if (indepth)
output_line_command (&instack[indepth], header_buf, 0, leave_file);
else
output_line_command (&instack[indepth], &outbuf, 0, enter_file);
if (check_for_duplicate) {
if (duplicate_version_of_header(header_buf,
fileptr, position_of_file_start, file_length)) {
header_buf->bufp = position_of_file_start;
} else {
add_version_of_header(fileptr,
position_of_file_start - header_buf->buf,
file_length);
}
fileptr->header_output = 1;
} else if (!fileptr->header_output) {
fileptr->relative_position_of_file_start =
position_of_file_start - header_buf->buf;
fileptr->file_length = file_length;
fileptr->header_output = 1;
}
} else
#endif
output_line_directive (&instack[indepth], op, 0, leave_file);
#ifndef NEXT_CPP_SERVER
free (fp->buf);
#endif
return;
nope:
perror_with_name (fname);
close (f);
free (fp->buf);
}
static void
record_control_macro (inc, macro_name)
struct include_file *inc;
U_CHAR *macro_name;
{
if (!inc->control_macro || inc->control_macro[0])
inc->control_macro = macro_name;
}
static char *
check_precompiled (pcf, st, fname, limit)
int pcf;
struct stat *st;
char *fname ATTRIBUTE_UNUSED;
char **limit;
{
int length = 0;
char *buf;
char *cp;
if (pcp_outfile)
return 0;
if (S_ISREG (st->st_mode))
{
size_t s = (size_t) st->st_size;
if (s != st->st_size || s + 2 < s)
memory_full ();
buf = xmalloc (s + 2);
length = safe_read (pcf, buf, s);
if (length < 0)
goto nope;
}
else
abort ();
if (length > 0 && buf[length-1] != '\n')
buf[length++] = '\n';
buf[length] = '\0';
*limit = buf + length;
if (!check_preconditions (buf))
goto nope;
for (cp = buf; *cp; cp++)
;
#ifdef DEBUG_PCP
fprintf (stderr, "Using preinclude %s\n", fname);
#endif
return cp + 1;
nope:
#ifdef DEBUG_PCP
fprintf (stderr, "Cannot use preinclude %s\n", fname);
#endif
free (buf);
return 0;
}
static int
check_preconditions (prec)
char *prec;
{
MACRODEF mdef;
char *lineend;
while (*prec) {
lineend = index (prec, '\n');
if (*prec++ != '#') {
error ("Bad format encountered while reading precompiled file");
return 0;
}
if (!strncmp (prec, "define", 6)) {
HASHNODE *hp;
#ifdef NEXT_CPP_SERVER
int hashcode;
#endif
prec += 6;
#ifdef NEXT_CPP_SERVER
mdef = create_definition ((U_CHAR *) prec, (U_CHAR *) lineend, NULL_PTR, &hashcode, 0);
#else
mdef = create_definition ((U_CHAR *) prec, (U_CHAR *) lineend, NULL_PTR);
#endif
if (mdef.defn == 0)
abort ();
#ifdef NEXT_CPP_SERVER
if ((hp = lookup (mdef.symnam, mdef.symlen, hashcode)) == NULL
#else
if ((hp = lookup (mdef.symnam, mdef.symlen, -1)) == NULL
#endif
|| (hp->type != T_MACRO && hp->type != T_CONST)
|| (hp->type == T_MACRO
&& !compare_defs (mdef.defn, hp->value.defn)
&& (mdef.defn->length != 2
|| mdef.defn->expansion[0] != '\n'
|| mdef.defn->expansion[1] != ' ')))
return 0;
} else if (!strncmp (prec, "undef", 5)) {
char *name;
int len;
prec += 5;
while (is_hor_space[(U_CHAR) *prec])
prec++;
name = prec;
while (is_idchar[(U_CHAR) *prec])
prec++;
len = prec - name;
if (lookup ((U_CHAR *) name, len, -1))
return 0;
} else {
error ("Bad format encountered while reading precompiled file");
return 0;
}
prec = lineend + 1;
}
return 1;
}
static void
pcfinclude (buf, name, op)
U_CHAR *buf, *name;
FILE_BUF *op;
{
FILE_BUF tmpbuf;
int nstrings;
U_CHAR *cp = buf;
nstrings = *cp++;
nstrings = (nstrings << 8) | *cp++;
nstrings = (nstrings << 8) | *cp++;
nstrings = (nstrings << 8) | *cp++;
while (nstrings--) {
U_CHAR *string_start;
U_CHAR *endofthiskey;
STRINGDEF *str;
int nkeys;
if ((size_t) cp & 3)
cp += 4 - ((size_t) cp & 3);
str = (STRINGDEF *) (GENERIC_PTR) cp;
string_start = cp += sizeof (STRINGDEF);
for (; *cp; cp++)
;
tmpbuf = expand_to_temp_buffer (string_start, cp++, 0, 0);
str->contents = tmpbuf.buf;
str->len = tmpbuf.length;
str->writeflag = 0;
str->filename = name;
#ifdef NEXT_CPP_SERVER
str->output_mark = op->bufp - op->buf;
#else
str->output_mark = outbuf.bufp - outbuf.buf;
#endif
str->chain = 0;
*stringlist_tailp = str;
stringlist_tailp = &str->chain;
nkeys = *cp++;
nkeys = (nkeys << 8) | *cp++;
nkeys = (nkeys << 8) | *cp++;
nkeys = (nkeys << 8) | *cp++;
if (nkeys == -1)
str->writeflag = 1;
else
for (; nkeys--; free (tmpbuf.buf), cp = endofthiskey + 1) {
KEYDEF *kp = (KEYDEF *) (GENERIC_PTR) cp;
HASHNODE *hp;
cp += sizeof (KEYDEF);
endofthiskey = cp + strlen ((char *) cp);
kp->str = str;
tmpbuf = expand_to_temp_buffer (cp, endofthiskey, 0, 0);
tmpbuf.bufp = tmpbuf.buf;
while (is_hor_space[*tmpbuf.bufp])
tmpbuf.bufp++;
if (!is_idstart[*tmpbuf.bufp]
|| tmpbuf.bufp == tmpbuf.buf + tmpbuf.length) {
str->writeflag = 1;
continue;
}
hp = lookup (tmpbuf.bufp, -1, -1);
if (hp == NULL) {
kp->chain = 0;
install (tmpbuf.bufp, -1, T_PCSTRING, (char *) kp, -1);
}
else if (hp->type == T_PCSTRING) {
kp->chain = hp->value.keydef;
hp->value.keydef = kp;
}
else
str->writeflag = 1;
}
}
output_line_directive (&instack[indepth], op, 0, enter_file);
}
static void
pcstring_used (hp)
HASHNODE *hp;
{
KEYDEF *kp;
for (kp = hp->value.keydef; kp; kp = kp->chain)
kp->str->writeflag = 1;
delete_macro (hp);
}
static void
#ifdef NEXT_CPP_SERVER
write_output (op, path, write_all)
FILE_BUF *op;
const char * path;
int write_all;
#else
write_output (path)
const char * path;
#endif
{
STRINGDEF *next_string;
U_CHAR *cur_buf_loc;
int line_directive_len = 80;
char *line_directive = xmalloc (line_directive_len);
int len;
#ifdef NEXT_CPP_SERVER
int output_fd;
FILE * outs;
if (!strcmp(path,"stdout"))
output_fd = fileno(stdout);
else
output_fd = open (path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
if (output_fd < 0) {
fatal("Could not write file %s", path);
return;
}
cur_buf_loc = write_all ? op->buf : op->output_written_to;
next_string = stringlist;
while (cur_buf_loc < op->bufp || next_string) {
if (next_string
&& cur_buf_loc - op->buf == next_string->output_mark) {
#else
if (flag_dump_symbols) {
if (!out_fname || !strcmp (out_fname, ""))
out_fname = "stdout";
else if (!freopen (out_fname, "w", stdout))
pfatal_with_name (out_fname);
}
cur_buf_loc = outbuf.buf;
next_string = stringlist;
while (cur_buf_loc < outbuf.bufp || next_string) {
if (next_string
&& cur_buf_loc - outbuf.buf == next_string->output_mark) {
#endif
if (next_string->writeflag) {
len = 4 * strlen ((char *) next_string->filename) + 32;
while (len > line_directive_len)
line_directive = xrealloc (line_directive,
line_directive_len *= 2);
sprintf (line_directive, "\n# %d ", next_string->lineno);
strcpy (quote_string (line_directive + strlen (line_directive),
(char *) next_string->filename,
strlen ((char *) next_string->filename)),
"\n");
#ifdef NEXT_CPP_SERVER
safe_write (output_fd, line_directive, strlen (line_directive));
safe_write (output_fd, next_string->contents, next_string->len);
#else
safe_write (fileno (stdout), line_directive, strlen (line_directive));
safe_write (fileno (stdout),
(char *) next_string->contents, next_string->len);
#endif
}
next_string = next_string->chain;
}
else {
len = (next_string
? (next_string->output_mark
#ifdef NEXT_CPP_SERVER
- (cur_buf_loc - op->buf))
: op->bufp - cur_buf_loc);
safe_write (output_fd, cur_buf_loc, len);
#else
- (cur_buf_loc - outbuf.buf))
: outbuf.bufp - cur_buf_loc);
safe_write (fileno (stdout), (char *) cur_buf_loc, len);
#endif
cur_buf_loc += len;
}
}
free (line_directive);
#ifdef NEXT_CPP_SERVER
#if 0
while (fsync(output_fd)) {
fprintf(stderr, "error calling fsync(%d) in ", output_fd);
perror_with_name(path);
break;
}
#endif
if (strcmp (path, "stdout") != 0 && close(output_fd)) {
fprintf(stderr, "error calling close(%d) in ", output_fd);
perror_with_name(path);
}
op->output_written_to = cur_buf_loc;
#endif
}
#ifdef NEXT_CPP_SERVER
static int
write_header_output (const char * output_fname,
FILE_BUF * op,
int write_all,
int report)
{
int result;
if (write_all || (op->output_written_to < op->bufp)) {
write_output (op, output_fname, write_all);
if (report)
fprintf(stderr,"wrote headers to %s\n", output_fname);
result = 1;
} else {
if (report)
fprintf(stderr,"did not write headers to %s\n", output_fname);
result = 0;
}
fflush(stderr);
return result;
}
#endif NEXT_CPP_SERVER
static void
pass_thru_directive (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword;
{
register int keyword_length = keyword->length;
check_expand (op, 1 + keyword_length + (limit - buf));
*op->bufp++ = '#';
bcopy (keyword->name, (char *) op->bufp, keyword_length);
op->bufp += keyword_length;
if (limit != buf && buf[0] != ' ')
*op->bufp++ = ' ';
bcopy ((char *) buf, (char *) op->bufp, limit - buf);
op->bufp += (limit - buf);
#if 0
*op->bufp++ = '\n';
op->lineno++;
#endif
}
struct arglist {
struct arglist *next;
U_CHAR *name;
int length;
int argno;
char rest_args;
};
#ifdef APPLE_EXTENSION
static int check__option(kwdname, kwdlen)
U_CHAR *kwdname;
int kwdlen;
{
struct arglist token;
token.next = NULL;
token.name = kwdname;
token.length = (kwdlen > 0) ? kwdlen : strlen(kwdname);
token.argno = 0;
token.rest_args = 0;
return check_assertion("__option", 8, 1, &token);
}
#endif
static MACRODEF
#ifndef NEXT_CPP_SERVER
create_definition (buf, limit, op)
#else
create_definition (buf, limit, op, hashcode, hashp)
int *hashcode;
HASHNODE **hashp;
#endif
U_CHAR *buf, *limit;
FILE_BUF *op;
{
U_CHAR *bp;
U_CHAR *symname;
int sym_length;
int line = instack[indepth].lineno;
char *file = instack[indepth].nominal_fname;
size_t file_len = instack[indepth].nominal_fname_len;
int rest_args = 0;
DEFINITION *defn;
int arglengths = 0;
MACRODEF mdef;
bp = buf;
while (is_hor_space[*bp])
bp++;
symname = bp;
sym_length = check_macro_name (bp, 0);
bp += sym_length;
#ifdef NEXT_CPP_SERVER
if (hashp) {
HASHNODE *hp;
*hashcode = hashf (symname, sym_length, HASHSIZE);
if ((hp = lookup (symname, sym_length, *hashcode)) != NULL) {
*hashp = hp;
if (hp->type == T_MACRO) {
if (strcmp(file, hp->value.defn->file) == 0 &&
line == hp->value.defn->line) {
defn = hp->value.defn;
goto reusedefn;
}
}
}
}
#endif
if (*bp == '(') {
struct arglist *arg_ptrs = NULL;
int argno = 0;
bp++;
SKIP_WHITE_SPACE (bp);
while (*bp != ')') {
struct arglist *temp;
temp = (struct arglist *) alloca (sizeof (struct arglist));
temp->name = bp;
temp->next = arg_ptrs;
temp->argno = argno++;
temp->rest_args = 0;
arg_ptrs = temp;
if (rest_args)
pedwarn ("another parameter follows `%s'",
rest_extension);
if (!is_idstart[*bp])
{
if (c9x && limit - bp > (long) REST_EXTENSION_LENGTH
&& bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)
{
rest_args = 1;
temp->rest_args = 1;
}
else
pedwarn ("invalid character in macro parameter name");
}
while (is_idchar[*bp]) {
bp++;
if (limit - bp > (long) REST_EXTENSION_LENGTH
&& bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
if (pedantic && !instack[indepth].system_header_p)
pedwarn ("ANSI C does not allow macro with variable arguments");
rest_args = 1;
temp->rest_args = 1;
break;
}
}
if (bp == temp->name && rest_args == 1)
{
temp->name = (U_CHAR *) va_args_name;
temp->length = VA_ARGS_NAME_LENGTH;
}
else
temp->length = bp - temp->name;
if (rest_args == 1)
bp += REST_EXTENSION_LENGTH;
arglengths += temp->length + 2;
SKIP_WHITE_SPACE (bp);
if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
error ("badly punctuated parameter list in `#define'");
goto nope;
}
if (*bp == ',') {
bp++;
SKIP_WHITE_SPACE (bp);
if (!is_idstart[*bp]
&& !(c9x && limit - bp > (long) REST_EXTENSION_LENGTH
&& bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0)) {
error ("badly punctuated parameter list in `#define'");
goto nope;
}
}
if (bp >= limit) {
error ("unterminated parameter list in `#define'");
goto nope;
}
{
struct arglist *otemp;
for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
if (temp->length == otemp->length
&& bcmp (temp->name, otemp->name, temp->length) == 0)
{
error ("duplicate argument name `%.*s' in `#define'",
temp->length, temp->name);
goto nope;
}
if (rest_args == 0 && temp->length == VA_ARGS_NAME_LENGTH
&& bcmp (temp->name, va_args_name, VA_ARGS_NAME_LENGTH) == 0)
{
error ("\
reserved name `%s' used as argument name in `#define'", va_args_name);
goto nope;
}
}
}
++bp;
SKIP_WHITE_SPACE (bp);
defn = collect_expansion (bp, limit, argno, arg_ptrs);
defn->rest_args = rest_args;
defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1);
{
struct arglist *temp;
int i = 0;
for (temp = arg_ptrs; temp; temp = temp->next) {
bcopy (temp->name, &defn->args.argnames[i], temp->length);
i += temp->length;
if (temp->next != 0) {
defn->args.argnames[i++] = ',';
defn->args.argnames[i++] = ' ';
}
}
defn->args.argnames[i] = 0;
}
} else {
if (bp < limit)
{
if (is_hor_space[*bp]) {
bp++;
SKIP_WHITE_SPACE (bp);
} else if (sym_length) {
switch (*bp) {
case '!': case '"': case '#': case '%': case '&': case '\'':
case ')': case '*': case '+': case ',': case '-': case '.':
case '/': case ':': case ';': case '<': case '=': case '>':
case '?': case '[': case '\\': case ']': case '^': case '{':
case '|': case '}': case '~':
warning ("missing white space after `#define %.*s'",
sym_length, symname);
break;
default:
pedwarn ("missing white space after `#define %.*s'",
sym_length, symname);
break;
}
}
}
defn = collect_expansion (bp, limit, -1, NULL_PTR);
defn->args.argnames = (U_CHAR *) "";
}
defn->line = line;
defn->file = file;
defn->file_len = file_len;
defn->predefined = !op;
#ifdef NEXT_CPP_SERVER
reusedefn:
#endif
mdef.defn = defn;
mdef.symnam = symname;
mdef.symlen = sym_length;
return mdef;
nope:
mdef.defn = 0;
return mdef;
}
static int
do_define (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword;
{
int hashcode;
MACRODEF mdef;
#ifdef NEXT_CPP_SERVER
HASHNODE *hp = 0;
#endif
if (pcp_outfile && op)
pass_thru_directive (buf, limit, op, keyword);
#ifdef NEXT_CPP_SERVER
mdef = create_definition (buf, limit, op, &hashcode, &hp);
#else
mdef = create_definition (buf, limit, op);
#endif
if (mdef.defn == 0)
goto nope;
if (flag_dump_symbols)
printf ("+Mh %*.*s %u\n", mdef.symlen, mdef.symlen, mdef.symnam,
instack[indepth].lineno);
if (flag_gen_index)
{
char buf[mdef.symlen+1];
sprintf (&buf[0],"%*.*s",mdef.symlen, mdef.symlen, mdef.symnam);
dump_symbol_info ("+Mh ", buf, instack[indepth].lineno);
}
#ifdef NEXT_CPP_SERVER
if (hp) {
if (hp->value.defn == mdef.defn) {
hp->defined_within_module = 1;
} else {
#else
hashcode = hashf (mdef.symnam, mdef.symlen, HASHSIZE);
{
HASHNODE *hp;
if ((hp = lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL) {
#endif
int ok = 0;
if (hp->type == T_PCSTRING)
ok = 1;
else if (hp->type == T_MACRO)
{
ok = ! compare_defs (mdef.defn, hp->value.defn);
#ifdef NEXT_CPP_SERVER
if (!ok && !hp->defined_within_module) {
hp->value.defn = mdef.defn;
ok = 1;
}
hp->defined_within_module = 1;
#endif
}
else if (hp->type == T_CONST)
ok = ! done_initializing;
if (!ok) {
if (debug_output && op)
pass_thru_directive (buf, limit, op, keyword);
pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam);
if (hp->type == T_MACRO)
pedwarn_with_file_and_line (hp->value.defn->file,
hp->value.defn->file_len,
hp->value.defn->line,
"this is the location of the previous definition");
}
hp->type = T_MACRO;
hp->value.defn = mdef.defn;
#ifdef NEXT_CPP_SERVER
}
#endif
} else {
if (debug_output && op)
pass_thru_directive (buf, limit, op, keyword);
#ifdef NEXT_CPP_SERVER
hp = install (mdef.symnam, mdef.symlen, T_MACRO,
(char *) mdef.defn, hashcode);
if (segregate_output &&
instack[indepth].file && !instack[indepth].file->macro_list) {
hp->owner = instack[indepth].file;
hp->owner->macro_count++;
}
#else
install (mdef.symnam, mdef.symlen, T_MACRO,
(char *) mdef.defn, hashcode);
}
#endif
}
return 0;
nope:
return 1;
}
static int
check_macro_name (symname, assertion)
U_CHAR *symname;
int assertion;
{
U_CHAR *p;
int sym_length;
for (p = symname; is_idchar[*p]; p++)
;
sym_length = p - symname;
if (sym_length == 0
|| (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
error (assertion ? "invalid assertion name" : "invalid macro name");
else if (!is_idstart[*symname]
|| (sym_length == 7 && ! bcmp (symname, "defined", 7)))
error ((assertion
? "invalid assertion name `%.*s'"
: "invalid macro name `%.*s'"),
sym_length, symname);
return sym_length;
}
static int
compare_defs (d1, d2)
DEFINITION *d1, *d2;
{
register struct reflist *a1, *a2;
register U_CHAR *p1 = d1->expansion;
register U_CHAR *p2 = d2->expansion;
int first = 1;
if (d1->nargs != d2->nargs)
return 1;
if (pedantic
&& strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
return 1;
for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
a1 = a1->next, a2 = a2->next) {
if (!((a1->nchars == a2->nchars && ! bcmp (p1, p2, a1->nchars))
|| ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
|| a1->argno != a2->argno
|| a1->stringify != a2->stringify
|| a1->raw_before != a2->raw_before
|| a1->raw_after != a2->raw_after)
return 1;
first = 0;
p1 += a1->nchars;
p2 += a2->nchars;
}
if (a1 != a2)
return 1;
if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
p2, d2->length - (p2 - d2->expansion), 1))
return 1;
return 0;
}
static int
comp_def_part (first, beg1, len1, beg2, len2, last)
int first;
U_CHAR *beg1, *beg2;
int len1, len2;
int last;
{
register U_CHAR *end1 = beg1 + len1;
register U_CHAR *end2 = beg2 + len2;
if (first) {
while (beg1 != end1 && is_space[*beg1]) beg1++;
while (beg2 != end2 && is_space[*beg2]) beg2++;
}
if (last) {
while (beg1 != end1 && is_space[end1[-1]]) end1--;
while (beg2 != end2 && is_space[end2[-1]]) end2--;
}
while (beg1 != end1 && beg2 != end2) {
if (is_space[*beg1] && is_space[*beg2]) {
while (beg1 != end1 && is_space[*beg1]) beg1++;
while (beg2 != end2 && is_space[*beg2]) beg2++;
} else if (*beg1 == *beg2) {
beg1++; beg2++;
} else break;
}
return (beg1 != end1) || (beg2 != end2);
}
static DEFINITION *
collect_expansion (buf, end, nargs, arglist)
U_CHAR *buf, *end;
int nargs;
struct arglist *arglist;
{
DEFINITION *defn;
register U_CHAR *p, *limit, *lastp, *exp_p;
struct reflist *endpat = NULL;
U_CHAR *concat = 0;
U_CHAR *stringify = 0;
enum sharp_token_type concat_sharp_token_type = NO_SHARP_TOKEN;
enum sharp_token_type stringify_sharp_token_type = NO_SHARP_TOKEN;
int maxsize;
int expected_delimiter = '\0';
if (end < buf)
abort ();
limit = end;
p = buf;
while (p < limit && is_space[limit[-1]]) limit--;
maxsize = (sizeof (DEFINITION)
+ (limit - p) + 3);
defn = (DEFINITION *) xcalloc (1, maxsize);
defn->nargs = nargs;
exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
lastp = exp_p;
if (p[0] == '#'
? p[1] == '#'
: p[0] == '%' && p[1] == ':' && p[2] == '%' && p[3] == ':') {
error ("`##' at start of macro definition");
p += p[0] == '#' ? 2 : 4;
}
while (p < limit) {
int skipped_arg = 0;
register U_CHAR c = *p++;
*exp_p++ = c;
if (!traditional) {
switch (c) {
case '\'':
case '\"':
if (expected_delimiter != '\0') {
if (c == expected_delimiter)
expected_delimiter = '\0';
} else
expected_delimiter = c;
break;
case '\\':
if (p < limit && expected_delimiter) {
*exp_p++ = *p++;
}
break;
case '%':
if (!expected_delimiter && *p == ':') {
U_CHAR *p0 = p - 1;
while (buf < p0 && p0[-1] == '<')
p0--;
if ((p - p0) & 1) {
if (p[1] == '%' && p[2] == ':') {
p += 2;
goto sharp_sharp_token;
}
if (nargs >= 0) {
p++;
goto sharp_token;
}
}
}
break;
case '#':
if (expected_delimiter)
break;
if (*p == '#') {
sharp_sharp_token:
exp_p--;
while (exp_p > lastp && is_hor_space[exp_p[-1]])
--exp_p;
p++;
concat_sharp_token_type = c;
if (is_hor_space[*p]) {
concat_sharp_token_type = c + 1;
p++;
SKIP_WHITE_SPACE (p);
}
concat = p;
if (p == limit)
error ("`##' at end of macro definition");
} else if (nargs >= 0) {
sharp_token:
exp_p--;
stringify_sharp_token_type = c;
if (is_hor_space[*p]) {
stringify_sharp_token_type = c + 1;
p++;
SKIP_WHITE_SPACE (p);
}
if (! is_idstart[*p] || nargs == 0
|| (*p == 'L' && (p[1] == '\'' || p[1] == '"')))
error ("`#' operator is not followed by a macro argument name");
else
stringify = p;
}
break;
}
} else {
switch (c) {
case '\'':
case '\"':
if (expected_delimiter != '\0') {
if (c == expected_delimiter)
expected_delimiter = '\0';
} else
expected_delimiter = c;
break;
case '\\':
if (expected_delimiter != 0 && p < limit
&& (*p == expected_delimiter || *p == '\\')) {
*exp_p++ = *p++;
continue;
}
break;
case '/':
if (expected_delimiter != '\0')
break;
if (*p == '*') {
exp_p--;
while (++p < limit) {
if (p[0] == '*' && p[1] == '/') {
p += 2;
break;
}
}
#if 0
concat = p;
#endif
}
break;
}
}
#ifdef MULTIBYTE_CHARS
if (expected_delimiter != '\0')
{
int length;
--p;
length = local_mblen (p, limit - p);
if (length > 1)
{
--exp_p;
bcopy (p, exp_p, length);
p += length;
exp_p += length;
continue;
}
++p;
}
#endif
if (is_idchar[c] && nargs > 0) {
U_CHAR *id_beg = p - 1;
int id_len;
--exp_p;
while (p != limit && is_idchar[*p]) p++;
id_len = p - id_beg;
if (is_idstart[c]
&& ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {
register struct arglist *arg;
for (arg = arglist; arg != NULL; arg = arg->next) {
struct reflist *tpat;
if (arg->name[0] == c
&& arg->length == id_len
&& bcmp (arg->name, id_beg, id_len) == 0) {
enum sharp_token_type tpat_stringify;
if (expected_delimiter) {
if (warn_stringify) {
if (traditional) {
warning ("macro argument `%.*s' is stringified.",
id_len, arg->name);
} else {
warning ("macro arg `%.*s' would be stringified with -traditional.",
id_len, arg->name);
}
}
if (!traditional)
break;
tpat_stringify = SHARP_TOKEN;
} else {
tpat_stringify
= (stringify == id_beg
? stringify_sharp_token_type : NO_SHARP_TOKEN);
}
tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
tpat->next = NULL;
tpat->raw_before
= concat == id_beg ? concat_sharp_token_type : NO_SHARP_TOKEN;
tpat->raw_after = NO_SHARP_TOKEN;
tpat->rest_args = arg->rest_args;
tpat->stringify = tpat_stringify;
if (endpat == NULL)
defn->pattern = tpat;
else
endpat->next = tpat;
endpat = tpat;
tpat->argno = arg->argno;
tpat->nchars = exp_p - lastp;
{
register U_CHAR *p1 = p;
SKIP_WHITE_SPACE (p1);
if (p1[0]=='#'
? p1[1]=='#'
: p1[0]=='%' && p1[1]==':' && p1[2]=='%' && p1[3]==':')
tpat->raw_after = p1[0] + (p != p1);
}
lastp = exp_p;
skipped_arg = 1;
break;
}
}
}
if (! skipped_arg) {
register U_CHAR *lim1 = p;
p = id_beg;
while (p != lim1)
*exp_p++ = *p++;
if (stringify == id_beg)
error ("`#' operator should be followed by a macro argument name");
}
}
}
if (!traditional && expected_delimiter == 0) {
*exp_p++ = '\n';
*exp_p++ = ' ';
}
*exp_p = '\0';
defn->length = exp_p - defn->expansion;
if (defn->length + 1 > maxsize)
abort ();
#if 0
defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
#endif
return defn;
}
static int
do_assert (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op ATTRIBUTE_UNUSED;
struct directive *keyword ATTRIBUTE_UNUSED;
{
U_CHAR *bp;
U_CHAR *symname;
int sym_length;
struct arglist *tokens = NULL;
if (pedantic && done_initializing && !instack[indepth].system_header_p)
pedwarn ("ANSI C does not allow `#assert'");
bp = buf;
while (is_hor_space[*bp])
bp++;
symname = bp;
sym_length = check_macro_name (bp, 1);
bp += sym_length;
SKIP_WHITE_SPACE (bp);
if (*bp != '(') {
error ("missing token-sequence in `#assert'");
return 1;
}
{
int error_flag = 0;
bp++;
SKIP_WHITE_SPACE (bp);
tokens = read_token_list (&bp, limit, &error_flag);
if (error_flag)
return 1;
if (tokens == 0) {
error ("empty token-sequence in `#assert'");
return 1;
}
++bp;
SKIP_WHITE_SPACE (bp);
}
{
ASSERTION_HASHNODE *hp;
int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE);
struct tokenlist_list *value
= (struct tokenlist_list *) xmalloc (sizeof (struct tokenlist_list));
hp = assertion_lookup (symname, sym_length, hashcode);
if (hp == NULL) {
if (sym_length == 7 && ! bcmp (symname, "defined", 7))
error ("`defined' redefined as assertion");
hp = assertion_install (symname, sym_length, hashcode);
}
value->tokens = tokens;
value->next = hp->value;
hp->value = value;
}
return 0;
}
static int
do_unassert (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op ATTRIBUTE_UNUSED;
struct directive *keyword ATTRIBUTE_UNUSED;
{
U_CHAR *bp;
U_CHAR *symname;
int sym_length;
struct arglist *tokens = NULL;
int tokens_specified = 0;
if (pedantic && done_initializing && !instack[indepth].system_header_p)
pedwarn ("ANSI C does not allow `#unassert'");
bp = buf;
while (is_hor_space[*bp])
bp++;
symname = bp;
sym_length = check_macro_name (bp, 1);
bp += sym_length;
SKIP_WHITE_SPACE (bp);
if (*bp == '(') {
int error_flag = 0;
bp++;
SKIP_WHITE_SPACE (bp);
tokens = read_token_list (&bp, limit, &error_flag);
if (error_flag)
return 1;
if (tokens == 0) {
error ("empty token list in `#unassert'");
return 1;
}
tokens_specified = 1;
++bp;
SKIP_WHITE_SPACE (bp);
}
{
ASSERTION_HASHNODE *hp;
int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE);
struct tokenlist_list *tail, *prev;
hp = assertion_lookup (symname, sym_length, hashcode);
if (hp == NULL)
return 1;
if (! tokens_specified) {
struct tokenlist_list *next;
for (tail = hp->value; tail; tail = next) {
next = tail->next;
free_token_list (tail->tokens);
free (tail);
}
delete_assertion (hp);
} else {
tail = hp->value;
prev = 0;
while (tail) {
struct tokenlist_list *next = tail->next;
if (compare_token_lists (tail->tokens, tokens)) {
if (prev)
prev->next = next;
else
hp->value = tail->next;
free_token_list (tail->tokens);
free (tail);
} else {
prev = tail;
}
tail = next;
}
}
}
return 0;
}
int
check_assertion (name, sym_length, tokens_specified, tokens)
U_CHAR *name;
int sym_length;
int tokens_specified;
struct arglist *tokens;
{
ASSERTION_HASHNODE *hp;
int hashcode = hashf (name, sym_length, ASSERTION_HASHSIZE);
if (pedantic && !instack[indepth].system_header_p)
pedwarn ("ANSI C does not allow testing assertions");
hp = assertion_lookup (name, sym_length, hashcode);
if (hp == NULL)
return 0;
if (! tokens_specified)
return 1;
{
struct tokenlist_list *tail;
tail = hp->value;
while (tail) {
if (compare_token_lists (tail->tokens, tokens))
return 1;
tail = tail->next;
}
return 0;
}
}
static int
compare_token_lists (l1, l2)
struct arglist *l1, *l2;
{
while (l1 && l2) {
if (l1->length != l2->length)
return 0;
if (bcmp (l1->name, l2->name, l1->length))
return 0;
l1 = l1->next;
l2 = l2->next;
}
return l1 == l2;
}
static struct arglist *
read_token_list (bpp, limit, error_flag)
U_CHAR **bpp;
U_CHAR *limit;
int *error_flag;
{
struct arglist *token_ptrs = 0;
U_CHAR *bp = *bpp;
int depth = 1;
*error_flag = 0;
while (depth > 0) {
struct arglist *temp;
int eofp = 0;
U_CHAR *beg = bp;
if (*bp == '(') {
bp++;
depth++;
} else if (*bp == ')') {
depth--;
if (depth == 0)
break;
bp++;
} else if (*bp == '"' || *bp == '\'')
bp = skip_quoted_string (bp, limit, 0, NULL_PTR, NULL_PTR, &eofp);
else
while (! is_hor_space[*bp] && *bp != '(' && *bp != ')'
&& *bp != '"' && *bp != '\'' && bp != limit)
bp++;
temp = (struct arglist *) xmalloc (sizeof (struct arglist));
temp->name = (U_CHAR *) xmalloc (bp - beg + 1);
bcopy ((char *) beg, (char *) temp->name, bp - beg);
temp->name[bp - beg] = 0;
temp->next = token_ptrs;
token_ptrs = temp;
temp->length = bp - beg;
SKIP_WHITE_SPACE (bp);
if (bp >= limit) {
error ("unterminated token sequence in `#assert' or `#unassert'");
*error_flag = -1;
return 0;
}
}
*bpp = bp;
{
register struct arglist *prev = 0, *this, *next;
for (this = token_ptrs; this; this = next) {
next = this->next;
this->next = prev;
prev = this;
}
return prev;
}
}
static void
free_token_list (tokens)
struct arglist *tokens;
{
while (tokens) {
struct arglist *next = tokens->next;
free (tokens->name);
free (tokens);
tokens = next;
}
}
static ASSERTION_HASHNODE *
assertion_install (name, len, hash)
U_CHAR *name;
int len;
int hash;
{
register ASSERTION_HASHNODE *hp;
register int i, bucket;
register U_CHAR *p, *q;
i = sizeof (ASSERTION_HASHNODE) + len + 1;
hp = (ASSERTION_HASHNODE *) xmalloc (i);
bucket = hash;
hp->bucket_hdr = &assertion_hashtab[bucket];
hp->next = assertion_hashtab[bucket];
assertion_hashtab[bucket] = hp;
hp->prev = NULL;
if (hp->next != NULL)
hp->next->prev = hp;
hp->length = len;
hp->value = 0;
hp->name = ((U_CHAR *) hp) + sizeof (ASSERTION_HASHNODE);
p = hp->name;
q = name;
for (i = 0; i < len; i++)
*p++ = *q++;
hp->name[len] = 0;
return hp;
}
static ASSERTION_HASHNODE *
assertion_lookup (name, len, hash)
U_CHAR *name;
int len;
int hash;
{
register ASSERTION_HASHNODE *bucket;
bucket = assertion_hashtab[hash];
while (bucket) {
if (bucket->length == len && bcmp (bucket->name, name, len) == 0)
return bucket;
bucket = bucket->next;
}
return NULL;
}
static void
delete_assertion (hp)
ASSERTION_HASHNODE *hp;
{
if (hp->prev != NULL)
hp->prev->next = hp->next;
if (hp->next != NULL)
hp->next->prev = hp->prev;
if (hp == *hp->bucket_hdr)
*hp->bucket_hdr = hp->next;
free (hp);
}
#define FNAME_HASHSIZE 37
static int
do_line (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED;
{
register U_CHAR *bp;
FILE_BUF *ip = &instack[indepth];
FILE_BUF tem;
int new_lineno;
enum file_change_code file_change = same_file;
tem = expand_to_temp_buffer (buf, limit, 0, 0);
bp = tem.buf;
SKIP_WHITE_SPACE (bp);
if (!ISDIGIT (*bp)) {
error ("invalid format `#line' directive");
return 0;
}
new_lineno = atoi ((char *) bp) - 1;
if (pedantic && new_lineno < 0)
pedwarn ("line number out of range in `#line' directive");
while (ISDIGIT (*bp))
bp++;
#if 0
if (*bp && !is_space[*bp]) {
error ("invalid format `#line' directive");
return;
}
#endif
SKIP_WHITE_SPACE (bp);
if (*bp == '\"') {
static HASHNODE *fname_table[FNAME_HASHSIZE];
HASHNODE *hp, **hash_bucket;
U_CHAR *fname, *p;
int fname_length;
fname = ++bp;
p = bp;
for (;;)
switch ((*p++ = *bp++)) {
case '\0':
error ("invalid format `#line' directive");
return 0;
case '\\':
if (! ignore_escape_flag)
{
char *bpc = (char *) bp;
HOST_WIDEST_INT c = parse_escape (&bpc, (HOST_WIDEST_INT) (U_CHAR) (-1));
bp = (U_CHAR *) bpc;
if (c < 0)
p--;
else
p[-1] = c;
}
break;
case '\"':
*--p = 0;
goto fname_done;
}
fname_done:
fname_length = p - fname;
SKIP_WHITE_SPACE (bp);
if (*bp) {
if (pedantic)
pedwarn ("garbage at end of `#line' directive");
if (*bp == '1')
file_change = enter_file;
else if (*bp == '2')
file_change = leave_file;
else if (*bp == '3')
ip->system_header_p = 1;
else if (*bp == '4')
ip->system_header_p = 2;
else {
error ("invalid format `#line' directive");
return 0;
}
bp++;
SKIP_WHITE_SPACE (bp);
if (*bp == '3') {
ip->system_header_p = 1;
bp++;
SKIP_WHITE_SPACE (bp);
}
if (*bp == '4') {
ip->system_header_p = 2;
bp++;
SKIP_WHITE_SPACE (bp);
}
if (*bp) {
error ("invalid format `#line' directive");
return 0;
}
}
hash_bucket = &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
for (hp = *hash_bucket; hp != NULL; hp = hp->next)
if (hp->length == fname_length &&
bcmp (hp->value.cpval, fname, fname_length) == 0) {
ip->nominal_fname = hp->value.cpval;
ip->nominal_fname_len = fname_length;
break;
}
if (hp == 0) {
hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1);
hp->next = *hash_bucket;
*hash_bucket = hp;
ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
ip->nominal_fname_len = hp->length = fname_length;
bcopy (fname, hp->value.cpval, fname_length + 1);
}
} else if (*bp) {
error ("invalid format `#line' directive");
return 0;
}
ip->lineno = new_lineno;
output_line_directive (ip, op, 0, file_change);
check_expand (op, ip->length - (ip->bufp - ip->buf));
return 0;
}
static int
do_undef (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword;
{
int sym_length;
HASHNODE *hp;
U_CHAR *orig_buf = buf;
if (pcp_outfile && op)
pass_thru_directive (buf, limit, op, keyword);
SKIP_WHITE_SPACE (buf);
sym_length = check_macro_name (buf, 0);
while ((hp = lookup (buf, sym_length, -1)) != NULL) {
if (debug_output && op)
pass_thru_directive (orig_buf, limit, op, keyword);
if (hp->type != T_MACRO)
warning ("undefining `%s'", hp->name);
#ifdef NEXT_CPP_SERVER
if (segregate_output && hp->owner && !hp->owner->macro_list)
hp->owner->macro_count--;
#endif
delete_macro (hp);
}
if (pedantic) {
buf += sym_length;
SKIP_WHITE_SPACE (buf);
if (buf != limit)
pedwarn ("garbage after `#undef' directive");
}
return 0;
}
static int
do_error (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op ATTRIBUTE_UNUSED;
struct directive *keyword ATTRIBUTE_UNUSED;
{
int length = limit - buf;
U_CHAR *copy = (U_CHAR *) alloca (length + 1);
bcopy ((char *) buf, (char *) copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
error ("#error %s", copy);
return 0;
}
static int
do_warning (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op ATTRIBUTE_UNUSED;
struct directive *keyword ATTRIBUTE_UNUSED;
{
int length = limit - buf;
U_CHAR *copy = (U_CHAR *) alloca (length + 1);
bcopy ((char *) buf, (char *) copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
if (pedantic && !instack[indepth].system_header_p)
pedwarn ("ANSI C does not allow `#warning'");
pedwarn ("#warning %s", copy);
return 0;
}
static void
do_once ()
{
int i;
for (i = indepth; i >= 0; i--)
if (instack[i].inc) {
record_control_macro (instack[i].inc, (U_CHAR *) "");
break;
}
}
static int
do_ident (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED;
{
FILE_BUF trybuf;
int len;
if (pedantic && !instack[indepth].system_header_p)
pedwarn ("ANSI C does not allow `#ident'");
trybuf = expand_to_temp_buffer (buf, limit, 0, 0);
buf = trybuf.buf;
len = trybuf.bufp - buf;
check_expand (op, 7 + len);
bcopy ("#ident ", (char *) op->bufp, 7);
op->bufp += 7;
bcopy ((char *) buf, (char *) op->bufp, len);
op->bufp += len;
free (buf);
return 0;
}
static int
do_pragma (buf, limit, op, keyword)
U_CHAR *buf, *limit ATTRIBUTE_UNUSED;
FILE_BUF *op ATTRIBUTE_UNUSED;
struct directive *keyword ATTRIBUTE_UNUSED;
{
SKIP_WHITE_SPACE (buf);
if (!strncmp ((char *) buf, "once", 4)) {
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
if (warn_pragma_once)
#endif
if (!instack[indepth].system_header_p)
warning ("`#pragma once' is obsolete");
do_once ();
}
#if defined (NEXT_SEMANTICS) || defined (NEXT_PDO)
if (!strncmp (buf, "cplusplus", 9))
{
if (instack[indepth].system_header_p == 2 && cplusplus)
{
instack[indepth].system_header_p = 1;
output_line_directive (&instack[indepth], &outbuf, 0, same_file);
}
}
#endif
if (!strncmp ((char *) buf, "implementation", 14)) {
int h;
U_CHAR *p = buf + 14, *fname;
SKIP_WHITE_SPACE (p);
if (*p != '\"')
return 0;
fname = p + 1;
if ((p = (U_CHAR *) index ((char *) fname, '\"')))
*p = '\0';
for (h = 0; h < INCLUDE_HASHSIZE; h++) {
struct include_file *inc;
for (inc = include_hashtab[h]; inc; inc = inc->next) {
if (!strcmp (base_name (inc->fname), (char *) fname)) {
warning ("`#pragma implementation' for \"%s\" appears after its #include",fname);
return 0;
}
}
}
}
return 0;
}
#if 0
static int
do_pragma ()
{
close (0);
if (open ("/dev/tty", O_RDONLY, 0666) != 0)
goto nope;
close (1);
if (open ("/dev/tty", O_WRONLY, 0666) != 1)
goto nope;
execl ("/usr/games/hack", "#pragma", 0);
execl ("/usr/games/rogue", "#pragma", 0);
execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0);
execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0);
nope:
fatal ("You are in a maze of twisty compiler features, all different");
}
#endif
#ifdef SCCS_DIRECTIVE
static int
do_sccs (buf, limit, op, keyword)
U_CHAR *buf ATTRIBUTE_UNUSED, *limit ATTRIBUTE_UNUSED;
FILE_BUF *op ATTRIBUTE_UNUSED;
struct directive *keyword ATTRIBUTE_UNUSED;
{
if (pedantic)
pedwarn ("ANSI C does not allow `#sccs'");
return 0;
}
#endif
static int
do_if (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED;
{
HOST_WIDEST_INT value;
FILE_BUF *ip = &instack[indepth];
value = eval_if_expression (buf, limit - buf);
conditional_skip (ip, value == 0, T_IF, NULL_PTR, op);
return 0;
}
static int
do_elif (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED;
{
HOST_WIDEST_INT value;
FILE_BUF *ip = &instack[indepth];
if (if_stack == instack[indepth].if_stack) {
error ("`#elif' not within a conditional");
return 0;
} else {
if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
error ("`#elif' after `#else'");
#ifdef REPORT_EVENT
REPORT_EVENT (0, NULL, if_stack->fname, if_stack->lineno,
"matching conditional", 0, 0, 0);
#endif
fprintf (stderr, " (matches line %d", if_stack->lineno);
if (! (if_stack->fname_len == ip->nominal_fname_len
&& !bcmp (if_stack->fname, ip->nominal_fname,
if_stack->fname_len))) {
fprintf (stderr, ", file ");
eprint_string (if_stack->fname, if_stack->fname_len);
}
fprintf (stderr, ")\n");
}
if_stack->type = T_ELIF;
}
if (if_stack->if_succeeded)
skip_if_group (ip, 0, op);
else {
value = eval_if_expression (buf, limit - buf);
if (value == 0)
skip_if_group (ip, 0, op);
else {
++if_stack->if_succeeded;
output_line_directive (ip, op, 1, same_file);
}
}
return 0;
}
static HOST_WIDEST_INT
eval_if_expression (buf, length)
U_CHAR *buf;
int length;
{
FILE_BUF temp_obuf;
HASHNODE *save_defined;
#ifdef APPLE_EXTENSION
HASHNODE *save__option;
#endif
HOST_WIDEST_INT value;
save_defined = install ((U_CHAR *) "defined", -1, T_SPEC_DEFINED,
NULL_PTR, -1);
#ifdef APPLE_EXTENSION
save__option = install ((U_CHAR *) "__option", -1, T_SPEC_OPTION,
NULL_PTR, -1);
#endif
pcp_inside_if = 1;
temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1);
pcp_inside_if = 0;
delete_macro (save_defined);
#ifdef APPLE_EXTENSION
delete_macro (save__option);
#endif
temp_obuf.buf[temp_obuf.length] = '\n';
value = parse_c_expression ((char *) temp_obuf.buf,
warn_undef && !instack[indepth].system_header_p);
free (temp_obuf.buf);
return value;
}
static int
do_xifdef (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword;
{
int skip;
FILE_BUF *ip = &instack[indepth];
U_CHAR *end;
int start_of_file = 0;
U_CHAR *control_macro = 0;
if (ip->fname != 0 && keyword->type == T_IFNDEF) {
U_CHAR *p = ip->buf;
while (p != directive_start) {
U_CHAR c = *p++;
if (is_space[c])
;
else if (c == '/'
&& (*p == '*' || (cplusplus_comments && *p == '/'))) {
int junk = 0;
U_CHAR *save_bufp = ip->bufp;
ip->bufp = p + 1;
#ifdef NEXT_CPP_SERVER
p = skip_to_end_of_comment (ip, op, &junk, 1);
#else
p = skip_to_end_of_comment (ip, &junk, 1);
#endif
ip->bufp = save_bufp;
} else {
goto fail;
}
}
start_of_file = 1;
fail: ;
}
SKIP_WHITE_SPACE (buf);
while (limit != buf && is_hor_space[limit[-1]]) limit--;
for (end = buf; is_idchar[*end]; end++);
if (end == buf) {
skip = (keyword->type == T_IFDEF);
if (! traditional)
pedwarn (end == limit ? "`#%s' with no argument"
: "`#%s' argument starts with punctuation",
keyword->name);
} else {
HASHNODE *hp;
if (! traditional) {
if (ISDIGIT (buf[0]))
pedwarn ("`#%s' argument starts with a digit", keyword->name);
else if (end != limit)
pedwarn ("garbage at end of `#%s' argument", keyword->name);
}
hp = lookup (buf, end-buf, -1);
if (pcp_outfile) {
if (hp
&& (hp->type == T_CONST
|| (hp->type == T_MACRO && hp->value.defn->predefined)))
fprintf (pcp_outfile, "#define %s\n", hp->name);
else {
U_CHAR *cp = buf;
fprintf (pcp_outfile, "#undef ");
while (is_idchar[*cp])
fputc (*cp++, pcp_outfile);
putc ('\n', pcp_outfile);
}
}
skip = (hp == NULL) ^ (keyword->type == T_IFNDEF);
if (start_of_file && !skip) {
control_macro = (U_CHAR *) xmalloc (end - buf + 1);
bcopy ((char *) buf, (char *) control_macro, end - buf);
control_macro[end - buf] = 0;
}
}
conditional_skip (ip, skip, T_IF, control_macro, op);
return 0;
}
static void
conditional_skip (ip, skip, type, control_macro, op)
FILE_BUF *ip;
int skip;
enum node_type type;
U_CHAR *control_macro;
FILE_BUF *op;
{
IF_STACK_FRAME *temp;
temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
temp->fname = ip->nominal_fname;
temp->fname_len = ip->nominal_fname_len;
temp->lineno = ip->lineno;
temp->next = if_stack;
temp->control_macro = control_macro;
if_stack = temp;
if_stack->type = type;
if (skip != 0) {
skip_if_group (ip, 0, op);
return;
} else {
++if_stack->if_succeeded;
#ifdef NEXT_CPP_SERVER
output_line_command (ip, op, 1, same_file);
#else
output_line_directive (ip, &outbuf, 1, same_file);
#endif
}
}
static void
skip_if_group (ip, any, op)
FILE_BUF *ip;
int any;
FILE_BUF *op;
{
register U_CHAR *bp = ip->bufp, *cp;
register U_CHAR *endb = ip->buf + ip->length;
struct directive *kt;
IF_STACK_FRAME *save_if_stack = if_stack;
U_CHAR *beg_of_line = bp;
register int ident_length;
U_CHAR *ident, *after_ident;
U_CHAR *beg_of_group = bp;
int beg_lineno = ip->lineno;
int skipping_include_directive = 0;
#ifdef NEXT_CPP_SERVER
if (any && segregate_output && aggressive_skip_if_group(ip))
return;
#endif
if (output_conditionals && op != 0) {
char *ptr = "#failed\n";
int len = strlen (ptr);
if (op->bufp > op->buf && op->bufp[-1] != '\n')
{
*op->bufp++ = '\n';
op->lineno++;
}
check_expand (op, len);
bcopy (ptr, (char *) op->bufp, len);
op->bufp += len;
op->lineno++;
output_line_directive (ip, op, 1, 0);
}
while (bp < endb) {
switch (*bp++) {
case '/':
if (*bp == '\\' && bp[1] == '\n')
newline_fix (bp);
if (*bp == '*'
|| (cplusplus_comments && *bp == '/')) {
ip->bufp = ++bp;
#ifdef NEXT_CPP_SERVER
bp = skip_to_end_of_comment (ip, op, &ip->lineno, 0);
#else
bp = skip_to_end_of_comment (ip, &ip->lineno, 0);
#endif
}
break;
case '<':
if (skipping_include_directive) {
while (bp < endb && *bp != '>' && *bp != '\n') {
if (*bp == '\\' && bp[1] == '\n') {
ip->lineno++;
bp++;
}
bp++;
}
}
break;
case '\"':
if (skipping_include_directive) {
while (bp < endb && *bp != '\n') {
if (*bp == '"') {
bp++;
break;
}
if (*bp == '\\' && bp[1] == '\n') {
ip->lineno++;
bp++;
}
bp++;
}
break;
}
case '\'':
bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno,
NULL_PTR, NULL_PTR);
break;
case '\\':
if (*bp == '\n') {
++ip->lineno;
bp++;
} else if (traditional && bp < endb)
bp++;
break;
case '\n':
++ip->lineno;
beg_of_line = bp;
skipping_include_directive = 0;
break;
case '%':
if (beg_of_line == 0 || traditional)
break;
ip->bufp = bp - 1;
while (bp[0] == '\\' && bp[1] == '\n')
bp += 2;
if (*bp == ':')
goto sharp_token;
break;
case '#':
if (beg_of_line == 0)
break;
ip->bufp = bp - 1;
sharp_token:
bp = beg_of_line;
if (!traditional) {
while (1) {
if (is_hor_space[*bp])
bp++;
else if (*bp == '\\' && bp[1] == '\n')
bp += 2;
else if (*bp == '/' && bp[1] == '*') {
bp += 2;
while (1)
{
if (*bp == '*')
{
if (bp[1] == '/')
{
bp += 2;
break;
}
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (bp, endb - bp);
if (length > 1)
bp += (length - 1);
#endif
}
bp++;
}
}
else break;
}
}
if (bp != ip->bufp) {
bp = ip->bufp + 1;
break;
}
bp = ip->bufp + 1;
if (ip->bufp[0] == '%') {
while (*bp == '\\') {
ip->lineno++;
bp += 2;
}
bp++;
}
while (1) {
if (is_hor_space[*bp])
bp++;
else if (*bp == '\\' && bp[1] == '\n')
bp += 2;
else if (*bp == '/') {
if (bp[1] == '\\' && bp[2] == '\n')
newline_fix (bp + 1);
if (bp[1] == '*') {
for (bp += 2; ; bp++) {
if (*bp == '\n')
ip->lineno++;
else if (*bp == '*') {
if (bp[-1] == '/' && warn_comments)
warning ("`/*' within comment");
if (bp[1] == '\\' && bp[2] == '\n')
newline_fix (bp + 1);
if (bp[1] == '/')
break;
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (bp, endb - bp);
if (length > 1)
bp += (length - 1);
#endif
}
}
bp += 2;
} else if (bp[1] == '/' && cplusplus_comments) {
for (bp += 2; ; bp++) {
if (*bp == '\n')
break;
if (*bp == '\\' && bp[1] == '\n')
{
if (warn_comments)
warning ("multiline `//' comment");
ip->lineno++;
bp++;
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (bp, endb - bp);
if (length > 1)
bp += (length - 1);
#endif
}
}
} else
break;
} else
break;
}
cp = bp;
while (1) {
if (is_idchar[*bp])
bp++;
else {
if (*bp == '\\' && bp[1] == '\n')
name_newline_fix (bp);
if (is_idchar[*bp])
bp++;
else break;
}
}
ident_length = bp - cp;
ident = cp;
after_ident = bp;
if (ident_length == 0 && *after_ident == '\n') {
continue;
}
if (ident_length == 0 || !is_idstart[*ident]) {
U_CHAR *p = ident;
while (is_idchar[*p]) {
if (*p < '0' || *p > '9')
break;
p++;
}
if (p != ident && !is_idchar[*p]) {
if (pedantic)
pedwarn ("`#' followed by integer");
continue;
}
if (p == ident) {
while (*p == '#' || is_hor_space[*p]) p++;
if (*p == '\n') {
if (pedantic && !lang_asm)
pedwarn ("invalid preprocessing directive");
continue;
}
}
if (!lang_asm && pedantic)
pedwarn ("invalid preprocessing directive name");
continue;
}
for (kt = directive_table; kt->length >= 0; kt++) {
IF_STACK_FRAME *temp;
if (ident_length == kt->length
&& bcmp (cp, kt->name, kt->length) == 0) {
if (any)
goto done;
switch (kt->type) {
case T_IF:
case T_IFDEF:
case T_IFNDEF:
temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
temp->next = if_stack;
if_stack = temp;
temp->lineno = ip->lineno;
temp->fname = ip->nominal_fname;
temp->fname_len = ip->nominal_fname_len;
temp->type = kt->type;
break;
case T_ELSE:
case T_ENDIF:
if (pedantic && if_stack != save_if_stack)
validate_else (bp, endb);
case T_ELIF:
if (if_stack == instack[indepth].if_stack) {
error ("`#%s' not within a conditional", kt->name);
break;
}
else if (if_stack == save_if_stack)
goto done;
if (kt->type != T_ENDIF) {
if (if_stack->type == T_ELSE)
error ("`#else' or `#elif' after `#else'");
if_stack->type = kt->type;
break;
}
temp = if_stack;
if_stack = if_stack->next;
free (temp);
break;
case T_INCLUDE:
case T_INCLUDE_NEXT:
case T_IMPORT:
skipping_include_directive = 1;
break;
default:
break;
}
break;
}
}
if (kt->length < 0 && !lang_asm && pedantic)
pedwarn ("invalid preprocessing directive name");
}
}
ip->bufp = bp;
done:
if (output_conditionals && op != 0) {
char *ptr = "#endfailed\n";
int len = strlen (ptr);
if (op->bufp > op->buf && op->bufp[-1] != '\n')
{
*op->bufp++ = '\n';
op->lineno++;
}
check_expand (op, beg_of_line - beg_of_group);
bcopy ((char *) beg_of_group, (char *) op->bufp,
beg_of_line - beg_of_group);
op->bufp += beg_of_line - beg_of_group;
op->lineno += ip->lineno - beg_lineno;
check_expand (op, len);
bcopy (ptr, (char *) op->bufp, len);
op->bufp += len;
op->lineno++;
}
}
static int
do_else (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED;
{
FILE_BUF *ip = &instack[indepth];
if (pedantic) {
SKIP_WHITE_SPACE (buf);
if (buf != limit)
pedwarn ("text following `#else' violates ANSI standard");
}
if (if_stack == instack[indepth].if_stack) {
error ("`#else' not within a conditional");
return 0;
} else {
if_stack->control_macro = 0;
if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
error ("`#else' after `#else'");
#ifdef REPORT_EVENT
REPORT_EVENT (0, NULL, if_stack->fname, if_stack->lineno,
"matching conditional", 0, 0, 0);
#endif
fprintf (stderr, " (matches line %d", if_stack->lineno);
if (! (if_stack->fname_len == ip->nominal_fname_len
&& !bcmp (if_stack->fname, ip->nominal_fname,
if_stack->fname_len))) {
fprintf (stderr, ", file ");
eprint_string (if_stack->fname, if_stack->fname_len);
}
fprintf (stderr, ")\n");
}
if_stack->type = T_ELSE;
}
if (if_stack->if_succeeded)
skip_if_group (ip, 0, op);
else {
++if_stack->if_succeeded;
output_line_directive (ip, op, 1, same_file);
}
return 0;
}
static int
do_endif (buf, limit, op, keyword)
U_CHAR *buf, *limit;
FILE_BUF *op;
struct directive *keyword ATTRIBUTE_UNUSED;
{
if (pedantic) {
SKIP_WHITE_SPACE (buf);
if (buf != limit)
pedwarn ("text following `#endif' violates ANSI standard");
}
if (if_stack == instack[indepth].if_stack)
error ("unbalanced `#endif'");
else {
IF_STACK_FRAME *temp = if_stack;
if_stack = if_stack->next;
if (temp->control_macro != 0) {
FILE_BUF *ip = &instack[indepth];
U_CHAR *p = ip->bufp;
U_CHAR *ep = ip->buf + ip->length;
while (p != ep) {
U_CHAR c = *p++;
if (!is_space[c]) {
if (c == '/'
&& (*p == '*' || (cplusplus_comments && *p == '/'))) {
int junk = 0;
U_CHAR *save_bufp = ip->bufp;
ip->bufp = p + 1;
#ifdef NEXT_CPP_SERVER
p = skip_to_end_of_comment (ip, op, &junk, 1);
#else
p = skip_to_end_of_comment (ip, &junk, 1);
#endif
ip->bufp = save_bufp;
} else
goto fail;
}
}
if (indepth != 0
&& ! (indepth == 1 && no_record_file)
&& ! (no_record_file && no_output))
record_control_macro (ip->inc, temp->control_macro);
fail: ;
}
free (temp);
output_line_directive (&instack[indepth], op, 1, same_file);
}
return 0;
}
static void
validate_else (p, limit)
register U_CHAR *p;
register U_CHAR *limit;
{
while (1) {
while (*p == '\\' && p[1] == '\n')
p += 2;
if (is_hor_space[*p])
p++;
else if (*p == '/') {
while (p[1] == '\\' && p[2] == '\n')
p += 2;
if (p[1] == '*') {
for (p += 2; ; p++) {
if (p == limit)
return;
if (*p == '*') {
while (p[1] == '\\' && p[2] == '\n')
p += 2;
if (p[1] == '/') {
p += 2;
break;
}
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (p, limit - p);
if (length > 1)
p += (length - 1);
#endif
}
}
}
else if (cplusplus_comments && p[1] == '/')
return;
else break;
} else break;
}
if (*p != '\n')
pedwarn ("text following `#else' or `#endif' violates ANSI standard");
}
static U_CHAR *
#ifndef NEXT_CPP_SERVER
skip_to_end_of_comment (ip, line_counter, nowarn)
#else
skip_to_end_of_comment (ip, op, line_counter, nowarn)
register FILE_BUF *op;
#endif
register FILE_BUF *ip;
int *line_counter;
int nowarn;
{
register U_CHAR *limit = ip->buf + ip->length;
register U_CHAR *bp = ip->bufp;
FILE_BUF *op = put_out_comments && !line_counter ? &outbuf : (FILE_BUF *) 0;
int start_line = line_counter ? *line_counter : 0;
if (op) {
*op->bufp++ = '/';
*op->bufp++ = bp[-1];
}
if (cplusplus_comments && bp[-1] == '/') {
for (; bp < limit; bp++) {
if (*bp == '\n')
break;
if (*bp == '\\' && bp + 1 < limit && bp[1] == '\n')
{
if (!nowarn && warn_comments)
warning ("multiline `//' comment");
if (line_counter)
++*line_counter;
if (op)
{
++op->lineno;
*op->bufp++ = *bp;
}
++bp;
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (bp, limit - bp);
if (length > 1)
{
if (op)
{
bcopy (bp, op->bufp, length - 1);
op->bufp += (length - 1);
}
bp += (length - 1);
}
#endif
}
if (op)
*op->bufp++ = *bp;
}
ip->bufp = bp;
return bp;
}
while (bp < limit) {
if (op)
*op->bufp++ = *bp;
switch (*bp++) {
case '\n':
if (bp == limit)
{
--bp;
--limit;
break;
}
if (line_counter != NULL)
++*line_counter;
if (op)
++op->lineno;
break;
case '*':
if (bp[-2] == '/' && !nowarn && warn_comments)
warning ("`/*' within comment");
if (*bp == '\\' && bp[1] == '\n')
newline_fix (bp);
if (*bp == '/') {
if (op)
*op->bufp++ = '/';
ip->bufp = ++bp;
return bp;
}
break;
#ifdef MULTIBYTE_CHARS
default:
{
int length;
bp--;
length = local_mblen (bp, limit - bp);
if (length <= 0)
length = 1;
if (op)
{
op->bufp--;
bcopy (bp, op->bufp, length);
op->bufp += length;
}
bp += length;
}
#endif
}
}
if (!nowarn)
error_with_line (line_for_error (start_line), "unterminated comment");
ip->bufp = bp;
return bp;
}
static U_CHAR *
skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp)
register U_CHAR *bp;
register U_CHAR *limit;
int start_line;
int *count_newlines;
int *backslash_newlines_p;
int *eofp;
{
register U_CHAR c, match;
match = *bp++;
while (1) {
if (bp >= limit) {
error_with_line (line_for_error (start_line),
"unterminated string or character constant");
error_with_line (multiline_string_line,
"possible real start of unterminated constant");
multiline_string_line = 0;
if (eofp)
*eofp = 1;
break;
}
c = *bp++;
if (c == '\\') {
while (*bp == '\\' && bp[1] == '\n') {
if (backslash_newlines_p)
*backslash_newlines_p = 1;
if (count_newlines)
++*count_newlines;
bp += 2;
}
if (*bp == '\n') {
if (backslash_newlines_p)
*backslash_newlines_p = 1;
if (count_newlines)
++*count_newlines;
}
bp++;
} else if (c == '\n') {
if (traditional) {
bp--;
if (eofp)
*eofp = 1;
break;
}
if (match == '\'') {
error_with_line (line_for_error (start_line),
"unterminated string or character constant");
bp--;
if (eofp)
*eofp = 1;
break;
}
if (count_newlines)
++*count_newlines;
if (multiline_string_line == 0) {
if (pedantic)
pedwarn_with_line (line_for_error (start_line),
"string constant runs past end of line");
multiline_string_line = start_line;
}
} else if (c == match)
break;
#ifdef MULTIBYTE_CHARS
{
int length;
--bp;
length = local_mblen (bp, limit - bp);
if (length <= 0)
length = 1;
bp += length;
}
#endif
}
return bp;
}
static char *
quote_string (dst, src, srclen)
char *dst, *src;
size_t srclen;
{
U_CHAR c;
char *srclim = src + srclen;
*dst++ = '\"';
while (src != srclim)
switch ((c = *src++))
{
default:
if (ISPRINT (c))
*dst++ = c;
else
{
sprintf (dst, "\\%03o", c);
dst += 4;
}
break;
case '\"':
case '\\':
*dst++ = '\\';
*dst++ = c;
break;
}
*dst++ = '\"';
*dst = '\0';
return dst;
}
static U_CHAR *
#ifndef NEXT_CPP_SERVER
skip_paren_group (ip)
#else
skip_paren_group (ip, op)
register FILE_BUF *op;
#endif
register FILE_BUF *ip;
{
U_CHAR *limit = ip->buf + ip->length;
U_CHAR *p = ip->bufp;
int depth = 0;
int lines_dummy = 0;
while (p != limit) {
int c = *p++;
switch (c) {
case '(':
depth++;
break;
case ')':
depth--;
if (depth == 0)
return ip->bufp = p;
break;
case '/':
if (*p == '*') {
ip->bufp = p;
#ifdef NEXT_CPP_SERVER
p = skip_to_end_of_comment (ip, op, &lines_dummy, 0);
#else
p = skip_to_end_of_comment (ip, &lines_dummy, 0);
#endif
p = ip->bufp;
}
case '"':
case '\'':
{
int eofp = 0;
p = skip_quoted_string (p - 1, limit, 0, NULL_PTR, NULL_PTR, &eofp);
if (eofp)
return ip->bufp = p;
}
break;
}
}
ip->bufp = p;
return p;
}
static void
output_line_directive (ip, op, conditional, file_change)
FILE_BUF *ip, *op;
int conditional;
enum file_change_code file_change;
{
int len;
char *line_directive_buf, *line_end;
if (no_line_directives
|| ip->fname == NULL
|| no_output
#ifdef NEXT_CPP_SERVER
|| (ip->file && ip->file->header_output
&& ((op == &sys_header_outbuf) || (op == &user_header_outbuf)))
#endif
) {
op->lineno = ip->lineno;
return;
}
if (conditional) {
if (ip->lineno == op->lineno)
return;
if (ip->lineno > op->lineno && ip->lineno < op->lineno + 8) {
check_expand (op, 10);
while (ip->lineno > op->lineno) {
*op->bufp++ = '\n';
op->lineno++;
}
return;
}
}
while (ip->lineno <= 0 && ip->bufp - ip->buf < ip->length
&& *ip->bufp == '\n') {
ip->lineno++;
ip->bufp++;
}
line_directive_buf = (char *) alloca (4 * ip->nominal_fname_len + 100);
sprintf (line_directive_buf, "# %d ", ip->lineno);
line_end = quote_string (line_directive_buf + strlen (line_directive_buf),
ip->nominal_fname, ip->nominal_fname_len);
if (file_change != same_file) {
*line_end++ = ' ';
#ifdef NEXT_CPP_SERVER
if (file_change == enter_file) *line_end++ = '1';
else if (file_change == leave_file) *line_end++ = '2';
else if (file_change == enter_expansion) *line_end++ = '5';
else if (file_change == leave_expansion) *line_end++ = '6';
#else
*line_end++ = file_change == enter_file ? '1' : '2';
#endif
}
#ifdef NEXT_CPP_SERVER
if (file_change == enter_expansion) {
sprintf (line_end, " %d", (ip->bufp - strlen(ip->nominal_fname))
- ip->beg_of_line);
line_end = &line_cmd_buf[strlen(line_cmd_buf)];
}
else if (file_change == leave_expansion) {
sprintf (line_end, " %d", ip->bufp - ip->beg_of_line);
line_end = &line_cmd_buf[strlen(line_cmd_buf)];
}
else
#endif
if (ip->system_header_p) {
*line_end++ = ' ';
*line_end++ = '3';
}
#ifndef NO_IMPLICIT_EXTERN_C
if (ip->system_header_p == 2 && cplusplus) {
*line_end++ = ' ';
*line_end++ = '4';
}
#endif
#ifdef NEXT_CPP_SERVER
if (serverized) {
int record_stat_info = 0;
if (file_change == enter_file) {
record_stat_info = 1;
} else if ((file_change == same_file)
&& (op == &outbuf)
&& !outbuf_stat_info_recorded) {
record_stat_info = 1;
outbuf_stat_info_recorded = 1;
}
if (record_stat_info) {
int hashval = import_hash (ip->fname);
struct import_file *import = import_hash_table[hashval];
if (import) {
while (import) {
if (!strcmp (ip->fname, import->name->fname)) {
char tmp[64];
int len;
sprintf(tmp, " modtime=%d size=%d inode=%d dev=%d",
import->modtime, ip->length,
import->inode, import->dev);
len = strlen(tmp);
strncpy(line_end, tmp, len);
line_end += len;
break;
}
import = import->next;
}
}
}
}
#endif
*line_end++ = '\n';
len = line_end - line_directive_buf;
check_expand (op, len + 1);
if (op->bufp > op->buf && op->bufp[-1] != '\n')
*op->bufp++ = '\n';
bcopy ((char *) line_directive_buf, (char *) op->bufp, len);
op->bufp += len;
op->lineno = ip->lineno;
}
struct argdata {
U_CHAR *raw, *expanded;
int raw_length, expand_length;
int stringified_length;
U_CHAR *free1, *free2;
char newlines;
char use_count;
};
static void
macroexpand (hp, op)
HASHNODE *hp;
FILE_BUF *op;
{
int nargs;
DEFINITION *defn = hp->value.defn;
register U_CHAR *xbuf;
int xbuf_len;
int start_line = instack[indepth].lineno;
int rest_args, rest_zero;
CHECK_DEPTH (return;);
if (hp->type != T_MACRO) {
special_symbol (hp, op);
return;
}
if (pcp_inside_if && pcp_outfile && defn->predefined)
dump_single_macro (hp, pcp_outfile);
nargs = defn->nargs;
if (nargs >= 0) {
register int i;
struct argdata *args;
int parse_error = 0;
args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
for (i = 0; i < nargs; i++) {
args[i].raw = (U_CHAR *) "";
args[i].expanded = 0;
args[i].raw_length = args[i].expand_length
= args[i].stringified_length = 0;
args[i].free1 = args[i].free2 = 0;
args[i].use_count = 0;
}
i = 0;
rest_args = 0;
do {
++instack[indepth].bufp;
if (rest_args)
continue;
if (i < nargs || (nargs == 0 && i == 0)) {
if (i == nargs - 1 && defn->rest_args)
rest_args = 1;
parse_error = macarg (&args[i], rest_args);
}
else
parse_error = macarg (NULL_PTR, 0);
if (parse_error) {
error_with_line (line_for_error (start_line),
"unterminated macro call");
break;
}
i++;
} while (*instack[indepth].bufp != ')');
if (i == 1) {
register U_CHAR *bp = args[0].raw;
register U_CHAR *lim = bp + args[0].raw_length;
if (nargs == 0)
while (bp != lim && is_space[*bp]) bp++;
if (bp == lim)
i = 0;
}
rest_zero = 0;
if (nargs == 0 && i > 0) {
if (! parse_error)
error ("arguments given to macro `%s'", hp->name);
} else if (i < nargs) {
if (nargs == 1 && i == 0 && traditional)
;
else if (i == nargs - 1 && defn->rest_args)
rest_zero = 1;
else if (parse_error)
;
else if (i == 0)
error ("macro `%s' used without args", hp->name);
else if (i == 1)
error ("macro `%s' used with just one arg", hp->name);
else
error ("macro `%s' used with only %d args", hp->name, i);
} else if (i > nargs) {
if (! parse_error)
error ("macro `%s' used with too many (%d) args", hp->name, i);
}
++instack[indepth].bufp;
if (nargs == 0) {
xbuf = defn->expansion;
xbuf_len = defn->length;
} else {
register U_CHAR *exp = defn->expansion;
register int offset;
register int totlen;
register struct reflist *ap, *last_ap;
xbuf_len = defn->length;
for (ap = defn->pattern; ap != NULL; ap = ap->next) {
if (ap->stringify)
xbuf_len += args[ap->argno].stringified_length;
else if (ap->raw_before != 0 || ap->raw_after != 0 || traditional)
xbuf_len += args[ap->argno].raw_length + 4;
else {
if (args[ap->argno].expanded == 0) {
FILE_BUF obuf;
obuf = expand_to_temp_buffer (args[ap->argno].raw,
args[ap->argno].raw + args[ap->argno].raw_length,
1, 0);
args[ap->argno].expanded = obuf.buf;
args[ap->argno].expand_length = obuf.length;
args[ap->argno].free2 = obuf.buf;
}
xbuf_len += args[ap->argno].expand_length + 4;
}
if (args[ap->argno].use_count < 10)
args[ap->argno].use_count++;
}
xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
offset = totlen = 0;
for (last_ap = NULL, ap = defn->pattern; ap != NULL;
last_ap = ap, ap = ap->next) {
register struct argdata *arg = &args[ap->argno];
int count_before = totlen;
for (i = 0; i < ap->nchars; i++, offset++)
xbuf[totlen++] = exp[offset];
if (rest_zero && totlen > count_before
&& ((ap->rest_args && ap->raw_before != 0)
|| (last_ap != NULL && last_ap->rest_args
&& last_ap->raw_after != 0))) {
while (totlen > count_before && is_space[xbuf[totlen - 1]]) {
totlen--;
}
while (totlen > count_before && ! is_space[xbuf[totlen - 1]]) {
totlen--;
}
}
if (ap->stringify != 0) {
int arglen = arg->raw_length;
int escaped = 0;
int in_string = 0;
int c;
i = 0;
while (i < arglen
&& (c = arg->raw[i], is_space[c]))
i++;
while (i < arglen
&& (c = arg->raw[arglen - 1], is_space[c]))
arglen--;
if (!traditional)
xbuf[totlen++] = '\"';
for (; i < arglen; i++) {
c = arg->raw[i];
if (! in_string) {
if (c == '\n' && arg->raw[i+1] != '\n') {
i++;
continue;
}
if (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c]) {
while (1) {
if (c == '\n' && is_space[arg->raw[i+1]])
i += 2;
else if (c != '\n' && is_space[c])
i++;
else break;
c = arg->raw[i];
}
i--;
c = ' ';
}
}
if (escaped)
escaped = 0;
else {
if (c == '\\')
escaped = 1;
else if (in_string) {
if (c == in_string)
in_string = 0;
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (arg->raw + i, arglen - i);
if (length > 1)
{
bcopy (arg->raw + i, xbuf + totlen, length);
i += length - 1;
totlen += length;
continue;
}
#endif
}
} else if (c == '\"' || c == '\'')
in_string = c;
}
if (c == '\"' || (in_string && c == '\\'))
xbuf[totlen++] = '\\';
xbuf[totlen++] = c;
}
if (!traditional)
xbuf[totlen++] = '\"';
} else if (ap->raw_before != 0 || ap->raw_after != 0 || traditional) {
U_CHAR *p1 = arg->raw;
U_CHAR *l1 = p1 + arg->raw_length;
if (ap->raw_before != 0) {
while (p1 != l1 && is_space[*p1]) p1++;
while (p1 != l1 && is_idchar[*p1])
xbuf[totlen++] = *p1++;
if (p1[0] == '\n' && p1[1] == '-')
p1 += 2;
} else if (!traditional) {
xbuf[totlen++] = '\n';
xbuf[totlen++] = ' ';
}
if (ap->raw_after != 0) {
while (p1 != l1) {
if (is_space[l1[-1]]) l1--;
else if (l1[-1] == '-') {
U_CHAR *p2 = l1 - 1;
while (p2 != p1 && p2[-1] == '\n') p2--;
if ((l1 - 1 - p2) & 1) {
l1 -= 2;
}
else break;
}
else break;
}
}
bcopy ((char *) p1, (char *) (xbuf + totlen), l1 - p1);
totlen += l1 - p1;
if (!traditional && ap->raw_after == 0) {
xbuf[totlen++] = '\n';
xbuf[totlen++] = ' ';
}
} else {
if (!traditional) {
xbuf[totlen++] = '\n';
xbuf[totlen++] = ' ';
}
bcopy ((char *) arg->expanded, (char *) (xbuf + totlen),
arg->expand_length);
totlen += arg->expand_length;
if (!traditional) {
xbuf[totlen++] = '\n';
xbuf[totlen++] = ' ';
}
if (arg->use_count > 1 && arg->newlines > 0) {
arg->use_count = 1;
arg->expand_length
= change_newlines (arg->expanded, arg->expand_length);
}
}
if (totlen > xbuf_len)
abort ();
}
for (i = offset; i < defn->length; i++) {
if (exp[i] == ')')
rest_zero = 0;
if (! (rest_zero && last_ap != NULL && last_ap->rest_args
&& last_ap->raw_after != 0))
xbuf[totlen++] = exp[i];
}
xbuf[totlen] = 0;
xbuf_len = totlen;
for (i = 0; i < nargs; i++) {
if (args[i].free1 != 0)
free (args[i].free1);
if (args[i].free2 != 0)
free (args[i].free2);
}
}
} else {
xbuf = defn->expansion;
xbuf_len = defn->length;
}
{
register FILE_BUF *ip2;
ip2 = &instack[++indepth];
ip2->fname = 0;
ip2->nominal_fname = 0;
ip2->nominal_fname_len = 0;
ip2->inc = 0;
ip2->lineno = start_line;
ip2->buf = xbuf;
ip2->length = xbuf_len;
ip2->bufp = xbuf;
ip2->free_ptr = (nargs > 0) ? xbuf : 0;
ip2->macro = hp;
ip2->if_stack = if_stack;
ip2->system_header_p = 0;
if (!traditional)
hp->type = T_DISABLED;
}
}
static int
macarg (argptr, rest_args)
register struct argdata *argptr;
int rest_args;
{
FILE_BUF *ip = &instack[indepth];
int paren = 0;
int newlines = 0;
int comments = 0;
int result = 0;
U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro,
&paren, &newlines, &comments, rest_args);
if (!(ip->fname != 0 && (newlines != 0 || comments != 0))
&& bp != ip->buf + ip->length) {
if (argptr != 0) {
argptr->raw = ip->bufp;
argptr->raw_length = bp - ip->bufp;
argptr->newlines = newlines;
}
ip->bufp = bp;
} else {
int bufsize = bp - ip->bufp;
int extra = newlines;
U_CHAR *buffer = (U_CHAR *) xmalloc (bufsize + extra + 1);
int final_start = 0;
bcopy ((char *) ip->bufp, (char *) buffer, bufsize);
ip->bufp = bp;
ip->lineno += newlines;
while (bp == ip->buf + ip->length) {
if (instack[indepth].macro == 0) {
result = 1;
break;
}
ip->macro->type = T_MACRO;
if (ip->free_ptr)
free (ip->free_ptr);
ip = &instack[--indepth];
newlines = 0;
comments = 0;
bp = macarg1 (ip->bufp, ip->buf + ip->length, ip->macro, &paren,
&newlines, &comments, rest_args);
final_start = bufsize;
bufsize += bp - ip->bufp;
extra += newlines;
buffer = (U_CHAR *) xrealloc (buffer, bufsize + extra + 1);
bcopy ((char *) ip->bufp, (char *) (buffer + bufsize - (bp - ip->bufp)),
bp - ip->bufp);
ip->bufp = bp;
ip->lineno += newlines;
}
if (argptr != 0) {
argptr->raw = buffer;
argptr->raw_length = bufsize;
argptr->free1 = buffer;
argptr->newlines = newlines;
if ((newlines || comments) && ip->fname != 0)
argptr->raw_length
= final_start +
discard_comments (argptr->raw + final_start,
argptr->raw_length - final_start,
newlines);
argptr->raw[argptr->raw_length] = 0;
if (argptr->raw_length > bufsize + extra)
abort ();
}
}
if (argptr != 0) {
register U_CHAR *buf, *lim;
register int totlen;
buf = argptr->raw;
lim = buf + argptr->raw_length;
while (buf != lim && is_space[*buf])
buf++;
while (buf != lim && is_space[lim[-1]])
lim--;
totlen = traditional ? 0 : 2;
while (buf != lim) {
register U_CHAR c = *buf++;
totlen++;
#if 0
if (is_space[c])
SKIP_ALL_WHITE_SPACE (buf);
else
#endif
if (c == '\"' || c == '\\')
totlen++;
}
argptr->stringified_length = totlen;
}
return result;
}
static U_CHAR *
macarg1 (start, limit, macro, depthptr, newlines, comments, rest_args)
U_CHAR *start;
register U_CHAR *limit;
struct hashnode *macro;
int *depthptr, *newlines, *comments;
int rest_args;
{
register U_CHAR *bp = start;
while (bp < limit) {
switch (*bp) {
case '(':
(*depthptr)++;
break;
case ')':
if (--(*depthptr) < 0)
return bp;
break;
case '\\':
if (traditional && bp + 1 < limit && bp[1] != '\n')
bp++;
break;
case '\n':
++*newlines;
break;
case '/':
if (macro)
break;
if (bp[1] == '\\' && bp[2] == '\n')
newline_fix (bp + 1);
if (bp[1] == '*') {
*comments = 1;
for (bp += 2; bp < limit; bp++) {
if (*bp == '\n')
++*newlines;
else if (*bp == '*') {
if (bp[-1] == '/' && warn_comments)
warning ("`/*' within comment");
if (bp[1] == '\\' && bp[2] == '\n')
newline_fix (bp + 1);
if (bp[1] == '/') {
bp++;
break;
}
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (bp, limit - bp);
if (length > 1)
bp += (length - 1);
#endif
}
}
} else if (bp[1] == '/' && cplusplus_comments) {
*comments = 1;
for (bp += 2; bp < limit; bp++) {
if (*bp == '\n') {
++*newlines;
break;
}
if (*bp == '\\' && bp + 1 < limit && bp[1] == '\n')
{
++*newlines;
if (warn_comments)
warning ("multiline `//' comment");
++bp;
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (bp, limit - bp);
if (length > 1)
bp += (length - 1);
#endif
}
}
}
break;
case '\'':
case '\"':
{
int quotec;
for (quotec = *bp++; bp + 1 < limit && *bp != quotec; bp++) {
if (*bp == '\\') {
bp++;
if (*bp == '\n')
++*newlines;
if (!macro) {
while (*bp == '\\' && bp[1] == '\n') {
bp += 2;
++*newlines;
}
}
} else if (*bp == '\n') {
++*newlines;
if (quotec == '\'')
break;
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
length = local_mblen (bp, limit - bp);
if (length > 1)
bp += (length - 1);
#endif
}
}
}
break;
case ',':
if ((*depthptr) == 0 && rest_args == 0)
return bp;
break;
}
bp++;
}
return bp;
}
static int
discard_comments (start, length, newlines)
U_CHAR *start;
int length;
int newlines;
{
register U_CHAR *ibp;
register U_CHAR *obp;
register U_CHAR *limit;
register int c;
if (newlines > 0) {
ibp = start + length;
obp = ibp + newlines;
limit = start;
while (limit != ibp)
*--obp = *--ibp;
}
ibp = start + newlines;
limit = start + length + newlines;
obp = start;
while (ibp < limit) {
*obp++ = c = *ibp++;
switch (c) {
case '\n':
*obp++ = '\n';
break;
case '\\':
if (*ibp == '\n') {
obp--;
ibp++;
}
break;
case '/':
if (*ibp == '\\' && ibp[1] == '\n')
newline_fix (ibp);
if (cplusplus_comments && ibp[0] == '/') {
obp[-1] = ' ';
ibp++;
while (ibp < limit)
{
if (*ibp == '\n')
break;
if (*ibp == '\\' && ibp + 1 < limit && ibp[1] == '\n')
ibp++;
else
{
#ifdef MULTIBYTE_CHARS
int length = local_mblen (ibp, limit - ibp);
if (length > 1)
ibp += (length - 1);
#endif
}
ibp++;
}
break;
}
if (ibp[0] != '*' || ibp + 1 >= limit)
break;
if (traditional)
obp--;
else
obp[-1] = ' ';
while (++ibp < limit) {
if (ibp[0] == '*') {
if (ibp[1] == '\\' && ibp[2] == '\n')
newline_fix (ibp + 1);
if (ibp[1] == '/') {
ibp += 2;
break;
}
}
else
{
#ifdef MULTIBYTE_CHARS
int length = local_mblen (ibp, limit - ibp);
if (length > 1)
ibp += (length - 1);
#endif
}
}
break;
case '\'':
case '\"':
{
int quotec = c;
while (ibp < limit) {
*obp++ = c = *ibp++;
if (c == quotec)
break;
if (c == '\n')
{
if (quotec == '\'')
break;
}
else if (c == '\\') {
if (ibp < limit && *ibp == '\n') {
ibp++;
obp--;
} else {
while (*ibp == '\\' && ibp[1] == '\n')
ibp += 2;
if (ibp < limit)
*obp++ = *ibp++;
}
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
ibp--;
length = local_mblen (ibp, limit - ibp);
if (length > 1)
{
obp--;
bcopy (ibp, obp, length);
ibp += length;
obp += length;
}
else
ibp++;
#endif
}
}
}
break;
}
}
return obp - start;
}
static int
change_newlines (start, length)
U_CHAR *start;
int length;
{
register U_CHAR *ibp;
register U_CHAR *obp;
register U_CHAR *limit;
register int c;
ibp = start;
limit = start + length;
obp = start;
while (ibp < limit) {
*obp++ = c = *ibp++;
switch (c) {
case '\n':
if (*ibp == '\n')
{
ibp++;
obp--;
*obp++ = ' ';
}
break;
case '\'':
case '\"':
{
int quotec = c;
while (ibp < limit) {
*obp++ = c = *ibp++;
if (c == quotec)
break;
else if (c == '\\' && ibp < limit && *ibp == '\n')
*obp++ = *ibp++;
else if (c == '\n')
{
if (quotec == '\'')
break;
}
else
{
#ifdef MULTIBYTE_CHARS
int length;
ibp--;
length = local_mblen (ibp, limit - ibp);
if (length > 1)
{
obp--;
bcopy (ibp, obp, length);
ibp += length;
obp += length;
}
else
ibp++;
#endif
}
}
}
break;
}
}
return obp - start;
}
static char *
my_strerror (errnum)
int errnum;
{
char *result;
#ifndef VMS
#ifndef HAVE_STRERROR
result = (char *) ((errnum < sys_nerr) ? sys_errlist[errnum] : 0);
#else
result = strerror (errnum);
#endif
#else
result = strerror (errnum, vaxc$errno);
#endif
if (!result)
result = "errno = ?";
return result;
}
static void
notice VPROTO ((const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char * msgid;
#endif
va_list args;
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
msgid = va_arg (args, const char *);
#endif
vnotice (msgid, args);
va_end (args);
}
static void
vnotice (msgid, args)
const char *msgid;
va_list args;
{
vfprintf (stderr, _(msgid), args);
}
void
error VPROTO ((const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char * msgid;
#endif
va_list args;
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
msgid = va_arg (args, const char *);
#endif
verror (msgid, args);
va_end (args);
}
void
verror (msgid, args)
const char *msgid;
va_list args;
{
int i;
FILE_BUF *ip = NULL;
print_containing_files ();
for (i = indepth; i >= 0; i--)
if (instack[i].fname != NULL) {
ip = &instack[i];
break;
}
#ifdef REPORT_EVENT
V_REPORT_EVENT (0, NULL, ip ? ip->nominal_fname : NULL, ip ? ip->lineno : 0,
msgid, args);
#endif
if (ip != NULL) {
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d: ", ip->lineno);
}
vnotice (msgid, args);
fprintf (stderr, "\n");
errors++;
}
static void
error_from_errno (name)
char *name;
{
int e = errno;
int i;
FILE_BUF *ip = NULL;
print_containing_files ();
for (i = indepth; i >= 0; i--)
if (instack[i].fname != NULL) {
ip = &instack[i];
break;
}
#ifdef REPORT_EVENT
REPORT_EVENT (0, NULL,
ip ? ip->nominal_fname : NULL,
ip ? ip->lineno : 0,
"%s: %s", name, my_strerror (e), 0);
#endif
if (ip != NULL) {
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d: ", ip->lineno);
}
fprintf (stderr, "%s: %s\n", name, my_strerror (e));
errors++;
}
void
warning VPROTO ((const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char * msgid;
#endif
va_list args;
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
msgid = va_arg (args, const char *);
#endif
vwarning (msgid, args);
va_end (args);
}
static void
vwarning (msgid, args)
const char *msgid;
va_list args;
{
int i;
FILE_BUF *ip = NULL;
if (inhibit_warnings)
return;
if (warnings_are_errors)
errors++;
print_containing_files ();
for (i = indepth; i >= 0; i--)
if (instack[i].fname != NULL) {
ip = &instack[i];
break;
}
#ifdef REPORT_EVENT
V_REPORT_EVENT (1, NULL, ip ? ip->nominal_fname : NULL, ip ? ip->lineno : 0,
msgid, args);
#endif
if (ip != NULL) {
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d: ", ip->lineno);
}
notice ("warning: ");
vnotice (msgid, args);
fprintf (stderr, "\n");
}
static void
error_with_line VPROTO ((int line, const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
int line;
const char * msgid;
#endif
va_list args;
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
line = va_arg (args, int);
msgid = va_arg (args, const char *);
#endif
verror_with_line (line, msgid, args);
va_end (args);
}
static void
verror_with_line (line, msgid, args)
int line;
const char *msgid;
va_list args;
{
int i;
FILE_BUF *ip = NULL;
print_containing_files ();
for (i = indepth; i >= 0; i--)
if (instack[i].fname != NULL) {
ip = &instack[i];
break;
}
#ifdef REPORT_EVENT
V_REPORT_EVENT (0, NULL, ip ? ip->nominal_fname : NULL, line, msgid, args);
#endif
if (ip != NULL) {
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d: ", line);
}
vnotice (msgid, args);
fprintf (stderr, "\n");
errors++;
}
static void
warning_with_line VPROTO ((int line, const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
int line;
const char * msgid;
#endif
va_list args;
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
line = va_arg (args, int);
msgid = va_arg (args, const char *);
#endif
vwarning_with_line (line, msgid, args);
va_end (args);
}
static void
vwarning_with_line (line, msgid, args)
int line;
const char *msgid;
va_list args;
{
int i;
FILE_BUF *ip = NULL;
if (inhibit_warnings)
return;
if (warnings_are_errors)
errors++;
print_containing_files ();
for (i = indepth; i >= 0; i--)
if (instack[i].fname != NULL) {
ip = &instack[i];
break;
}
#ifdef REPORT_EVENT
V_REPORT_EVENT (warnings_are_errors ? 0 : 1, NULL,
ip ? ip->nominal_fname : NULL, line, msgid, args);
#endif
if (ip != NULL) {
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, line ? ":%d: " : ": ", line);
}
notice ("warning: ");
vnotice (msgid, args);
fprintf (stderr, "\n");
}
void
pedwarn VPROTO ((const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char * msgid;
#endif
va_list args;
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
msgid = va_arg (args, const char *);
#endif
if (pedantic_errors)
verror (msgid, args);
else
vwarning (msgid, args);
va_end (args);
}
void
pedwarn_with_line VPROTO ((int line, const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
int line;
const char * msgid;
#endif
va_list args;
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
line = va_arg (args, int);
msgid = va_arg (args, const char *);
#endif
if (pedantic_errors)
verror_with_line (line, msgid, args);
else
vwarning_with_line (line, msgid, args);
va_end (args);
}
static void
pedwarn_with_file_and_line VPROTO ((const char *file, size_t file_len, int line,
const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char *file;
size_t file_len;
int line;
const char * msgid;
#endif
va_list args;
if (!pedantic_errors && inhibit_warnings)
return;
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
file = va_arg (args, const char *);
file_len = va_arg (args, size_t);
line = va_arg (args, int);
msgid = va_arg (args, const char *);
#endif
#ifdef REPORT_EVENT
V_REPORT_EVENT (pedantic_errors ? 0 : 1, NULL, file, line, msgid, args);
#endif
if (file) {
eprint_string (file, file_len);
fprintf (stderr, ":%d: ", line);
}
if (pedantic_errors)
errors++;
if (!pedantic_errors)
notice ("warning: ");
vnotice (msgid, args);
va_end (args);
fprintf (stderr, "\n");
}
static void
pedwarn_strange_white_space (ch)
int ch;
{
switch (ch)
{
case '\f': pedwarn ("formfeed in preprocessing directive"); break;
case '\r': pedwarn ("carriage return in preprocessing directive"); break;
case '\v': pedwarn ("vertical tab in preprocessing directive"); break;
default: abort ();
}
}
static void
print_containing_files ()
{
FILE_BUF *ip = NULL;
int i;
int first = 1;
if (last_error_tick == input_file_stack_tick)
return;
for (i = indepth; i >= 0; i--)
if (instack[i].fname != NULL) {
ip = &instack[i];
break;
}
if (ip == NULL)
return;
for (i--; i >= 0; i--)
if (instack[i].fname != NULL) {
ip = &instack[i];
if (first) {
first = 0;
notice ( "In file included from ");
} else {
notice (",\n from ");
}
eprint_string (ip->nominal_fname, ip->nominal_fname_len);
fprintf (stderr, ":%d", ip->lineno);
}
if (! first)
fprintf (stderr, ":\n");
last_error_tick = input_file_stack_tick;
}
static int
line_for_error (line)
int line;
{
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 ();
return 0;
}
static int
grow_outbuf (obuf, needed)
register FILE_BUF *obuf;
register int needed;
{
register U_CHAR *p;
int minsize;
if (obuf->length - (obuf->bufp - obuf->buf) > needed)
return 0;
obuf->length *= 2;
minsize = (3 * needed) / 2 + (obuf->bufp - obuf->buf);
if (minsize > obuf->length)
obuf->length = minsize;
if ((p = (U_CHAR *) xrealloc (obuf->buf, obuf->length)) == NULL)
memory_full ();
obuf->bufp = p + (obuf->bufp - obuf->buf);
#ifdef NEXT_CPP_SERVER
obuf->output_written_to = p + (obuf->output_written_to - obuf->buf);
#endif
obuf->buf = p;
return 0;
}
static HASHNODE *
install (name, len, type, value, hash)
U_CHAR *name;
int len;
enum node_type type;
char *value;
int hash;
{
register HASHNODE *hp;
register int i, bucket;
register U_CHAR *p, *q;
if (len < 0) {
p = name;
while (is_idchar[*p])
p++;
len = p - name;
}
if (hash < 0)
hash = hashf (name, len, HASHSIZE);
i = sizeof (HASHNODE) + len + 1;
hp = (HASHNODE *) xmalloc (i);
bucket = hash;
hp->bucket_hdr = &hashtab[bucket];
hp->next = hashtab[bucket];
hashtab[bucket] = hp;
hp->prev = NULL;
if (hp->next != NULL)
hp->next->prev = hp;
hp->type = type;
hp->length = len;
hp->value.cpval = value;
hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
#ifdef NEXT_CPP_SERVER
hp->defined_within_module = 1;
hp->owner = 0;
#endif
p = hp->name;
q = name;
for (i = 0; i < len; i++)
*p++ = *q++;
hp->name[len] = 0;
return hp;
}
HASHNODE *
lookup (name, len, hash)
U_CHAR *name;
int len;
int hash;
{
register U_CHAR *bp;
register HASHNODE *bucket;
if (len < 0) {
for (bp = name; is_idchar[*bp]; bp++) ;
len = bp - name;
}
if (hash < 0)
#ifdef NEXT_CPP_SERVER
{
#endif
hash = hashf (name, len, HASHSIZE);
bucket = hashtab[hash];
while (bucket) {
if (bucket->length == len && bcmp (bucket->name, name, len) == 0)
#ifdef NEXT_CPP_SERVER
return bucket->defined_within_module ? bucket : NULL;
bucket = bucket->next;
}
} else {
bucket = hashtab[hash];
while (bucket) {
if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
#endif
return bucket;
bucket = bucket->next;
#ifdef NEXT_CPP_SERVER
}
#endif
}
return NULL;
}
static void
delete_macro (hp)
HASHNODE *hp;
{
if (hp->prev != NULL)
hp->prev->next = hp->next;
if (hp->next != NULL)
hp->next->prev = hp->prev;
if (hp == *hp->bucket_hdr)
*hp->bucket_hdr = hp->next;
#if 0
if (hp->type == T_MACRO) {
DEFINITION *d = hp->value.defn;
struct reflist *ap, *nextap;
for (ap = d->pattern; ap != NULL; ap = nextap) {
nextap = ap->next;
free (ap);
}
free (d);
}
#endif
#ifdef NEXT_CPP_SERVER
if (!hp->owner) {
if (hp->type == T_MACRO) {
hp->next = free_undefined_macros;
free_undefined_macros = hp;
} else {
#endif
free (hp);
#ifdef NEXT_CPP_SERVER
}
}
#endif
}
static int
hashf (name, len, hashsize)
register U_CHAR *name;
register int len;
int hashsize;
{
register int r = 0;
while (len--)
r = HASHSTEP (r, *name++);
return MAKE_POS (r) % hashsize;
}
static void
dump_single_macro (hp, of)
register HASHNODE *hp;
FILE *of;
{
register DEFINITION *defn = hp->value.defn;
struct reflist *ap;
int offset;
int concat;
fprintf (of, "#define %s", hp->name);
if (defn->nargs >= 0) {
int i;
fprintf (of, "(");
for (i = 0; i < defn->nargs; i++) {
dump_arg_n (defn, i, of);
if (i + 1 < defn->nargs)
fprintf (of, ", ");
}
fprintf (of, ")");
}
fprintf (of, " ");
offset = 0;
concat = 0;
for (ap = defn->pattern; ap != NULL; ap = ap->next) {
dump_defn_1 (defn->expansion, offset, ap->nchars, of);
offset += ap->nchars;
if (!traditional) {
if (ap->nchars != 0)
concat = 0;
if (ap->stringify) {
switch (ap->stringify) {
case SHARP_TOKEN: fprintf (of, "#"); break;
case WHITE_SHARP_TOKEN: fprintf (of, "# "); break;
case PERCENT_COLON_TOKEN: fprintf (of, "%%:"); break;
case WHITE_PERCENT_COLON_TOKEN: fprintf (of, "%%: "); break;
default: abort ();
}
}
if (ap->raw_before != 0) {
if (concat) {
switch (ap->raw_before) {
case WHITE_SHARP_TOKEN:
case WHITE_PERCENT_COLON_TOKEN:
fprintf (of, " ");
break;
default:
break;
}
} else {
switch (ap->raw_before) {
case SHARP_TOKEN: fprintf (of, "##"); break;
case WHITE_SHARP_TOKEN: fprintf (of, "## "); break;
case PERCENT_COLON_TOKEN: fprintf (of, "%%:%%:"); break;
case WHITE_PERCENT_COLON_TOKEN: fprintf (of, "%%:%%: "); break;
default: abort ();
}
}
}
concat = 0;
}
dump_arg_n (defn, ap->argno, of);
if (!traditional && ap->raw_after != 0) {
switch (ap->raw_after) {
case SHARP_TOKEN: fprintf (of, "##"); break;
case WHITE_SHARP_TOKEN: fprintf (of, " ##"); break;
case PERCENT_COLON_TOKEN: fprintf (of, "%%:%%:"); break;
case WHITE_PERCENT_COLON_TOKEN: fprintf (of, " %%:%%:"); break;
default: abort ();
}
concat = 1;
}
}
dump_defn_1 (defn->expansion, offset, defn->length - offset, of);
fprintf (of, "\n");
}
static void
dump_all_macros ()
{
int bucket;
for (bucket = 0; bucket < HASHSIZE; bucket++) {
register HASHNODE *hp;
for (hp = hashtab[bucket]; hp; hp= hp->next) {
if (hp->type == T_MACRO)
dump_single_macro (hp, stdout);
}
}
}
static void
dump_defn_1 (base, start, length, of)
U_CHAR *base;
int start;
int length;
FILE *of;
{
U_CHAR *p = base + start;
U_CHAR *limit = base + start + length;
if (traditional)
fwrite (p, sizeof (*p), length, of);
else {
while (p < limit) {
if (*p == '\"' || *p =='\'') {
U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR,
NULL_PTR, NULL_PTR);
fwrite (p, sizeof (*p), p1 - p, of);
p = p1;
} else {
if (*p != '\n')
putc (*p, of);
p++;
}
}
}
}
static void
dump_arg_n (defn, argnum, of)
DEFINITION *defn;
int argnum;
FILE *of;
{
register U_CHAR *p = defn->args.argnames;
while (argnum + 1 < defn->nargs) {
p = (U_CHAR *) index ((char *) p, ' ') + 1;
argnum++;
}
while (*p && *p != ',') {
putc (*p, of);
p++;
}
}
static void
initialize_char_syntax ()
{
register int i;
for (i = 'a'; i <= 'z'; i++) {
is_idchar[i - 'a' + 'A'] = 1;
is_idchar[i] = 1;
is_idstart[i - 'a' + 'A'] = 1;
is_idstart[i] = 1;
}
for (i = '0'; i <= '9'; i++)
is_idchar[i] = 1;
is_idchar['_'] = 1;
is_idstart['_'] = 1;
is_idchar['$'] = 1;
is_idstart['$'] = 1;
is_hor_space[' '] = 1;
is_hor_space['\t'] = 1;
is_hor_space['\v'] = 1;
is_hor_space['\f'] = 1;
is_hor_space['\r'] = 1;
is_space[' '] = 1;
is_space['\t'] = 1;
is_space['\v'] = 1;
is_space['\f'] = 1;
is_space['\n'] = 1;
is_space['\r'] = 1;
}
static void
initialize_builtins (inp, outp)
FILE_BUF *inp;
FILE_BUF *outp;
{
install ((U_CHAR *) "__LINE__", -1, T_SPECLINE, NULL_PTR, -1);
install ((U_CHAR *) "__DATE__", -1, T_DATE, NULL_PTR, -1);
install ((U_CHAR *) "__FILE__", -1, T_FILE, NULL_PTR, -1);
install ((U_CHAR *) "__BASE_FILE__", -1, T_BASE_FILE, NULL_PTR, -1);
install ((U_CHAR *) "__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, NULL_PTR, -1);
install ((U_CHAR *) "__VERSION__", -1, T_VERSION, NULL_PTR, -1);
#ifndef NO_BUILTIN_SIZE_TYPE
install ((U_CHAR *) "__SIZE_TYPE__", -1, T_SIZE_TYPE, NULL_PTR, -1);
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
install ((U_CHAR *) "__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, NULL_PTR, -1);
#endif
install ((U_CHAR *) "__WCHAR_TYPE__", -1, T_WCHAR_TYPE, NULL_PTR, -1);
install ((U_CHAR *) "__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE,
NULL_PTR, -1);
install ((U_CHAR *) "__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE,
NULL_PTR, -1);
install ((U_CHAR *) "__IMMEDIATE_PREFIX__", -1, T_IMMEDIATE_PREFIX_TYPE,
NULL_PTR, -1);
install ((U_CHAR *) "__TIME__", -1, T_TIME, NULL_PTR, -1);
if (!traditional) {
install ((U_CHAR *) "__STDC__", -1, T_CONST, "1", -1);
install ((U_CHAR *) "__STDC_VERSION__", -1, T_CONST, "199409L", -1);
}
#ifdef NEXT_SEMANTICS
if (objc)
install ((U_CHAR *) "__OBJC__", -1, T_CONST, NULL_PTR, -1);
#ifdef NEXT_CPP_SERVER
install ((U_CHAR *) "_NEXT_SOURCE", -1, T_CONST, NULL_PTR, -1);
install ((U_CHAR *) "__GNUC__", -1, T_CONST, NULL_PTR, -1);
#endif
#endif
install ((U_CHAR *) "__HAVE_BUILTIN_SETJMP__", -1, T_CONST, "1", -1);
if (debug_output)
{
char directive[2048];
U_CHAR *udirective = (U_CHAR *) directive;
register struct directive *dp = &directive_table[0];
struct tm *timebuf = timestamp ();
sprintf (directive, " __BASE_FILE__ \"%s\"\n",
instack[0].nominal_fname);
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
sprintf (directive, " __VERSION__ \"%s\"\n", version_string);
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
#ifndef NO_BUILTIN_SIZE_TYPE
sprintf (directive, " __SIZE_TYPE__ %s\n", SIZE_TYPE);
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
sprintf (directive, " __PTRDIFF_TYPE__ %s\n", PTRDIFF_TYPE);
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
#endif
sprintf (directive, " __WCHAR_TYPE__ %s\n", wchar_type);
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
sprintf (directive, " __DATE__ \"%s %2d %4d\"\n",
monthnames[timebuf->tm_mon],
timebuf->tm_mday, timebuf->tm_year + 1900);
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
sprintf (directive, " __TIME__ \"%02d:%02d:%02d\"\n",
timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
if (!traditional)
{
sprintf (directive, " __STDC__ 1");
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
}
if (objc)
{
sprintf (directive, " __OBJC__ 1");
output_line_directive (inp, outp, 0, same_file);
pass_thru_directive (udirective, &udirective[strlen (directive)],
outp, dp);
}
}
}
static void
make_definition (str)
char *str;
{
FILE_BUF *ip;
struct directive *kt;
U_CHAR *buf, *p;
p = buf = (U_CHAR *) str;
if (!is_idstart[*p]) {
error ("malformed option `-D %s'", str);
return;
}
while (is_idchar[*++p])
;
if (*p == '(') {
while (is_idchar[*++p] || *p == ',' || is_hor_space[*p])
;
if (*p++ != ')')
p = (U_CHAR *) str;
}
if (*p == 0) {
buf = (U_CHAR *) alloca (p - buf + 4);
strcpy ((char *)buf, str);
strcat ((char *)buf, " 1");
} else if (*p != '=') {
error ("malformed option `-D %s'", str);
return;
} else {
U_CHAR *q;
buf = (U_CHAR *) alloca (2 * strlen (str) + 1);
strncpy ((char *) buf, str, p - (U_CHAR *) str);
buf[p - (U_CHAR *) str] = ' ';
p++;
q = &buf[p - (U_CHAR *) str];
while (*p) {
if (*p == '\"' || *p == '\'') {
int unterminated = 0;
U_CHAR *p1 = skip_quoted_string (p, p + strlen ((char *) p), 0,
NULL_PTR, NULL_PTR, &unterminated);
if (unterminated)
return;
while (p != p1)
*q++ = *p++;
} else if (*p == '\\' && p[1] == '\n')
p += 2;
else if (*p == '\n')
{
*q++ = '\n';
*q++ = '\n';
p++;
}
else
*q++ = *p++;
}
*q = 0;
}
ip = &instack[++indepth];
ip->nominal_fname = ip->fname = "*Initialization*";
ip->nominal_fname_len = strlen (ip->nominal_fname);
ip->buf = ip->bufp = buf;
ip->length = strlen ((char *) buf);
ip->lineno = 1;
ip->macro = 0;
ip->free_ptr = 0;
ip->if_stack = if_stack;
ip->system_header_p = 0;
#ifdef NEXT_CPP_SERVER
ip->dir = ip->file = 0;
ip->beg_of_line = 0;
#endif
for (kt = directive_table; kt->type != T_DEFINE; kt++)
;
do_define (buf, buf + strlen ((char *) buf), NULL_PTR, kt);
--indepth;
}
static void
make_undef (str, op)
char *str;
FILE_BUF *op;
{
FILE_BUF *ip;
struct directive *kt;
ip = &instack[++indepth];
ip->nominal_fname = ip->fname = "*undef*";
ip->nominal_fname_len = strlen (ip->nominal_fname);
ip->buf = ip->bufp = (U_CHAR *) str;
ip->length = strlen (str);
ip->lineno = 1;
ip->macro = 0;
ip->free_ptr = 0;
ip->if_stack = if_stack;
ip->system_header_p = 0;
for (kt = directive_table; kt->type != T_UNDEF; kt++)
;
do_undef ((U_CHAR *) str, (U_CHAR *) str + strlen (str), op, kt);
--indepth;
}
static void
make_assertion (option, str)
const char *option;
const char *str;
{
FILE_BUF *ip;
struct directive *kt;
U_CHAR *buf, *p, *q;
buf = (U_CHAR *) alloca (strlen (str) + 1);
strcpy ((char *) buf, str);
p = q = buf;
while (*p) {
if (*p == '\\' && p[1] == '\n')
p += 2;
else
*q++ = *p++;
}
*q = 0;
p = buf;
if (!is_idstart[*p]) {
error ("malformed option `%s %s'", option, str);
return;
}
while (is_idchar[*++p])
;
SKIP_WHITE_SPACE (p);
if (! (*p == 0 || *p == '(')) {
error ("malformed option `%s %s'", option, str);
return;
}
ip = &instack[++indepth];
ip->nominal_fname = ip->fname = "*Initialization*";
ip->nominal_fname_len = strlen (ip->nominal_fname);
ip->buf = ip->bufp = buf;
ip->length = strlen ((char *) buf);
ip->lineno = 1;
ip->macro = 0;
ip->free_ptr = 0;
ip->if_stack = if_stack;
ip->system_header_p = 0;
#ifdef NEXT_CPP_SERVER
ip->dir = ip->file = 0;
ip->beg_of_line = 0;
#endif
for (kt = directive_table; kt->type != T_ASSERT; kt++)
;
do_assert (buf, buf + strlen ((char *) buf) , NULL_PTR, kt);
--indepth;
}
static struct file_name_list *
new_include_prefix (prev_file_name, component, prefix, name)
struct file_name_list *prev_file_name;
const char *component;
const char *prefix;
const char *name;
{
if (name == 0)
fatal ("Directory name missing after command line option");
if (*name == 0)
return 0;
prefix = update_path (prefix, component);
name = update_path (name, component);
{
struct file_name_list *dir
= ((struct file_name_list *)
xmalloc (sizeof (struct file_name_list)
+ strlen (prefix) + strlen (name) + 2));
size_t len;
strcpy (dir->fname, prefix);
strcat (dir->fname, name);
len = simplify_filename (dir->fname);
if (len && dir->fname[len - 1] != DIR_SEPARATOR) {
if (len == 1 && dir->fname[len - 1] == '.')
len = 0;
else
#ifdef VMS
dir->fname[len++] = '/';
#else
dir->fname[len++] = DIR_SEPARATOR;
#endif
dir->fname[len] = 0;
}
if (prev_file_name && !strcmp (prev_file_name->fname, dir->fname)) {
if (!first_bracket_include)
first_bracket_include = prev_file_name;
free (dir);
return 0;
}
#ifndef VMS
if (len != 0)
{
dir->fname[len] = '.';
dir->fname[len + 1] = 0;
}
if (stat (len ? dir->fname : ".", &dir->st) != 0) {
if (errno != ENOENT && errno != ENOTDIR)
error_from_errno (dir->fname);
free (dir);
return 0;
}
if (len != 0)
dir->fname[len] = 0;
if (prev_file_name
&& INO_T_EQ (prev_file_name->st.st_ino, dir->st.st_ino)
&& prev_file_name->st.st_dev == dir->st.st_dev) {
if (!first_bracket_include)
first_bracket_include = prev_file_name;
free (dir);
return 0;
}
#endif
dir->next = 0;
dir->c_system_include_path = 0;
dir->got_name_map = 0;
return dir;
}
}
static void
append_include_chain (first, last)
struct file_name_list *first, *last;
{
struct file_name_list *dir;
if (!first || !last)
return;
if (include == 0)
include = first;
else
last_include->next = first;
if (first_bracket_include == 0)
first_bracket_include = first;
for (dir = first; ; dir = dir->next) {
int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
if (len > max_include_len)
max_include_len = len;
if (dir == last)
break;
}
last->next = NULL;
last_include = last;
}
#ifdef NEXT_FRAMEWORKS
static void
append_framework_chain (first, last)
struct file_name_list *first, *last;
{
struct file_name_list *dir;
if (!first || !last)
return;
if (framework == 0)
framework = first;
else
last_framework->next = first;
if (first_bracket_framework == 0)
first_bracket_framework = first;
for (dir = first; ; dir = dir->next) {
int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
if (len > max_include_len)
max_include_len = len;
if (dir == last)
break;
}
last->next = NULL;
last_framework = last;
}
#endif
static int
quote_string_for_make (dst, src)
char *dst;
const char *src;
{
const char *p = src;
int i = 0;
for (;;)
{
char c = *p++;
switch (c)
{
case '\0':
case ' ':
case '\t':
{
const char *q;
for (q = p - 1; src < q && q[-1] == '\\'; q--)
{
if (dst)
dst[i] = '\\';
i++;
}
}
if (!c)
return i;
if (dst)
dst[i] = '\\';
i++;
goto ordinary_char;
case '$':
if (dst)
dst[i] = c;
i++;
default:
ordinary_char:
if (dst)
dst[i] = c;
i++;
break;
}
}
}
static void
deps_output (string, spacer)
const char *string;
int spacer;
{
int size = quote_string_for_make ((char *) 0, string);
if (size == 0)
return;
#ifndef MAX_OUTPUT_COLUMNS
#define MAX_OUTPUT_COLUMNS 72
#endif
if (MAX_OUTPUT_COLUMNS - 1 - 2 < deps_column + size
&& 1 < deps_column) {
bcopy (" \\\n ", &deps_buffer[deps_size], 4);
deps_size += 4;
deps_column = 1;
if (spacer == ' ')
spacer = 0;
}
if (deps_size + 2 * size + 8 > deps_allocated_size) {
deps_allocated_size = (deps_size + 2 * size + 50) * 2;
deps_buffer = xrealloc (deps_buffer, deps_allocated_size);
}
if (spacer == ' ') {
deps_buffer[deps_size++] = ' ';
deps_column++;
}
quote_string_for_make (&deps_buffer[deps_size], string);
deps_size += size;
deps_column += size;
if (spacer == ':') {
deps_buffer[deps_size++] = ':';
deps_column++;
}
deps_buffer[deps_size] = 0;
}
void
fatal VPROTO ((const char * msgid, ...))
{
#ifndef ANSI_PROTOTYPES
const char * msgid;
#endif
va_list args;
fprintf (stderr, "%s: ", progname);
VA_START (args, msgid);
#ifndef ANSI_PROTOTYPES
msgid = va_arg (args, const char *);
#endif
#ifdef REPORT_EVENT
V_REPORT_EVENT (0, progname, NULL, 0, msgid, args);
#endif
vnotice (msgid, args);
va_end (args);
fprintf (stderr, "\n");
#ifdef NEXT_CPP_SERVER
if (serverized)
return;
#endif
exit (FATAL_EXIT_CODE);
}
void
fancy_abort ()
{
fatal ("Internal gcc abort.");
}
static void
perror_with_name (name)
char *name;
{
#ifdef REPORT_EVENT
REPORT_EVENT (0, progname, NULL, 0,
"%s: %s", name,
(errno < sys_nerr)
? sys_errlist[errno]
: "undocumented I/O error",
0);
#endif
fprintf (stderr, "%s: %s: %s\n", progname, name, my_strerror (errno));
errors++;
}
static void
pfatal_with_name (name)
char *name;
{
#ifdef REPORT_EVENT
REPORT_EVENT (0, progname, NULL, 0,
"%s: %s", name,
(errno < sys_nerr)
? sys_errlist[errno]
: "undocumented I/O error",
0);
#endif
perror_with_name (name);
#ifdef VMS
exit (vaxc$errno);
#else
exit (FATAL_EXIT_CODE);
#endif
}
static void
pipe_closed (signo)
int signo ATTRIBUTE_UNUSED;
{
fatal ("output pipe has been closed");
}
static void
memory_full ()
{
fatal ("Memory exhausted.");
}
PTR
xmalloc (size)
size_t size;
{
register PTR ptr = (PTR) malloc (size);
if (!ptr)
memory_full ();
return ptr;
}
PTR
xrealloc (old, size)
PTR old;
size_t size;
{
register PTR ptr;
if (old)
ptr = (PTR) realloc (old, size);
else
ptr = (PTR) malloc (size);
if (!ptr)
memory_full ();
return ptr;
}
PTR
xcalloc (number, size)
size_t number, size;
{
register size_t total = number * size;
register PTR ptr = (PTR) malloc (total);
if (!ptr)
memory_full ();
bzero (ptr, total);
return ptr;
}
static char *
savestring (input)
char *input;
{
size_t size = strlen (input);
char *output = xmalloc (size + 1);
#ifdef NEXT_FRAMEWORKS
strncpy (output, input, size + 1);
#else
strcpy (output, input);
#endif
return output;
}
char *
xstrdup (input)
const char *input;
{
register size_t len = strlen (input) + 1;
register char *output = xmalloc (len);
memcpy (output, input, len);
return output;
}
#ifdef VMS
static int
hack_vms_include_specification (fullname, vaxc_include)
char *fullname;
int vaxc_include;
{
register char *basename, *unixname, *local_ptr, *first_slash;
int f, check_filename_before_returning, must_revert;
char Local[512];
check_filename_before_returning = 0;
must_revert = 0;
first_slash = index (fullname, '/');
if (first_slash == 0)
return 0;
if (index (fullname, ':') == 0)
{
if (first_slash == fullname)
{
first_slash = index (fullname+1, '/');
if (first_slash)
*first_slash = ':';
for (basename = fullname; *basename != 0; basename++)
*basename = *(basename+1);
}
else if ((first_slash[-1] != '.')
&& (first_slash[-1] != ':')
&& (first_slash[-1] != ']'))
{
*first_slash = ':';
}
else if ((first_slash[1] == '[')
&& (first_slash[-1] == '.'))
fullname += 2;
}
basename = base_name (fullname);
if (vaxc_include && !index (basename,'.'))
strcat (basename, ".h");
local_ptr = Local;
if ((basename[-1] == ':')
|| (basename[-1] == ']')
|| (basename[-1] == '>'))
unixname = basename;
else
unixname = fullname;
if (*unixname == '/')
unixname++;
if (((basename - fullname) > 1)
&& ( (basename[-1] == ']')
|| (basename[-1] == '>')))
{
if (basename[-2] != '.')
{
basename -= 1;
unixname--;
}
else
{
basename -= 2;
unixname--;
}
}
else
{
if ((unixname != fullname)
&& (basename[-1] != ':'))
*local_ptr++ = ':';
*local_ptr++ = '[';
}
if (unixname == fullname)
{
must_revert = 1;
if ((first_slash != 0)
&& (*unixname != '/')
&& (*unixname != '.'))
*local_ptr++ = '.';
}
if (index (unixname, '/') == 0)
{
if (local_ptr[-1] == '[')
{
strcpy (local_ptr, "000000]");
local_ptr += strlen (local_ptr);
check_filename_before_returning = 1;
}
}
else
{
while (index (unixname, '/') != 0)
{
if ((unixname[0] == '.') && (unixname[1] == '/'))
{
if ( ((unixname == fullname)
&& (fullname+2 != basename))
|| ((basename[-1] == ':')
&& (unixname-1 == basename)))
*local_ptr++ = '.';
unixname += 2;
continue;
}
if ( local_ptr[-1] != '.'
&& local_ptr[-1] != '['
&& local_ptr[-1] != '<')
*local_ptr++ = '.';
if ( (unixname[0] == '.')
&& (unixname[1] == '.')
&& (unixname[2] == '/'))
{
if ((local_ptr[-1] == '.')
&& (local_ptr[-2] == '['))
local_ptr--;
*local_ptr++ = '-';
unixname += 3;
continue;
}
while (*unixname != '/')
*local_ptr++= *unixname++;
unixname++;
}
if (local_ptr[-1] == '.')
local_ptr--;
if (local_ptr[-1] == '[')
local_ptr--;
else
*local_ptr++ = ']';
}
while (*unixname)
*local_ptr++ = *unixname++;
*local_ptr = 0;
strcpy ((must_revert==1)?fullname:basename, Local);
if (check_filename_before_returning)
{
f = open (fullname, O_RDONLY, 0666);
if (f >= 0)
{
close (f);
return 1;
}
basename = index (fullname, '[');
local_ptr = index (fullname, ']') + 1;
strcpy (basename, local_ptr);
}
return 1;
}
#endif
#ifdef VMS
static FILE *
VMS_freopen (fname, type, oldfile)
char *fname;
char *type;
FILE *oldfile;
{
#undef freopen
if (strcmp (type, "w") == 0)
return freopen (fname, type, oldfile,
"mbc=16", "deq=64", "fop=tef", "shr=nil");
return freopen (fname, type, oldfile, "mbc=16");
}
static FILE *
VMS_fopen (fname, type)
char *fname;
char *type;
{
#undef fopen
FILE *(*vmslib_fopen)() = (FILE *(*)()) fopen;
if (*type == 'w')
return (*vmslib_fopen) (fname, type, "mbc=32",
"deq=64", "fop=tef", "shr=nil");
else
return (*vmslib_fopen) (fname, type, "mbc=32");
}
static int
VMS_open (fname, flags, prot)
char *fname;
int flags;
int prot;
{
#undef open
return open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef");
}
#include <fab.h>
#include <nam.h>
extern unsigned long SYS$PARSE(), SYS$SEARCH();
#undef fstat
static int
VMS_fstat (fd, statbuf)
int fd;
struct stat *statbuf;
{
int result = fstat (fd, statbuf);
if (result < 0)
{
FILE *fp;
char nambuf[NAM$C_MAXRSS+1];
if ((fp = fdopen (fd, "r")) != 0 && fgetname (fp, nambuf) != 0)
result = VMS_stat (nambuf, statbuf);
}
return result;
}
static int
VMS_stat (name, statbuf)
const char *name;
struct stat *statbuf;
{
int result = stat (name, statbuf);
if (result < 0)
{
struct FAB fab;
struct NAM nam;
char exp_nam[NAM$C_MAXRSS+1],
res_nam[NAM$C_MAXRSS+1];
fab = cc$rms_fab;
fab.fab$l_fna = (char *) name;
fab.fab$b_fns = (unsigned char) strlen (name);
fab.fab$l_nam = (void *) &nam;
nam = cc$rms_nam;
nam.nam$l_esa = exp_nam, nam.nam$b_ess = sizeof exp_nam - 1;
nam.nam$l_rsa = res_nam, nam.nam$b_rss = sizeof res_nam - 1;
nam.nam$b_nop = NAM$M_PWD | NAM$M_NOCONCEAL;
if (SYS$PARSE (&fab) & 1)
{
if (SYS$SEARCH (&fab) & 1)
{
res_nam[nam.nam$b_rsl] = '\0';
result = stat (res_nam, statbuf);
}
nam.nam$b_nop = NAM$M_SYNCHK;
fab.fab$l_fna = 0, fab.fab$b_fns = 0;
(void) SYS$PARSE (&fab);
}
}
return result;
}
#endif
#ifdef NEXT_SEMANTICS
#define RTF_HEADER "{\\rtf0\\ansi"
#define RTF_HEADER_LEN 11
static void
buf_convert_rtf (buf)
FILE_BUF *buf;
{
int asciiTextLen;
if (buf->buf
&& buf->length > RTF_HEADER_LEN
&& !strncmp (buf->buf, RTF_HEADER, RTF_HEADER_LEN))
{
const char * asciiText = rtf_to_ascii(buf->buf, buf->length, &asciiTextLen);
if (asciiText)
{
buf->buf = buf->bufp = (char *) asciiText;
buf->length = asciiTextLen;
}
}
}
#define ASCII_TERMINATOR '\0'
static const char *
rtf_to_ascii (const char *rtfTextPtr, int rtfTextLen, int * asciiTextLen)
{
char * asciiTextBuf = (char *) xmalloc(rtfTextLen);
char * asciiTextPtr = asciiTextBuf;
const char *endRtfPtr = rtfTextPtr + rtfTextLen;
if (!asciiTextBuf)
return NULL;
while ( rtfTextPtr != endRtfPtr ) {
switch( *rtfTextPtr ) {
case '\n':
rtfTextPtr++;
break;
case '}':
if ( *++rtfTextPtr == '\n' ) {
rtfTextPtr++;
if (*rtfTextPtr == '¨') rtfTextPtr++;
}
break;
case '{':
if ( !strncmp( rtfTextPtr, "{\\stylesheet", 12 )
|| !strncmp( rtfTextPtr, "{\\fonttbl", 9 )
|| !strncmp( rtfTextPtr, "{\\colortbl", 10 )
|| !strncmp( rtfTextPtr, "{\\NeXTHelp", 10 )
|| !strncmp( rtfTextPtr, "{{\\NeXTHelp", 11 ) ) {
int depth = 1;
while ( depth > 0 ) {
switch ( *++rtfTextPtr ) {
case '{': depth++; break;
case '}': depth--; break;
}
}
}
else
rtfTextPtr++;
break;
case '\\':
rtfTextPtr++;
if (*rtfTextPtr == '{'
|| *rtfTextPtr == '}'
|| *rtfTextPtr == '\\'
|| *rtfTextPtr == '\n' ) {
*asciiTextPtr++ = *rtfTextPtr++;
} else if ( *rtfTextPtr == '\'' ) {
int v1, v2, value;
rtfTextPtr++;
v1 = isdigit( *rtfTextPtr ) ? (*rtfTextPtr - '0')
: ((*rtfTextPtr - 'a') + 10);
rtfTextPtr++;
v2 = isdigit( *rtfTextPtr ) ? (*rtfTextPtr - '0')
: ((*rtfTextPtr - 'a') + 10);
value = (v1 << 4) | (v2);
*asciiTextPtr++ = value;
rtfTextPtr++;
} else {
while ( isalpha( *rtfTextPtr ) ) rtfTextPtr++;
if (*rtfTextPtr == '-') rtfTextPtr++;
while ( isdigit( *rtfTextPtr ) ) rtfTextPtr++;
if ( *rtfTextPtr == ' ' ) rtfTextPtr++;
else while (*rtfTextPtr == ' ') rtfTextPtr++;
}
break;
default:
*asciiTextPtr++ = *rtfTextPtr++;
}
}
*asciiTextPtr = ASCII_TERMINATOR;
*asciiTextLen = (int)asciiTextPtr - (int)asciiTextBuf;
return asciiTextBuf;
}
#endif
#ifdef NEXT_CPP_SERVER
struct negative_file {
char *name;
struct negative_file *next;
};
static struct negative_file *negative_hash_table[IMPORT_HASH_SIZE];
static void
add_to_negative_cache (fname)
char *fname;
{
struct negative_file *i;
int hashval;
hashval = import_hash (fname);
i = (struct negative_file *)xmalloc (sizeof (struct negative_file));
i->name = fname;
i->next = negative_hash_table[hashval];
negative_hash_table[hashval] = i;
}
static int
found_in_negative_cache (filename)
char *filename;
{
struct negative_file *i;
int hashval;
hashval = import_hash (filename);
i = negative_hash_table[hashval];
while (i) {
if (!strcmp (filename, i->name))
return 1;
i = i->next;
}
return 0;
}
#if 0
void get_input_file_names(in_fname, in_fname_count, in_fname_list)
char *in_fname;
int *in_fname_count;
struct file_name_list **in_fname_list;
{
char *in_fnamep = in_fname;
char c;
*in_fname_count = 1;
while (c = *in_fnamep++)
if (c == ' ') (*in_fname_count)++;
if (*in_fname_count > 1) {
int nelem = 0;
*in_fname_list = (struct file_name_list *) xmalloc (*in_fname_count *
sizeof (struct file_name_list));
in_fnamep = in_fname;
if ((*in_fname_list)[nelem++].fname = strtok(in_fnamep," "))
while ((*in_fname_list)[nelem++].fname = strtok(NULL," "));
} else {
*in_fname_list = 0;
}
}
#endif
static void
add_version_of_header(fileptr, start, length)
struct file_name_list *fileptr;
unsigned int start;
unsigned int length;
{
struct file_name_list *ptr;
ptr = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
bzero (ptr, sizeof (struct file_name_list));
ptr->fname = fileptr->fname;
ptr->versions = fileptr->versions;
fileptr->versions = ptr;
ptr->relative_position_of_file_start = start;
ptr->file_length = length;
}
static int
duplicate_version_of_header(op, fileptr, position_of_file_start,
file_length)
FILE_BUF *op;
struct file_name_list *fileptr;
U_CHAR *position_of_file_start;
unsigned int file_length;
{
int found_a_version = 0;
do {
if ((file_length == fileptr->file_length) &&
(!bcmp (position_of_file_start,
op->buf+fileptr->relative_position_of_file_start,
file_length))) {
found_a_version = 1;
}
fileptr = fileptr->versions;
} while (fileptr && !found_a_version);
return found_a_version;
}
static int
aggressive_skip_if_group (ip)
FILE_BUF *ip;
{
if (ip->bufp == ip->file->position_after_last_include) {
if (if_stack && if_stack->type == T_IF && if_stack->control_macro) {
if (ip->file->control_macro)
ip->bufp = ip->file->position_of_last_endif;
else
ip->bufp = ip->buf + ip->length;
enable_macros_from_header(ip->file);
return 1;
} else {
return 0;
}
} else if (!ip->file->position_after_last_include) {
ip->bufp = ip->buf + ip->length;
enable_macros_from_header(ip->file);
return 1;
} else {
return 0;
}
}
static void
dump_memory_statistics ()
{
struct file_name_list *new;
struct import_file *imp;
struct negative_file *neg;
int n_elements = 0, n_other = 0, size_bufs = 0, size_mlists = 0;
int n_expansion_strings = 0, n_string_count = 0, control_names = 0;
int bucket;
fprintf(stderr, "all_input_files (chain of struct file_name_list's):\n");
for (new = all_input_files; new; new = new->next) {
n_elements++;
n_string_count += (strlen(new->fname)+1);
size_bufs += new->length;
}
fprintf(stderr, "%10d bytes for %d elements (%d bytes each)\n",
n_elements * sizeof(struct file_name_list),
n_elements, sizeof(struct file_name_list));
fprintf(stderr, "%10d bytes for input file names\n", n_string_count);
fprintf(stderr, "%10d bytes for input buffers\n", size_bufs);
n_string_count = n_elements = size_bufs = 0;
fprintf(stderr, "all_output_files (chain of struct file_name_list's):\n");
for (new = all_output_files; new; new = new->next) {
n_elements++;
if (new->fname)
n_string_count += (strlen(new->fname)+1);
size_bufs += new->length;
}
fprintf(stderr, "%10d bytes for %d elements (%d bytes each)\n",
n_elements * sizeof(struct file_name_list),
n_elements, sizeof(struct file_name_list));
fprintf(stderr, "%10d bytes for output file names\n", n_string_count);
fprintf(stderr, "%10d bytes for output buffers\n", size_bufs);
n_string_count = n_elements = size_bufs = 0;
fprintf(stderr, "all_include_files (chain of struct file_name_list's):\n");
for (new = all_include_files; new; new = new->next) {
n_elements++;
n_string_count += (strlen(new->fname)+1);
if (new->control_macro)
control_names += (strlen(new->control_macro)+1);
size_bufs += new->length;
size_mlists += new->macro_count * sizeof ( HASHNODE * );
fprintf(stderr, "%s\n", new->fname);
}
fprintf(stderr, "%10d bytes for %d elements (%d bytes each)\n",
n_elements * sizeof(struct file_name_list),
n_elements, sizeof(struct file_name_list));
fprintf(stderr, "%10d bytes for file names\n", n_string_count);
fprintf(stderr, "%10d bytes for control macro names\n", control_names);
fprintf(stderr, "%10d bytes for input buffers\n", size_bufs);
fprintf(stderr, "%10d bytes for macro lists\n", size_mlists);
n_string_count = n_elements = 0;
fprintf(stderr, "include directories (chain of struct file_name_list's):\n");
for (new = include; new; new = new->next) {
n_elements++;
n_string_count += (strlen(new->fname)+1);
}
fprintf(stderr, "%10d bytes for %d elements (%d bytes each)\n",
n_elements * sizeof(struct file_name_list),
n_elements, sizeof(struct file_name_list));
fprintf(stderr, "%10d bytes for directory names\n", n_string_count);
n_elements = 0;
fprintf(stderr, "import_hash_table (struct import_file's):\n");
for (bucket = 0; bucket < IMPORT_HASH_SIZE; bucket++) {
imp = import_hash_table[bucket];
while (imp) {
n_elements++;
imp = imp->next;
}
}
fprintf(stderr, "%10d bytes for import hash table buckets (statically allocated)\n",
sizeof(import_hash_table));
fprintf(stderr, "%10d bytes for %d elements (%d bytes each)\n",
n_elements * sizeof(struct import_file),
n_elements, sizeof(struct import_file));
n_elements = 0;
n_string_count = 0;
fprintf(stderr, "negative_hash_table (struct negative_file's):\n");
for (bucket = 0; bucket < IMPORT_HASH_SIZE; bucket++) {
neg = negative_hash_table[bucket];
while (neg) {
n_elements++;
n_string_count += (strlen(neg->name)+1);
neg = neg->next;
}
}
fprintf(stderr, "%10d bytes for negative hash table buckets (statically allocated)\n",
sizeof(negative_hash_table));
fprintf(stderr, "%10d bytes for %d elements (%d bytes each)\n",
n_elements * sizeof(struct negative_file),
n_elements, sizeof(struct negative_file));
fprintf(stderr, "%10d bytes for file names\n", n_string_count);
fprintf(stderr, "hashtab for macro's (struct hashnode's/definition's):\n");
n_string_count = 0;
n_elements = 0;
n_other = 0;
for (bucket = 0; bucket < HASHSIZE; bucket++) {
register HASHNODE *hp;
for (hp = hashtab[bucket]; hp; hp= hp->next) {
if (hp->type == T_MACRO) {
n_elements++;
if (hp->value.defn->length) {
n_string_count++;
n_expansion_strings += hp->value.defn->length;
}
} else {
n_other++;
}
}
}
fprintf(stderr, "%10d bytes for macro hash table buckets (statically allocated)\n",
sizeof(hashtab));
fprintf(stderr, "%10d bytes for %d macro hashnode's (%d bytes each)\n",
n_elements * sizeof(struct hashnode),
n_elements, sizeof(struct hashnode));
fprintf(stderr, "%10d bytes for %d macro definitions's (%d bytes each)\n",
n_elements * sizeof(struct definition),
n_elements, sizeof(struct definition));
fprintf(stderr, "%10d bytes for %d macro expansion strings\n",
n_expansion_strings, n_string_count);
fprintf(stderr, "%10d bytes for %d other hashnode's (%d bytes each)\n",
n_other * sizeof(struct hashnode),
n_other, sizeof(struct hashnode));
return;
}
static void
enable_macros_from_header(entry)
struct file_name_list *entry;
{
int i;
if (entry->macro_list) {
for (i = 0; i < entry->macro_count; i++) {
entry->macro_list[i]->defined_within_module = 1;
}
}
}
static void
clear_import()
{
struct import_file *i;
int h;
for (h = 0; h < IMPORT_HASH_SIZE; h++) {
i = import_hash_table[h];
while (i) {
i->visited_within_module = 0;
i = i->next;
}
}
}
static void
really_delete_macro(hp)
HASHNODE * hp;
{
DEFINITION *d = hp->value.defn;
struct reflist *ap, *nextap;
for (ap = d->pattern; ap != NULL; ap = nextap) {
nextap = ap->next;
free (ap);
}
if ((d->nargs > 0) && d->args.argnames)
free (d->args.argnames);
free (d);
free (hp);
}
static void
clear_all_macros ()
{
int bucket;
register HASHNODE *hp, *hp_next;
for (bucket = 0; bucket < HASHSIZE; bucket++) {
for (hp = hashtab[bucket]; hp; hp= hp->next) {
if (hp->type == T_MACRO) {
hp->defined_within_module = 0;
if (hp->owner && hp->owner->macro_count) {
if (hp->owner->macro_index < hp->owner->macro_count) {
if (!hp->owner->macro_list) {
int nbytes = hp->owner->macro_count * sizeof ( HASHNODE * );
hp->owner->macro_list = (HASHNODE **) xmalloc ( nbytes );
bzero(hp->owner->macro_list, nbytes);
}
hp->owner->macro_list[hp->owner->macro_index++] = hp;
}
} else {
}
}
}
}
for (hp = free_undefined_macros; hp; hp = hp_next) {
hp_next = hp->next;
really_delete_macro (hp);
}
#if 0
for (hp = installed_builtins; hp; hp = hp_next) {
hp_next = hp->next;
really_delete_macro (hp);
}
#endif
}
time_t file_modtime(const char * filename) {
int hashval = import_hash (filename);
struct import_file *i = import_hash_table[hashval];
while (i) {
if (!strcmp (filename, i->name->fname)) {
return i->modtime;
}
i = i->next;
}
return 0;
}
static void handle_file_modification(const char * filename) {
struct file_name_list *ptr, *next_ptr, *prev_ptr, *version, *next_version;
int hashval = import_hash (filename);
int multiple_versions = 0, removed_from_hash = 0, removed_from_cache = 0;
struct import_file *prev = NULL;
struct import_file *i = import_hash_table[hashval];
while (i) {
if (!strcmp (filename, i->name->fname)) {
if (prev)
prev->next = i->next;
else
import_hash_table[hashval] = i->next;
removed_from_hash = 1;
}
prev = i;
i = i->next;
}
if (!removed_from_hash) {
const char * basefilename = strrchr(filename,'/');
if (basefilename) {
for (hashval = 0; hashval < IMPORT_HASH_SIZE; hashval++) {
prev = NULL;
i = import_hash_table[hashval];
while (i) {
const char * baseiname = strrchr(i->name->fname,'/');
if (!strcmp (basefilename, baseiname)) {
if (prev)
prev->next = i->next;
else
import_hash_table[hashval] = i->next;
fprintf(stderr,"...punted %s\n",i->name->fname);
}
prev = i;
i = i->next;
}
}
} else {
fprintf(stderr,"Cpp Internal Error: could not remove file '%s' from import hash table. Looks like a bad file name!!\n", filename);
}
}
prev_ptr = NULL;
for (ptr = next_ptr = all_include_files; ptr; ptr = next_ptr) {
next_ptr = ptr->next;
if (ptr->fname && !strcmp (ptr->fname, filename)) {
if (ptr->versions) {
multiple_versions = 1;
for (version = next_version = ptr->versions;
version;
version = next_version) {
next_version = version->next;
free(version);
}
}
if (prev_ptr)
prev_ptr->next = next_ptr;
else
all_include_files = next_ptr;
free(ptr->fname);
free(ptr);
removed_from_cache = 1;
}
prev_ptr = ptr;
}
#ifdef DEBUG
if (!removed_from_cache)
fprintf(stderr,"Warning: could not remove file '%s' from import cache.\n", filename);
#endif
if (multiple_versions)
fprintf(stderr,"Removed all versions of %s from header cache\n", filename);
else
fprintf(stderr,"Removed %s from header cache\n", filename);
fflush(stderr);
}
static void init_output_file_buf(FILE_BUF * outbuf)
{
outbuf->buf = (U_CHAR *) xmalloc (OUTBUF_SIZE);
outbuf->length = OUTBUF_SIZE;
outbuf->bufp = outbuf->output_written_to = outbuf->buf;
bzero (outbuf->bufp, outbuf->length);
outbuf->lineno = 0;
}
static int sysUsr_startTime;
static int sysUsr_finishTime;
static struct timeval real_startTime;
static struct timeval real_finishTime;
static int gettime ()
{
#if defined (NEXT_PDO) && defined (hpux)
struct tms tms;
times (&tms);
return tms.tms_utime / CLK_TCK;
#else
struct rusage rusage;
getrusage (0, &rusage);
return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec
+ rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec);
#endif
}
static void start()
{
sysUsr_startTime = gettime();
gettimeofday(&real_startTime, 0);
}
static void stop()
{
sysUsr_finishTime = gettime();
gettimeofday(&real_finishTime, 0);
}
static void display(FILE * strm, int addNewLine)
{
real_finishTime.tv_sec -= real_startTime.tv_sec;
real_finishTime.tv_usec -= real_startTime.tv_usec;
if (real_finishTime.tv_usec < 0)
real_finishTime.tv_sec--, real_finishTime.tv_usec += 1000000;
fprintf(strm, "%3d.%03d (sys+usr) %3d.%01d (real)%s",
(sysUsr_finishTime-sysUsr_startTime) / 1000000,
(sysUsr_finishTime-sysUsr_startTime) % 1000000,
real_finishTime.tv_sec,
real_finishTime.tv_usec/100000,
addNewLine ? "\n" : "");
}
#endif