From f1a86df6cbc181439d3c1b402275110c9debd76d Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Mon, 7 Dec 1998 13:35:20 +0000 Subject: [PATCH] cpplib.h (struct cpp_buffer): Replace dir and dlen members with a struct file_name_list pointer. 1998-11-26 01:17 -0500 Zack Weinberg * cpplib.h (struct cpp_buffer): Replace dir and dlen members with a struct file_name_list pointer. (struct cpp_reader): Add pointer to chain of `actual directory' include searchpath entries. (struct file_name_list): Add *alloc pointer for the sake of the actual-directory chain. Move definition of HOST_WIDE_INT here. (cpp_parse_escape): Change prototype to match changes in cppexp.c. * cppfiles.c (actual_directory): New function. (finclude): Use it to initialize the buffer's actual_dir entry. (find_include_file): We don't need to fix up max_include_len here. * cpplib.c (do_include): Don't allocate a file_name_list on the fly for current directory "" includes, use the one that's been preallocated in pfile->buffer->actual_dir. Hoist out duplicate code from the search_start selection logic. (cpp_reader_init): Initialize pfile->actual_dirs. Remove definition of HOST_WIDE_INT. Change calls to cpp_parse_escape to match changes in cppexp.c (note hardcoded MASK, which is safe since this is the source character set). * cppexp.c: Bring over changes to cpp_parse_escape from cccp.c to handle wide character constants in #if directives. The function now returns a HOST_WIDE_INT, and takes a third argument which is a binary mask for all legal values (0x00ff for 8-bit `char', 0xffff for 16-bit `wchar_t', etc.) Define MAX_CHAR_TYPE_MASK and MAX_WCHAR_TYPE_MASK. Change callers of cpp_parse_escape to match. [Fixes c-torture/execute/widechar-1.c] From-SVN: r24153 --- gcc/ChangeLog | 38 +++++++++++++++++++++ gcc/cppexp.c | 62 ++++++++++++++------------------- gcc/cppfiles.c | 89 ++++++++++++++++++++++++++++++----------------- gcc/cpplib.c | 93 ++++++++++++++++---------------------------------- gcc/cpplib.h | 33 ++++++++++++++++-- 5 files changed, 181 insertions(+), 134 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 84a79ba5cd8..f2f0aaf2bd6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +1998-11-26 01:17 -0500 Zack Weinberg + + * cpplib.h (struct cpp_buffer): Replace dir and dlen members + with a struct file_name_list pointer. + (struct cpp_reader): Add pointer to chain of `actual + directory' include searchpath entries. + (struct file_name_list): Add *alloc pointer for the sake of + the actual-directory chain. + + Move definition of HOST_WIDE_INT here. + (cpp_parse_escape): Change prototype to match changes in + cppexp.c. + + * cppfiles.c (actual_directory): New function. + (finclude): Use it to initialize the buffer's actual_dir + entry. + (find_include_file): We don't need to fix up max_include_len + here. + + * cpplib.c (do_include): Don't allocate a file_name_list on + the fly for current directory "" includes, use the one that's + been preallocated in pfile->buffer->actual_dir. Hoist out + duplicate code from the search_start selection logic. + (cpp_reader_init): Initialize pfile->actual_dirs. + + Remove definition of HOST_WIDE_INT. Change calls + to cpp_parse_escape to match changes in cppexp.c (note + hardcoded MASK, which is safe since this is the source + character set). + + * cppexp.c: Bring over changes to cpp_parse_escape from cccp.c + to handle wide character constants in #if directives. The + function now returns a HOST_WIDE_INT, and takes a third + argument which is a binary mask for all legal values (0x00ff + for 8-bit `char', 0xffff for 16-bit `wchar_t', etc.) Define + MAX_CHAR_TYPE_MASK and MAX_WCHAR_TYPE_MASK. Change callers of + cpp_parse_escape to match. [Fixes c-torture/execute/widechar-1.c] + Mon Dec 7 15:38:25 1998 Dave Brolley * gcc.c (default_compilers): Fix typo in USE_CPPLIB spec for cc1. diff --git a/gcc/cppexp.c b/gcc/cppexp.c index 419e5bd79dc..87b84a624fc 100644 --- a/gcc/cppexp.c +++ b/gcc/cppexp.c @@ -72,6 +72,14 @@ struct arglist { #define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE #endif +#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \ + ? (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE)) \ + : ~ (HOST_WIDE_INT) 0) + +#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \ + ? ~ (~ (HOST_WIDE_INT) 0 << MAX_WCHAR_TYPE_SIZE) \ + : ~ (HOST_WIDE_INT) 0) + /* Yield nonzero if adding two numbers with A's and B's signs can yield a number with SUM's sign, where A, B, and SUM are all C integers. */ #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0) @@ -101,28 +109,6 @@ static long right_shift PARAMS ((cpp_reader *, long, int, unsigned long)); #define SKIP_OPERAND 8 /*#define UNSIGNEDP 16*/ -/* Find the largest host integer type and set its size and type. - Watch out: on some crazy hosts `long' is shorter than `int'. */ - -#ifndef HOST_WIDE_INT -# if HAVE_INTTYPES_H -# include -# define HOST_WIDE_INT intmax_t -# else -# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \ - && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT) -# define HOST_WIDE_INT int -# else -# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \ - || ! (defined LONG_LONG_MAX || defined LLONG_MAX)) -# define HOST_WIDE_INT long -# else -# define HOST_WIDE_INT long long -# endif -# endif -# endif -#endif - #ifndef CHAR_BIT #define CHAR_BIT 8 #endif @@ -275,7 +261,7 @@ cpp_lex (pfile, skip_evaluation) cpp_reader *pfile; int skip_evaluation; { - register int c; + register HOST_WIDE_INT c; register struct token *toktab; enum cpp_token token; struct operation op; @@ -359,7 +345,9 @@ cpp_lex (pfile, skip_evaluation) { if (c == '\\') { - c = cpp_parse_escape (pfile, (char **) &ptr); + c = cpp_parse_escape (pfile, (char **) &ptr, + wide_flag ? MAX_WCHAR_TYPE_MASK + : MAX_CHAR_TYPE_MASK); if (width < HOST_BITS_PER_INT && (unsigned) c >= (unsigned)(1 << width)) cpp_pedwarn (pfile, @@ -480,10 +468,11 @@ cpp_lex (pfile, skip_evaluation) If \ is followed by 000, we return 0 and leave the string pointer after the zeros. A value of 0 does not mean end of string. */ -int -cpp_parse_escape (pfile, string_ptr) +HOST_WIDE_INT +cpp_parse_escape (pfile, string_ptr, result_mask) cpp_reader *pfile; char **string_ptr; + HOST_WIDE_INT result_mask; { register int c = *(*string_ptr)++; switch (c) @@ -494,7 +483,7 @@ cpp_parse_escape (pfile, string_ptr) return TARGET_BS; case 'e': case 'E': - if (CPP_PEDANTIC (pfile)) + if (CPP_OPTIONS (pfile)->pedantic) cpp_pedwarn (pfile, "non-ANSI-standard escape sequence, `\\%c'", c); return 033; case 'f': @@ -522,7 +511,7 @@ cpp_parse_escape (pfile, string_ptr) case '6': case '7': { - register int i = c - '0'; + register HOST_WIDE_INT i = c - '0'; register int count = 0; while (++count < 3) { @@ -535,17 +524,17 @@ cpp_parse_escape (pfile, string_ptr) break; } } - if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0) + if (i != (i & result_mask)) { - i &= (1 << MAX_CHAR_TYPE_SIZE) - 1; - cpp_pedwarn (pfile, - "octal character constant does not fit in a byte"); + i &= result_mask; + cpp_pedwarn (pfile, "octal escape sequence out of range"); } return i; } case 'x': { - register unsigned i = 0, overflow = 0, digits_found = 0, digit; + register unsigned HOST_WIDE_INT i = 0, overflow = 0; + register int digits_found = 0, digit; for (;;) { c = *(*string_ptr)++; @@ -566,11 +555,10 @@ cpp_parse_escape (pfile, string_ptr) } if (!digits_found) cpp_error (pfile, "\\x used with no following hex digits"); - if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1))) + if (overflow | (i != (i & result_mask))) { - i &= (1 << BITS_PER_UNIT) - 1; - cpp_pedwarn (pfile, - "hex character constant does not fit in a byte"); + i &= result_mask; + cpp_pedwarn (pfile, "hex escape sequence out of range"); } return i; } diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index 8a4a0efb41c..8c01cddc787 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -42,6 +42,7 @@ static char *remap_filename PROTO ((cpp_reader *, char *, struct file_name_list *)); static long safe_read PROTO ((int, char *, int)); static void simplify_pathname PROTO ((char *)); +static struct file_name_list *actual_directory PROTO ((cpp_reader *, char *)); #if 0 static void hack_vms_include_specification PROTO ((char *)); @@ -422,11 +423,6 @@ find_include_file (pfile, fname, search_start, ihash, before) /* Search directory path, trying to open the file. */ - /* The first entry in the search list may be a buffer-specific entry, - and its directory name may be longer than max_include_len. Adjust - as appropriate. */ - if (pfile->max_include_len < search_start->nlen) - pfile->max_include_len = search_start->nlen; len = strlen (fname); name = xmalloc (len + pfile->max_include_len + 2 + INCLUDE_LEN_FUDGE); @@ -690,34 +686,11 @@ finclude (pfile, fd, ihash) fp->colno = 1; fp->cleanup = file_cleanup; - /* The ->dir field is only used when ignore_srcdir is not in effect; + /* The ->actual_dir field is only used when ignore_srcdir is not in effect; see do_include */ if (!CPP_OPTIONS (pfile)->ignore_srcdir) - { - char *last_slash; - fp->dir = savestring (fp->fname); - last_slash = rindex (fp->dir, '/'); - if (last_slash) - { - if (last_slash == fp->dir) - { - fp->dlen = 1; - last_slash[1] = '\0'; - } - else - { - fp->dlen = last_slash - fp->dir; - *last_slash = '\0'; - } - } - else - { - fp->dir[0] = '.'; - fp->dir[1] = '\0'; - fp->dlen = 1; - } - } - + fp->actual_dir = actual_directory (pfile, fp->fname); + if (S_ISREG (st.st_mode)) { st_size = (size_t) st.st_size; @@ -790,6 +763,60 @@ finclude (pfile, fd, ihash) return 0; } +static struct file_name_list * +actual_directory (pfile, fname) + cpp_reader *pfile; + char *fname; +{ + char *last_slash, *dir; + size_t dlen; + struct file_name_list *x; + + dir = savestring (fname); + last_slash = rindex (dir, '/'); + if (last_slash) + { + if (last_slash == dir) + { + dlen = 1; + last_slash[1] = '\0'; + } + else + { + dlen = last_slash - dir; + *last_slash = '\0'; + } + } + else + { + dir[0] = '.'; + dir[1] = '\0'; + dlen = 1; + } + + if (dlen > pfile->max_include_len) + pfile->max_include_len = dlen; + + for (x = pfile->actual_dirs; x; x = x->alloc) + if (!strcmp (x->name, dir)) + { + free (dir); + return x; + } + + /* Not found, make a new one. */ + x = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); + x->name = dir; + x->nlen = dlen; + x->next = CPP_OPTIONS (pfile)->quote_include; + x->alloc = pfile->actual_dirs; + x->sysp = 0; + x->name_map = NULL; + + pfile->actual_dirs = x; + return x; +} + /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME, retrying if necessary. If MAX_READ_LEN is defined, read at most that bytes at a time. Return a negative value if an error occurs, diff --git a/gcc/cpplib.c b/gcc/cpplib.c index a9bb550bb55..dbdf2f45c08 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -50,27 +50,6 @@ extern char *update_path PARAMS ((char *, char *)); #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) -/* Find the largest host integer type and set its size and type. - Watch out: on some crazy hosts `long' is shorter than `int'. */ - -#ifndef HOST_WIDE_INT -# if HAVE_INTTYPES_H -# include -# define HOST_WIDE_INT intmax_t -# else -# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \ - && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT) -# define HOST_WIDE_INT int -# else -# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \ - || ! (defined LONG_LONG_MAX || defined LLONG_MAX)) -# define HOST_WIDE_INT long -# else -# define HOST_WIDE_INT long long -# endif -# endif -# endif -#endif /* By default, colon separates directories in a path. */ #ifndef PATH_SEPARATOR @@ -2932,7 +2911,7 @@ do_include (pfile, keyword, unused1, unused2) int before; /* included before? */ long flen; char *fbeg, *fend; - struct file_name_list *srcdir = 0; /* for "" includes */ + cpp_buffer *fp; enum cpp_token token; @@ -3015,48 +2994,39 @@ do_include (pfile, keyword, unused1, unused2) cpp_error (pfile, "empty file name in `#%s'", keyword->name); return 0; } + + search_start = 0; + + for (fp = CPP_BUFFER (pfile); + fp != CPP_NULL_BUFFER (pfile); + fp = CPP_PREV_BUFFER (fp)) + if (fp->fname != NULL) + break; + + if (fp == CPP_NULL_BUFFER (pfile)) + fp = NULL; /* For #include_next, skip in the search path past the dir in which the containing file was found. */ if (skip_dirs) { - cpp_buffer *fp = CPP_BUFFER (pfile); - for (; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp)) - if (fp->fname != NULL) - { - /* Don't skip anything if the containing file was found - by an absolute path. */ - if (fp->ihash->foundhere == ABSOLUTE_PATH) - search_start = angle_brackets - ? CPP_OPTIONS (pfile)->bracket_include - : CPP_OPTIONS (pfile)->quote_include; - else - search_start = fp->ihash->foundhere->next; - break; - } + if (fp) + search_start = fp->ihash->foundhere->next; } else - search_start = angle_brackets - ? CPP_OPTIONS (pfile)->bracket_include - : CPP_OPTIONS (pfile)->quote_include; - - /* For "" includes when ignore_srcdir is off, tack the actual directory - of the current file onto the beginning of the search path. - The block must be permanently allocated since it may wind up - in the include hash. */ - if (!angle_brackets - && search_start == CPP_OPTIONS (pfile)->quote_include - && !CPP_OPTIONS (pfile)->ignore_srcdir) { - srcdir = (struct file_name_list *) - xmalloc (sizeof (struct file_name_list)); - srcdir->next = CPP_OPTIONS (pfile)->quote_include; - srcdir->name = CPP_BUFFER (pfile)->dir; - srcdir->nlen = CPP_BUFFER (pfile)->dlen; - srcdir->sysp = 0; - srcdir->name_map = NULL; - - search_start = srcdir; + if (angle_brackets) + search_start = CPP_OPTIONS (pfile)->bracket_include; + else + { + if (!CPP_OPTIONS (pfile)->ignore_srcdir) + { + if (fp) + search_start = fp->actual_dir; + } + else + search_start = CPP_OPTIONS (pfile)->quote_include; + } } if (!search_start) @@ -3067,10 +3037,6 @@ do_include (pfile, keyword, unused1, unused2) fd = find_include_file (pfile, fbeg, search_start, &ihash, &before); - if (srcdir - && (ihash == (struct include_hash *)-1 || srcdir != ihash->foundhere)) - free (srcdir); - if (fd == -2) return 0; @@ -3128,8 +3094,8 @@ do_include (pfile, keyword, unused1, unused2) /* Handle -H option. */ if (CPP_OPTIONS(pfile)->print_include_names) { - cpp_buffer *buf = CPP_BUFFER (pfile); - while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile)) + fp = CPP_BUFFER (pfile); + while ((fp = CPP_PREV_BUFFER (fp)) != CPP_NULL_BUFFER (pfile)) putc ('.', stderr); fprintf (stderr, " %s\n", ihash->name); } @@ -3282,7 +3248,7 @@ convert_string (pfile, result, in, limit, handle_escapes) if (handle_escapes) { char *bpc = (char *) in; - int i = (U_CHAR) cpp_parse_escape (pfile, &bpc); + int i = (U_CHAR) cpp_parse_escape (pfile, &bpc, 0x00ffU); in = (U_CHAR *) bpc; if (i >= 0) *result++ = (U_CHAR)c; @@ -5380,6 +5346,7 @@ cpp_reader_init (pfile) pfile->timebuf = NULL; pfile->only_seen_white = 1; pfile->buffer = CPP_NULL_BUFFER(pfile); + pfile->actual_dirs = NULL; } static struct cpp_pending * diff --git a/gcc/cpplib.h b/gcc/cpplib.h index fe2810237dc..3cb275327de 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -110,8 +110,7 @@ struct cpp_buffer { /* Filename specified with #line command. */ char *nominal_fname; /* Actual directory of this file, used only for "" includes */ - char *dir; - size_t dlen; + struct file_name_list *actual_dir; /* Pointer into the include hash table. Used for include_next and to record control macros. @@ -182,6 +181,10 @@ struct cpp_reader { #define ALL_INCLUDE_HASHSIZE 71 struct include_hash *all_include_files[ALL_INCLUDE_HASHSIZE]; + /* Chain of `actual directory' file_name_list entries, + for "" inclusion. */ + struct file_name_list *actual_dirs; + /* Current maximum length of directory names in the search path for include files. (Altered as we get more of them.) */ unsigned int max_include_len; @@ -485,6 +488,8 @@ struct cpp_options { struct file_name_list { struct file_name_list *next; + struct file_name_list *alloc; /* for the cache of + current directory entries */ char *name; unsigned int nlen; /* We use these to tell if the directory mentioned here is a duplicate @@ -656,6 +661,28 @@ struct if_stack { }; typedef struct if_stack IF_STACK_FRAME; +/* Find the largest host integer type and set its size and type. + Watch out: on some crazy hosts `long' is shorter than `int'. */ + +#ifndef HOST_WIDE_INT +# if HAVE_INTTYPES_H +# include +# define HOST_WIDE_INT intmax_t +# else +# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \ + && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT) +# define HOST_WIDE_INT int +# else +# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \ + || ! (defined LONG_LONG_MAX || defined LLONG_MAX)) +# define HOST_WIDE_INT long +# else +# define HOST_WIDE_INT long long +# endif +# endif +# endif +#endif + extern void cpp_buf_line_and_col PARAMS((cpp_buffer *, long *, long *)); extern cpp_buffer* cpp_file_buffer PARAMS((cpp_reader *)); extern void cpp_define PARAMS ((cpp_reader*, unsigned char *)); @@ -678,7 +705,7 @@ extern void cpp_perror_with_name PROTO ((cpp_reader *, const char *)); extern void v_cpp_message PROTO ((cpp_reader *, int, const char *, va_list)); extern void cpp_grow_buffer PARAMS ((cpp_reader *, long)); -extern int cpp_parse_escape PARAMS ((cpp_reader *, char **)); +extern HOST_WIDE_INT cpp_parse_escape PARAMS ((cpp_reader *, char **, HOST_WIDE_INT)); extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *, unsigned char *, long)); extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *));