struct file_name_list *));
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 struct file_name_list *actual_directory PROTO ((cpp_reader *,
+ const char *));
+static void initialize_input_buffer PROTO ((cpp_reader *, int,
+ struct stat *));
+static int file_cleanup PROTO ((cpp_buffer *, cpp_reader *));
+static void find_position PROTO ((U_CHAR *, U_CHAR *,
+ unsigned long *,
+ unsigned long *));
#if 0
static void hack_vms_include_specification PROTO ((char *));
Note that this algorithm is quadratic in the number of -I switches,
which is acceptable since there aren't usually that many of them. */
- for (cur = quote; cur; cur = cur->next)
+ for (cur = quote, prev = NULL; cur; cur = cur->next)
{
for (other = quote; other != cur; other = other->next)
if (INO_T_EQ (cur->ino, other->ino)
struct include_hash *
include_hash (pfile, fname, add)
cpp_reader *pfile;
- char *fname;
+ const char *fname;
int add;
{
unsigned int hash = 0;
struct include_hash *l, *m;
- char *f = fname;
+ const char *f = fname;
while (*f)
hash += *f++;
int
find_include_file (pfile, fname, search_start, ihash, before)
cpp_reader *pfile;
- char *fname;
+ const char *fname;
struct file_name_list *search_start;
struct include_hash **ihash;
int *before;
len = 20;
set = alloc = xmalloc (len + 1);
- if (! is_space[ch])
+ if (! is_space(ch))
{
*set++ = ch;
- while ((ch = getc (f)) != EOF && ! is_space[ch])
+ while ((ch = getc (f)) != EOF && ! is_space(ch))
{
if (set - alloc == len)
{
char *from, *to;
struct file_name_map *ptr;
- if (is_space[ch])
+ if (is_space(ch))
continue;
from = read_filename_string (ch, f);
- while ((ch = getc (f)) != EOF && is_hor_space[ch])
+ while ((ch = getc (f)) != EOF && is_hspace(ch))
;
to = read_filename_string (ch, f);
}
}
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. */
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;
fp->system_header_p = ihash->foundhere->sysp;
fp->lineno = 1;
fp->colno = 1;
+ fp->line_base = fp->buf;
fp->cleanup = file_cleanup;
/* The ->actual_dir field is only used when ignore_srcdir is not in effect;
static struct file_name_list *
actual_directory (pfile, fname)
cpp_reader *pfile;
- char *fname;
+ const char *fname;
{
char *last_slash, *dir;
size_t dlen;
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;
U_CHAR *limit;
- long *linep;
- long *colp;
+ unsigned long *linep;
+ unsigned long *colp;
{
- long line = *linep, col = 0;
+ unsigned long line = *linep, col = 0;
while (start < limit)
{
U_CHAR ch = *start++;
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)
U_CHAR *buf = (U_CHAR *) xmalloc (len);
U_CHAR *ip, *op, *line_base;
U_CHAR *ibase;
- unsigned int line, deferred_newlines;
+ 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)
offset += count;
ip = ibase;
- ibase = intermed + 2;
+ ibase = pfile->input_buffer + 2;
ibase[count] = ibase[count+1] = '\0';
if (offset > len)
ip++;
else if (*ip == '\0')
{
- --ibase;
- intermed[1] = '\r';
+ *--ibase = '\r';
goto read_next;
}
else if (ip[-2] == '\n')
and come back next pass. */
if (*ip == '\0')
{
- --ibase;
- intermed[1] = '\\';
+ *--ibase = '\\';
goto read_next;
}
else if (*ip == '\n')
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 == ' ')
case SPECCASE_QUESTION: /* ? */
{
- unsigned int d;
+ unsigned int d, t;
/* If we're at the end of the intermediate buffer,
we have to shift the ?'s down to the start and
come back next pass. */
d = ip[0];
if (d == '\0')
{
- --ibase;
- intermed[1] = '?';
+ *--ibase = '?';
goto read_next;
}
if (d != '?')
d = ip[1];
if (d == '\0')
{
- ibase -= 2;
- intermed[0] = intermed[1] = '?';
+ *--ibase = '?';
+ *--ibase = '?';
goto read_next;
}
- if (!trigraph_table[d])
+
+ /* Trigraph map:
+ * from to from to from to
+ * ?? = # ?? ) ] ?? ! |
+ * ?? ( [ ?? ' ^ ?? > }
+ * ?? / \ ?? < { ?? - ~
+ */
+ if (d == '=') t = '#';
+ else if (d == ')') t = ']';
+ else if (d == '!') t = '|';
+ else if (d == '(') t = '[';
+ else if (d == '\'') t = '^';
+ else if (d == '>') t = '}';
+ else if (d == '/') t = '\\';
+ else if (d == '<') t = '{';
+ else if (d == '-') t = '~';
+ else
{
*op++ = '?';
break;
}
-
if (CPP_OPTIONS (pfile)->warn_trigraphs)
{
- long col;
+ unsigned long col;
find_position (line_base, op, &line, &col);
line_base = op - col;
cpp_warning_with_line (pfile, line, col,
}
if (CPP_OPTIONS (pfile)->trigraphs)
{
- if (trigraph_table[d] == '\\')
+ if (t == '\\')
goto backslash;
else
- *op++ = trigraph_table[d];
+ *op++ = t;
}
else
{
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 == '?')
{
else
*op++ = '\r';
}
- else if (ibase == intermed + 1)
+ else if (ibase == pfile->input_buffer + 1)
{
if (*ibase == '\r')
*op++ = '\n';
if (op[-1] != '\n')
{
- long col;
+ unsigned long col;
find_position (line_base, op, &line, &col);
cpp_warning_with_line (pfile, line, col, "no newline at end of file\n");
if (offset + 1 > 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 = (U_CHAR *) 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 = (U_CHAR *) 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
void
deps_output (pfile, string, spacer)
cpp_reader *pfile;
- char *string;
+ const char *string;
int spacer;
{
int size;
char *base;
int absolute = 0;
-#if defined _WIN32 || defined __MSDOS__
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
/* Convert all backslashes to slashes. */
for (from = path; *from; from++)
if (*from == '\\') *from = '/';