aboutsummaryrefslogtreecommitdiff
path: root/gcc
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 /gcc
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 'gcc')
-rw-r--r--gcc/doc/cpp.texi8
-rw-r--r--gcc/testsuite/c-c++-common/cpp/embed-15.c88
-rw-r--r--gcc/testsuite/c-c++-common/cpp/embed-16.c31
-rw-r--r--gcc/testsuite/gcc.dg/cpp/embed-5.c4
4 files changed, 129 insertions, 2 deletions
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 032b095..612d97e 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -3966,8 +3966,8 @@ treated the same), followed by parameter argument in parentheses, like
with currently supported standard parameters @code{limit}, @code{prefix},
@code{suffix} and @code{if_empty}, or implementation defined parameters
specified by a unique vendor prefix followed by @code{::} followed by
-name of the parameter. GCC will use the @code{gnu} prefix but currently
-doesn't support any extensions.
+name of the parameter. GCC uses the @code{gnu} prefix for vendor
+parameters and currently supports the @code{gnu::offset} parameter.
The @code{limit} parameter argument is a constant expression which
specifies the maximum number of bytes included by the directive,
@@ -3977,6 +3977,10 @@ that sequence is not empty and @code{if_empty} argument is balanced token
sequence which is used as expansion for @code{#embed} directive if the
resource is empty.
+The @code{gnu::offset} parameter argument is a constant expression
+which specifies how many bytes to skip from the start of the resource.
+@code{limit} is then counted from that position.
+
The @code{#embed} directive is not supported in the Traditional Mode
(@pxref{Traditional Mode}).
diff --git a/gcc/testsuite/c-c++-common/cpp/embed-15.c b/gcc/testsuite/c-c++-common/cpp/embed-15.c
new file mode 100644
index 0000000..c12aeb3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/embed-15.c
@@ -0,0 +1,88 @@
+/* { dg-do run } */
+/* { dg-options "--embed-dir=${srcdir}/c-c++-common/cpp/embed-dir" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+
+#if __has_embed (__FILE__ gnu::offset (4 + FOOBAR) limit (3)) != __STDC_EMBED_FOUND__
+#error "__has_embed fail"
+#endif
+
+#embed <magna-carta.txt> limit(1) gnu::offset (0) prefix(int a = ) suffix (;)
+#embed <magna-carta.txt> limit(1) __gnu__::offset (1 * 1) prefix(int b = ) suffix (;)
+#embed <magna-carta.txt> limit(1) gnu::__offset__ (1 + 1) prefix(int c = ) suffix (;)
+#embed <magna-carta.txt> __limit__(1) __gnu__::__offset__ (1 + (1 \
+ + 1)) __prefix__(int d = ) __suffix__ (;)
+const unsigned char e[] = {
+ #embed <magna-carta.txt> limit(5) gnu::offset (999)
+};
+const unsigned char f[] = {
+ #embed <magna-carta.txt> limit(7) gnu::offset (998)
+};
+const unsigned char g[] = {
+ #embed <magna-carta.txt> limit(8) gnu::offset (998)
+};
+const unsigned char h[] = {
+ #embed <magna-carta.txt> limit(8) gnu::offset (997)
+};
+const unsigned char i[] = {
+ #embed <magna-carta.txt> limit(9) gnu::offset (997)
+};
+const unsigned char j[] = {
+ #embed <magna-carta.txt> limit(30) gnu::offset (990)
+};
+const unsigned char k[] = {
+ #embed <magna-carta.txt> limit(26) gnu::offset (992)
+};
+const unsigned char l[] = {
+ #embed <magna-carta.txt>
+};
+const unsigned char m[] = {
+ #embed <magna-carta.txt> __limit__ (1000) __gnu__::__offset__ (32)
+};
+#if __has_embed (<magna-carta.txt> limit(5) gnu::offset (999)) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt> limit(5) gnu::offset (999)) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt> limit(7) gnu::offset (998)) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt> limit(8) gnu::offset (998)) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt> limit(8) gnu::offset (997)) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt> limit(9) gnu::offset (997)) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt> limit(30) gnu::offset (990)) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt> limit(26) gnu::offset (992)) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt>) != __STDC_EMBED_FOUND__ \
+ || __has_embed (<magna-carta.txt> limit(26) gnu::offset (992)) != __STDC_EMBED_FOUND__
+#error "__has_embed fail"
+#endif
+
+#ifdef __cplusplus
+#define C "C"
+#else
+#define C
+#endif
+extern C void abort (void);
+extern C int memcmp (const void *, const void *, __SIZE_TYPE__);
+
+int
+main ()
+{
+ if (a != 'H' || b != 'e' || c != 'n' || d != 'r')
+ abort ();
+ if (sizeof (e) != 5
+ || sizeof (f) != 7
+ || sizeof (g) != 8
+ || sizeof (h) != 8
+ || sizeof (i) != 9
+ || sizeof (j) != 30
+ || sizeof (k) != 26
+ || sizeof (l) < 1032
+ || sizeof (m) != 1000)
+ abort ();
+ if (memcmp (e, l + 999, 5)
+ || memcmp (f, l + 998, 7)
+ || memcmp (g, l + 998, 8)
+ || memcmp (h, l + 997, 8)
+ || memcmp (i, l + 997, 9)
+ || memcmp (j, l + 990, 30)
+ || memcmp (k, l + 992, 26)
+ || memcmp (m, l + 32, 1000))
+ abort ();
+ if (l[0] != 'H' || l[1] != 'e' || l[2] != 'n' || l[3] != 'r')
+ abort ();
+}
diff --git a/gcc/testsuite/c-c++-common/cpp/embed-16.c b/gcc/testsuite/c-c++-common/cpp/embed-16.c
new file mode 100644
index 0000000..a3d1a6d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/embed-16.c
@@ -0,0 +1,31 @@
+/* { dg-do preprocess } */
+/* { dg-options "" } */
+
+#embed __FILE__ gnu::offset(1) gnu::offset(1) /* { dg-error "duplicate embed parameter 'gnu::offset'" } */
+#embed __FILE__ gnu::offset prefix() suffix() /* { dg-error "expected '\\\('" } */
+#embed __FILE__ gnu::offset (1 / 0) /* { dg-error "division by zero in #embed" } */
+#embed __FILE__ __gnu__::__offset__ (+ + +) /* { dg-error "operator '\\\+' has no right operand" } */
+#define FOO 1
+#embed __FILE__ gnu::offset(0 + defined(FOO)) /* { dg-error "'defined' in #embed parameter" } */
+#embed __FILE__ gnu::offset (-1) /* { dg-error "negative embed parameter operand" } */
+#embed __FILE__ gnu::offset (-42) /* { dg-error "negative embed parameter operand" } */
+#embed __FILE__ gnu::offset (-9223372036854775807 - 1) /* { dg-error "negative embed parameter operand" } */
+#embed __FILE__ gnu::offset (18446744073709551615ULL) /* { dg-error "too large 'gnu::offset' argument" } */
+#if 1 + __has_embed (__FILE__ gnu::offset(1) __gnu__::__offset__(1)) /* { dg-error "duplicate embed parameter 'gnu::offset'" } */
+#endif
+#if 1 + __has_embed (__FILE__ __gnu__::__offset__ prefix() suffix()) /* { dg-error "expected '\\\('" } */
+#endif
+#if 1 + __has_embed (__FILE__ gnu::offset(1/0)) /* { dg-error "division by zero in #embed" } */
+#endif
+#if 1 + __has_embed (__FILE__ gnu::offset(+ + +)) /* { dg-error "operator '\\\+' has no right operand" } */
+#endif
+#if 1 + __has_embed (__FILE__ gnu::offset(0 + defined(FOO))) /* { dg-error "'defined' in #embed parameter" } */
+#endif
+#if 1 + __has_embed (__FILE__ gnu::offset (-1)) /* { dg-error "negative embed parameter operand" } */
+#endif
+#if 1 + __has_embed (__FILE__ gnu::offset (-42)) /* { dg-error "negative embed parameter operand" } */
+#endif
+#if 1 + __has_embed (__FILE__ gnu::offset (-9223372036854775807 - 1)) /* { dg-error "negative embed parameter operand" } */
+#endif
+#if 1 + __has_embed (__FILE__ gnu::offset (18446744073709551615ULL)) /* { dg-error "too large 'gnu::offset' argument" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/embed-5.c b/gcc/testsuite/gcc.dg/cpp/embed-5.c
new file mode 100644
index 0000000..6420914
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/embed-5.c
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+/* { dg-options "-std=c23 -pedantic-errors --embed-dir=${srcdir}/c-c++-common/cpp/embed-dir" } */
+
+#include "../../c-c++-common/cpp/embed-15.c"