From e5931ca02b0c0718d185542f574d985aa00ae85e Mon Sep 17 00:00:00 2001 From: brolley Date: Mon, 10 May 1999 15:24:36 +0000 Subject: [PATCH] 1999-05-10 18:21 -0400 Zack Weinberg * cppfiles.c (initialize_input_buffer): New function. (finclude): Call it, if pfile->input_buffer is NULL. Accept any character device as an input file. (read_and_prescan): Use pfile->input_buffer and pfile->input_speccase. * cppinit.c (cpp_cleanup): Free pfile->input_buffer and pfile->input_speccase. * cpplib.h (cpp_reader): Add input_buffer, input_speccase, and input_buffer_len members. Use memcpy in CPP_PUTS_Q. * cppmain.c: Buffer output in the token_buffer; throttle number of calls to fwrite; check for errors from fwrite. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@26869 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cppfiles.c | 138 ++++++++++++++++++++++++++++++++++++++------------------- gcc/cppinit.c | 8 ++++ gcc/cpplib.h | 9 +++- gcc/cppmain.c | 28 ++++++++---- 4 files changed, 128 insertions(+), 55 deletions(-) diff --git a/gcc/cppfiles.c b/gcc/cppfiles.c index e2305c6ad6c..a63d7e5bd69 100644 --- a/gcc/cppfiles.c +++ b/gcc/cppfiles.c @@ -45,6 +45,9 @@ static long read_and_prescan PROTO ((cpp_reader *, cpp_buffer *, int, size_t)); static struct file_name_list *actual_directory PROTO ((cpp_reader *, char *)); +static void initialize_input_buffer PROTO ((cpp_reader *, int, + struct stat *)); + #if 0 static void hack_vms_include_specification PROTO ((char *)); #endif @@ -648,10 +651,12 @@ finclude (pfile, fd, ihash) } } else if (S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode) + /* Permit any kind of character device: the sensible ones are + ttys and /dev/null, but weeding out the others is too hard. */ + || S_ISCHR (st.st_mode) /* Some 4.x (x<4) derivatives have a bug that makes fstat() of a socket or pipe return a stat struct with most fields zeroed. */ - || (st.st_mode == 0 && st.st_nlink == 0 && st.st_size == 0) - || (S_ISCHR (st.st_mode) && isatty (fd))) + || (st.st_mode == 0 && st.st_nlink == 0 && st.st_size == 0)) { /* Cannot get its file size before reading. 4k is a decent first guess. */ @@ -663,6 +668,9 @@ finclude (pfile, fd, ihash) goto fail; } + if (pfile->input_buffer == NULL) + initialize_input_buffer (pfile, fd, &st); + /* Read the file, converting end-of-line characters and trigraphs (if enabled). */ fp->ihash = ihash; @@ -758,8 +766,7 @@ actual_directory (pfile, fname) return x; } -/* Almost but not quite the same as adjust_position in cpplib.c. - Used only by read_and_prescan. */ +/* Determine the current line and column. Used only by read_and_prescan. */ static void find_position (start, limit, linep, colp) U_CHAR *start; @@ -804,9 +811,14 @@ find_position (start, limit, linep, colp) If your file has more than one kind of end-of-line marker, you will get messed-up line numbering. */ -#ifndef PIPE_BUF -#define PIPE_BUF 4096 -#endif +/* Table of characters that can't be handled in the inner loop. + Keep these contiguous to optimize the performance of the code generated + for the switch that uses them. */ +#define SPECCASE_EMPTY 0 +#define SPECCASE_NUL 1 +#define SPECCASE_CR 2 +#define SPECCASE_BACKSLASH 3 +#define SPECCASE_QUESTION 4 static long read_and_prescan (pfile, fp, desc, len) @@ -818,45 +830,24 @@ read_and_prescan (pfile, fp, desc, len) U_CHAR *buf = (U_CHAR *) xmalloc (len); U_CHAR *ip, *op, *line_base; U_CHAR *ibase; + U_CHAR *speccase = pfile->input_speccase; unsigned long line; unsigned int deferred_newlines; int count; size_t offset; - /* PIPE_BUF bytes of buffer proper, 2 to detect running off the end - without address arithmetic all the time, and 2 for pushback in - the case there's a potential trigraph or end-of-line digraph at - the end of a block. */ - U_CHAR intermed[PIPE_BUF + 2 + 2]; - - /* Table of characters that can't be handled in the inner loop. - Keep these contiguous to optimize the performance of the code generated - for the switch that uses them. */ -#define SPECCASE_EMPTY 0 -#define SPECCASE_NUL 1 -#define SPECCASE_CR 2 -#define SPECCASE_BACKSLASH 3 -#define SPECCASE_QUESTION 4 - U_CHAR speccase[256]; offset = 0; op = buf; line_base = buf; line = 1; - ibase = intermed + 2; + ibase = pfile->input_buffer + 2; deferred_newlines = 0; - memset (speccase, SPECCASE_EMPTY, sizeof (speccase)); - speccase['\0'] = SPECCASE_NUL; - speccase['\r'] = SPECCASE_CR; - speccase['\\'] = SPECCASE_BACKSLASH; - if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs) - speccase['?'] = SPECCASE_QUESTION; - for (;;) { read_next: - count = read (desc, intermed + 2, PIPE_BUF); + count = read (desc, pfile->input_buffer + 2, pfile->input_buffer_len); if (count < 0) goto error; else if (count == 0) @@ -864,7 +855,7 @@ read_and_prescan (pfile, fp, desc, len) offset += count; ip = ibase; - ibase = intermed + 2; + ibase = pfile->input_buffer + 2; ibase[count] = ibase[count+1] = '\0'; if (offset > len) @@ -924,8 +915,7 @@ read_and_prescan (pfile, fp, desc, len) ip++; else if (*ip == '\0') { - --ibase; - intermed[1] = '\r'; + *--ibase = '\r'; goto read_next; } else if (ip[-2] == '\n') @@ -941,8 +931,7 @@ read_and_prescan (pfile, fp, desc, len) and come back next pass. */ if (*ip == '\0') { - --ibase; - intermed[1] = '\\'; + *--ibase = '\\'; goto read_next; } else if (*ip == '\n') @@ -965,9 +954,8 @@ read_and_prescan (pfile, fp, desc, len) if (*ip == '\n') ip++; else if (*ip == '\0') { - ibase -= 2; - intermed[0] = '\\'; - intermed[1] = '\r'; + *--ibase = '\r'; + *--ibase = '\\'; goto read_next; } else if (*ip == '\r' || *ip == '\t' || *ip == ' ') @@ -991,8 +979,7 @@ read_and_prescan (pfile, fp, desc, len) d = ip[0]; if (d == '\0') { - --ibase; - intermed[1] = '?'; + *--ibase = '?'; goto read_next; } if (d != '?') @@ -1003,8 +990,8 @@ read_and_prescan (pfile, fp, desc, len) d = ip[1]; if (d == '\0') { - ibase -= 2; - intermed[0] = intermed[1] = '?'; + *--ibase = '?'; + *--ibase = '?'; goto read_next; } if (!trigraph_table[d]) @@ -1047,7 +1034,7 @@ read_and_prescan (pfile, fp, desc, len) This may be any of: ?? ? \ \r \n \\r \\n. \r must become \n, \\r or \\n must become \r. We know we have space already. */ - if (ibase == intermed) + if (ibase == pfile->input_buffer) { if (*ibase == '?') { @@ -1057,7 +1044,7 @@ read_and_prescan (pfile, fp, desc, len) else *op++ = '\r'; } - else if (ibase == intermed + 1) + else if (ibase == pfile->input_buffer + 1) { if (*ibase == '\r') *op++ = '\n'; @@ -1095,6 +1082,67 @@ read_and_prescan (pfile, fp, desc, len) return -1; } +/* Initialize the `input_buffer' and `input_speccase' tables. + These are only used by read_and_prescan, but they're large and + somewhat expensive to set up, so we want them allocated once for + the duration of the cpp run. */ + +static void +initialize_input_buffer (pfile, fd, st) + cpp_reader *pfile; + int fd; + struct stat *st; +{ + long pipe_buf; + U_CHAR *tmp; + + /* Table of characters that cannot be handled by the + read_and_prescan inner loop. The number of non-EMPTY entries + should be as small as humanly possible. */ + + tmp = xmalloc (1 << CHAR_BIT); + memset (tmp, SPECCASE_EMPTY, 1 << CHAR_BIT); + tmp['\0'] = SPECCASE_NUL; + tmp['\r'] = SPECCASE_CR; + tmp['\\'] = SPECCASE_BACKSLASH; + if (CPP_OPTIONS (pfile)->trigraphs || CPP_OPTIONS (pfile)->warn_trigraphs) + tmp['?'] = SPECCASE_QUESTION; + + pfile->input_speccase = tmp; + + /* Determine the appropriate size for the input buffer. Normal C + source files are smaller than eight K. If we are reading a pipe, + we want to make sure the input buffer is bigger than the kernel's + pipe buffer. */ + pipe_buf = -1; + + if (! S_ISREG (st->st_mode)) + { +#ifdef _PC_PIPE_BUF + pipe_buf = fpathconf (fd, _PC_PIPE_BUF); +#endif + if (pipe_buf == -1) + { +#ifdef PIPE_BUF + pipe_buf = PIPE_BUF; +#else + pipe_buf = 8192; +#endif + } + } + + if (pipe_buf < 8192) + pipe_buf = 8192; + /* PIPE_BUF bytes of buffer proper, 2 to detect running off the end + without address arithmetic all the time, and 2 for pushback in + the case there's a potential trigraph or end-of-line digraph at + the end of a block. */ + + tmp = xmalloc (pipe_buf + 2 + 2); + pfile->input_buffer = tmp; + pfile->input_buffer_len = pipe_buf; +} + /* Add output to `deps_buffer' for the -M switch. STRING points to the text to be output. SPACER is ':' for targets, ' ' for dependencies, zero for text diff --git a/gcc/cppinit.c b/gcc/cppinit.c index 9b2ecca459a..f9bc306bd52 100644 --- a/gcc/cppinit.c +++ b/gcc/cppinit.c @@ -569,6 +569,14 @@ cpp_cleanup (pfile) pfile->deps_allocated_size = 0; } + if (pfile->input_buffer) + { + free (pfile->input_buffer); + free (pfile->input_speccase); + pfile->input_buffer = pfile->input_speccase = NULL; + pfile->input_buffer_len = 0; + } + while (pfile->if_stack) { IF_STACK_FRAME *temp = pfile->if_stack; diff --git a/gcc/cpplib.h b/gcc/cpplib.h index 45f025e9717..aadec44eb86 100644 --- a/gcc/cpplib.h +++ b/gcc/cpplib.h @@ -241,6 +241,13 @@ struct cpp_reader /* Number of bytes since the last newline. */ int deps_column; + + /* A buffer and a table, used only by read_and_prescan (in cppfiles.c) + which are allocated once per cpp_reader object to keep them off the + stack and avoid setup costs. */ + U_CHAR *input_buffer; + U_CHAR *input_speccase; + size_t input_buffer_len; }; #define CPP_FATAL_LIMIT 1000 @@ -269,7 +276,7 @@ struct cpp_reader /* Append string STR (of length N) to PFILE's output buffer. Assume there is enough space. */ #define CPP_PUTS_Q(PFILE, STR, N) \ - (bcopy (STR, (PFILE)->limit, (N)), (PFILE)->limit += (N)) + (memcpy ((PFILE)->limit, STR, (N)), (PFILE)->limit += (N)) /* Append string STR (of length N) to PFILE's output buffer. Make space. */ #define CPP_PUTS(PFILE, STR, N) CPP_RESERVE(PFILE, N), CPP_PUTS_Q(PFILE, STR,N) /* Append character CH to PFILE's output buffer. Assume sufficient space. */ diff --git a/gcc/cppmain.c b/gcc/cppmain.c index e7d82b5429b..0d891f80980 100644 --- a/gcc/cppmain.c +++ b/gcc/cppmain.c @@ -46,6 +46,7 @@ main (argc, argv) char *p; int argi = 1; /* Next argument to handle. */ struct cpp_options *opts = &options; + enum cpp_token kind; p = argv[0] + strlen (argv[0]); while (p != argv[0] && p[-1] != '/') --p; @@ -80,21 +81,30 @@ main (argc, argv) else if (! freopen (opts->out_fname, "w", stdout)) cpp_pfatal_with_name (&parse_in, opts->out_fname); - for (;;) + do { - enum cpp_token kind; - if (! opts->no_output) + kind = cpp_get_token (&parse_in); + if (CPP_WRITTEN (&parse_in) >= BUFSIZ || kind == CPP_EOF) { - fwrite (parse_in.token_buffer, 1, CPP_WRITTEN (&parse_in), stdout); + if (! opts->no_output) + { + size_t rem, count = CPP_WRITTEN (&parse_in); + + rem = fwrite (parse_in.token_buffer, 1, count, stdout); + if (rem < count) + /* Write error. */ + cpp_pfatal_with_name (&parse_in, opts->out_fname); + } + + CPP_SET_WRITTEN (&parse_in, 0); } - CPP_SET_WRITTEN (&parse_in, 0); - kind = cpp_get_token (&parse_in); - if (kind == CPP_EOF) - break; } + while (kind != CPP_EOF); cpp_finish (&parse_in); - fwrite (parse_in.token_buffer, 1, CPP_WRITTEN (&parse_in), stdout); + if (fwrite (parse_in.token_buffer, 1, CPP_WRITTEN (&parse_in), stdout) + < CPP_WRITTEN (&parse_in)) + cpp_pfatal_with_name (&parse_in, opts->out_fname); if (parse_in.errors) exit (FATAL_EXIT_CODE); -- 2.11.0