aboutsummaryrefslogtreecommitdiff
path: root/libcpp/files.cc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-09-12 11:34:06 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2024-09-12 11:34:06 +0200
commit44058b847145166715f15e49fa8854f30e852f24 (patch)
tree6a05f67450a55752b5494c725d0cc982d0d6cc72 /libcpp/files.cc
parenteba6d2aa71a9b59386e5a2453cbe924371626b0b (diff)
downloadgcc-44058b847145166715f15e49fa8854f30e852f24.zip
gcc-44058b847145166715f15e49fa8854f30e852f24.tar.gz
gcc-44058b847145166715f15e49fa8854f30e852f24.tar.bz2
libcpp: Add support for gnu::offset #embed/__has_embed parameter
The following patch adds on top of the just posted #embed patch a first extension, gnu::offset which allows to seek in the data file (for seekable files, otherwise read and throw away). I think this is useful e.g. when some binary data start with some well known header which shouldn't be included in the data etc. 2024-09-12 Jakub Jelinek <jakub@redhat.com> libcpp/ * internal.h (struct cpp_embed_params): Add offset member. * directives.cc (EMBED_PARAMS): Add gnu::offset entry. (enum embed_param_kind): Add NUM_EMBED_STD_PARAMS. (_cpp_parse_embed_params): Use NUM_EMBED_STD_PARAMS rather than NUM_EMBED_PARAMS when parsing standard parameters. Parse gnu::offset parameter. * files.cc (struct _cpp_file): Add offset member. (_cpp_stack_embed): Handle params->offset. gcc/ * doc/cpp.texi (Binary Resource Inclusion): Document gnu::offset #embed parameter. gcc/testsuite/ * c-c++-common/cpp/embed-15.c: New test. * c-c++-common/cpp/embed-16.c: New test. * gcc.dg/cpp/embed-5.c: New test.
Diffstat (limited to 'libcpp/files.cc')
-rw-r--r--libcpp/files.cc95
1 files changed, 82 insertions, 13 deletions
diff --git a/libcpp/files.cc b/libcpp/files.cc
index 52b1850..9d64bff 100644
--- a/libcpp/files.cc
+++ b/libcpp/files.cc
@@ -90,6 +90,9 @@ struct _cpp_file
/* Size for #embed, perhaps smaller than st.st_size. */
size_t limit;
+ /* Offset for #embed. */
+ off_t offset;
+
/* File descriptor. Invalid if -1, otherwise open. */
int fd;
@@ -1242,8 +1245,11 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
_cpp_file *orig_file = file;
if (file->buffer_valid
&& (!S_ISREG (file->st.st_mode)
- || (file->limit < file->st.st_size + (size_t) 0
- && file->limit < params->limit)))
+ || file->offset + (cpp_num_part) 0 > params->offset
+ || (file->limit < file->st.st_size - file->offset + (size_t) 0
+ && (params->offset - file->offset > (cpp_num_part) file->limit
+ || file->limit - (params->offset
+ - file->offset) < params->limit))))
{
bool found = false;
if (S_ISREG (file->st.st_mode))
@@ -1256,8 +1262,13 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
&& strcmp (file->path, file->next_file->path) == 0)
{
file = file->next_file;
- if (file->limit >= file->st.st_size + (size_t) 0
- || file->limit >= params->limit)
+ if (file->offset + (cpp_num_part) 0 <= params->offset
+ && (file->limit >= (file->st.st_size - file->offset
+ + (size_t) 0)
+ || (params->offset
+ - file->offset <= (cpp_num_part) file->limit
+ && file->limit - (params->offset
+ - file->offset) >= params->limit)))
{
found = true;
break;
@@ -1313,8 +1324,10 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
if (regular)
{
cpp_num_part limit;
- if (file->st.st_size + (cpp_num_part) 0 < params->limit)
- limit = file->st.st_size;
+ if (file->st.st_size + (cpp_num_part) 0 < params->offset)
+ limit = 0;
+ else if (file->st.st_size - params->offset < params->limit)
+ limit = file->st.st_size - params->offset;
else
limit = params->limit;
if (params->has_embed)
@@ -1325,6 +1338,14 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
"%s is too large", file->path);
goto fail;
}
+ if (lseek (file->fd, params->offset, SEEK_CUR)
+ != (off_t) params->offset)
+ {
+ cpp_errno_filename (pfile, CPP_DL_ERROR, file->path,
+ params->loc);
+ goto fail;
+ }
+ file->offset = params->offset;
file->limit = limit;
size = limit;
}
@@ -1337,6 +1358,38 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
buf = XNEWVEC (uchar, size ? size : 1);
total = 0;
+ if (!regular && params->offset)
+ {
+ uchar *buf2 = buf;
+ ssize_t size2 = size;
+ cpp_num_part total2 = params->offset;
+
+ if (params->offset > 8 * 1024 && size < 8 * 1024)
+ {
+ size2 = 32 * 1024;
+ buf2 = XNEWVEC (uchar, size2);
+ }
+ do
+ {
+ if ((cpp_num_part) size2 > total2)
+ size2 = total2;
+ count = read (file->fd, buf2, size2);
+ if (count < 0)
+ {
+ cpp_errno_filename (pfile, CPP_DL_ERROR, file->path,
+ params->loc);
+ if (buf2 != buf)
+ free (buf2);
+ free (buf);
+ goto fail;
+ }
+ total2 -= count;
+ }
+ while (total2);
+ if (buf2 != buf)
+ free (buf2);
+ }
+
while ((count = read (file->fd, buf + total, size - total)) > 0)
{
total += count;
@@ -1377,7 +1430,10 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
file->limit = total;
}
else if (!regular)
- file->limit = total;
+ {
+ file->offset = params->offset;
+ file->limit = total;
+ }
file->buffer_start = buf;
file->buffer = buf;
@@ -1386,9 +1442,22 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
file->fd = -1;
}
else if (params->has_embed)
- return file->limit && params->limit ? 1 : 2;
+ {
+ if (params->offset - file->offset > file->limit)
+ return 2;
+ size_t limit = file->limit - (params->offset - file->offset);
+ return limit && params->limit ? 1 : 2;
+ }
+ const uchar *buffer = file->buffer;
size_t limit = file->limit;
+ if (params->offset - file->offset > limit)
+ limit = 0;
+ else
+ {
+ buffer += params->offset - file->offset;
+ limit -= params->offset - file->offset;
+ }
if (params->limit < limit)
limit = params->limit;
@@ -1412,20 +1481,20 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
size_t len = 0;
for (size_t i = 0; i < limit; ++i)
{
- if (file->buffer[i] < 10)
+ if (buffer[i] < 10)
len += 2;
- else if (file->buffer[i] < 100)
+ else if (buffer[i] < 100)
len += 3;
#if UCHAR_MAX == 255
else
len += 4;
#else
- else if (file->buffer[i] < 1000)
+ else if (buffer[i] < 1000)
len += 4;
else
{
char buf[64];
- len += sprintf (buf, "%d", file->buffer[i]) + 1;
+ len += sprintf (buf, "%d", buffer[i]) + 1;
}
#endif
if (len > INTTYPE_MAXIMUM (ssize_t))
@@ -1479,7 +1548,7 @@ _cpp_stack_embed (cpp_reader *pfile, const char *fname, bool angle,
if (i == 0)
tok->flags |= PREV_WHITE;
tok->val.str.text = s;
- tok->val.str.len = sprintf ((char *) s, "%d", file->buffer[i]);
+ tok->val.str.len = sprintf ((char *) s, "%d", buffer[i]);
s += tok->val.str.len + 1;
if (tok == &pfile->directive_result)
tok = toks;