poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[COMMITTED] libpoke: support for 'eoffset, 'esize and 'ename attributes


From: Jose E. Marchesi
Subject: [COMMITTED] libpoke: support for 'eoffset, 'esize and 'ename attributes
Date: Mon, 14 Feb 2022 00:57:14 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

This patch introduces support for three new value attributes:

  VAL'eoffset (IDX)
  VAL'esize (IDX)
  VAL'ename (IDX)

where VAL is a composite value and IDX is an index of either an array
or struct element (field.)

'eoffset evaluates to an offset value with the offset of the element
at IDX.

'esize evaluates to an offset value with the size of the element at
IDX.

'ename evaluates to a string with the name of the element at IDX.  For
struct fields, this is the field name (empty string for anonymous
fields).  For array elements, a string ".[IDX]" is composed as the
name, by convention.

The new attributes can be used along with the already existing 'length
in order to do some introspection on composite values.  For example:

  (poke) load elf
  (poke) var ehdr = Elf64_Ehdr {}
  (poke) for (var i = 0; i < ehdr'length; ++i) printf "%v %v %v\n", \
         ehdr'eoffset (i), ehdr'esize (i), ehdr'ename (i)
  0x0000000000000000UL#b 0x0000000000000080UL#b "e_ident"
  0x0000000000000080UL#b 0x0000000000000010UL#b "e_type"
  0x0000000000000090UL#b 0x0000000000000010UL#b "e_machine"
  0x00000000000000a0UL#b 0x0000000000000020UL#b "e_version"
  0x00000000000000c0UL#b 0x0000000000000040UL#b "e_entry"
  0x0000000000000100UL#b 0x0000000000000040UL#b "e_phoff"
  0x0000000000000140UL#b 0x0000000000000040UL#b "e_shoff"
  0x0000000000000180UL#b 0x0000000000000020UL#b "e_flags"
  0x00000000000001a0UL#b 0x0000000000000010UL#b "e_ehsize"
  0x00000000000001b0UL#b 0x0000000000000010UL#b "e_phentsize"
  0x00000000000001c0UL#b 0x0000000000000010UL#b "e_phnum"
  0x00000000000001d0UL#b 0x0000000000000010UL#b "e_shentsize"
  0x00000000000001e0UL#b 0x0000000000000010UL#b "e_shnum"
  0x00000000000001f0UL#b 0x0000000000000010UL#b "e_shstrndx"

If IDX doesn't refer to an element in the composite VAL then the
exception E_out_of_bounds is raised.

The new attributes are obviously intended to be applied to composite
values such as arrays and structs.  However, they can be applied to
any kind of value (including values of type `any') raising a run-time
error whenever necessary:

  (poke) 1'eoffset (0)
  unhandled invalid argument exception

This makes it possible to write poke code (such as commands) that get
`any' value as argument.

2022-02-14  Jose E. Marchesi  <jemarch@gnu.org>

        * libpoke/pkl-attrs.def: New attributes EOFFSET, ESIZE and ENAME.
        * libpoke/pkl-ast.c (pkl_ast_make_binary_exp): New function.
        * libpoke/pkl-tab.y: Rule for attributes with one argument.
        * libpoke/pkl-ast.h (struct pkl_ast_exp): Allow three operands.
        * libpoke/pkl-pass.c (pkl_do_pass_1): Traverse all expression
        operands.
        * libpoke/pkl-trans.c (pkl_trans1_ps_op_attr): Handle binary
        attributes.
        * libpoke/pkl-anal.c (pkl_anal1_ps_op_attr): New handler.
        (pkl_phase_anal1): Register handler.
        * libpoke/pkl-typify.c (pkl_typify1_ps_attr): Handle new
        attributes.
        * libpoke/pkl-promo.c (pkl_promo_ps_op_attr): New handler.
        (pkl_phase_promo): Register handler.
        * libpoke/pkl-gen.c (pkl_gen_ps_op_attr): Handle EOFFSET, ESIZE
        and ENAME.
        * libpoke/pvm.jitter (tyisa): New instruction.
        (srefin): Likewise.
        * libpoke/pkl-insn.def: Define PKL_INSN_TYISA.
        Define PKL_INSN_SREFIN.
        * libpoke/pkl-gen-attrs.pks (attr_eoffset): New macro.
        (attr_eoffset): Likewise.
        (attr_ename): Likewise.
        * testsuite/poke.pkl/attr-diag-2.pk: New test.
        * testsuite/poke.pkl/attr-diag-3.pk: Likewise.
        * testsuite/poke.pkl/attr-diag-4.pk: Likewise.
        * testsuite/poke.pkl/attr-eoffset-5.pk: Likewise.
        * testsuite/poke.pkl/attr-eoffset-4.pk: Likewise.
        * testsuite/poke.pkl/attr-eoffset-3.pk: Likewise.
        * testsuite/poke.pkl/attr-eoffset-2.pk: Likewise.
        * testsuite/poke.pkl/attr-eoffset-1.pk: Likewise.
        * testsuite/poke.pkl/attr-esize-5.pk: Likewise.
        * testsuite/poke.pkl/attr-esize-4.pk: Likewise.
        * testsuite/poke.pkl/attr-esize-3.pk: Likewise.
        * testsuite/poke.pkl/attr-esize-2.pk: Likewise.
        * testsuite/poke.pkl/attr-esize-1.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-arr-6.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-arr-5.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-arr-4.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-arr-3.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-arr-2.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-arr-1.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-union-1.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-struct-1.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-struct-2.pk: Likewise.
        * testsuite/poke.pkl/attr-ename-union-2.pk: Likewise.
        * doc/poke.texi (Array Attributes): Document new attributes for
        arrays.
        (Struct Attributes): Ditto for structs.
        * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
---
 ChangeLog                                 |  53 ++++++++++++
 doc/poke.texi                             |  65 ++++++++++++++
 libpoke/pkl-anal.c                        |  37 ++++++++
 libpoke/pkl-ast.c                         |  26 ++++++
 libpoke/pkl-ast.h                         |   8 +-
 libpoke/pkl-attrs.def                     |   6 ++
 libpoke/pkl-gen-attrs.pks                 | 137 ++++++++++++++++++++++++++++--
 libpoke/pkl-gen.c                         |  10 +++
 libpoke/pkl-insn.def                      |   2 +
 libpoke/pkl-pass.c                        |  11 +--
 libpoke/pkl-promo.c                       |  36 ++++++++
 libpoke/pkl-tab.y                         |   9 +-
 libpoke/pkl-trans.c                       |  19 ++++-
 libpoke/pkl-typify.c                      |  53 +++++++++++-
 libpoke/pvm.jitter                        |  39 +++++++++
 testsuite/Makefile.am                     |  23 +++++
 testsuite/poke.pkl/attr-diag-2.pk         |   5 ++
 testsuite/poke.pkl/attr-diag-3.pk         |   4 +
 testsuite/poke.pkl/attr-diag-4.pk         |   6 ++
 testsuite/poke.pkl/attr-ename-arr-1.pk    |   4 +
 testsuite/poke.pkl/attr-ename-arr-2.pk    |   4 +
 testsuite/poke.pkl/attr-ename-arr-3.pk    |   4 +
 testsuite/poke.pkl/attr-ename-arr-4.pk    |   4 +
 testsuite/poke.pkl/attr-ename-arr-5.pk    |   4 +
 testsuite/poke.pkl/attr-ename-arr-6.pk    |   4 +
 testsuite/poke.pkl/attr-ename-struct-1.pk |   6 ++
 testsuite/poke.pkl/attr-ename-struct-2.pk |   6 ++
 testsuite/poke.pkl/attr-ename-union-1.pk  |   7 ++
 testsuite/poke.pkl/attr-ename-union-2.pk  |   7 ++
 testsuite/poke.pkl/attr-eoffset-1.pk      |   4 +
 testsuite/poke.pkl/attr-eoffset-2.pk      |   4 +
 testsuite/poke.pkl/attr-eoffset-3.pk      |   4 +
 testsuite/poke.pkl/attr-eoffset-4.pk      |   4 +
 testsuite/poke.pkl/attr-eoffset-5.pk      |   4 +
 testsuite/poke.pkl/attr-esize-1.pk        |   4 +
 testsuite/poke.pkl/attr-esize-2.pk        |   4 +
 testsuite/poke.pkl/attr-esize-3.pk        |   4 +
 testsuite/poke.pkl/attr-esize-4.pk        |   4 +
 testsuite/poke.pkl/attr-esize-5.pk        |   4 +
 39 files changed, 621 insertions(+), 18 deletions(-)
 create mode 100644 testsuite/poke.pkl/attr-diag-2.pk
 create mode 100644 testsuite/poke.pkl/attr-diag-3.pk
 create mode 100644 testsuite/poke.pkl/attr-diag-4.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-arr-1.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-arr-2.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-arr-3.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-arr-4.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-arr-5.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-arr-6.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-struct-1.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-struct-2.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-union-1.pk
 create mode 100644 testsuite/poke.pkl/attr-ename-union-2.pk
 create mode 100644 testsuite/poke.pkl/attr-eoffset-1.pk
 create mode 100644 testsuite/poke.pkl/attr-eoffset-2.pk
 create mode 100644 testsuite/poke.pkl/attr-eoffset-3.pk
 create mode 100644 testsuite/poke.pkl/attr-eoffset-4.pk
 create mode 100644 testsuite/poke.pkl/attr-eoffset-5.pk
 create mode 100644 testsuite/poke.pkl/attr-esize-1.pk
 create mode 100644 testsuite/poke.pkl/attr-esize-2.pk
 create mode 100644 testsuite/poke.pkl/attr-esize-3.pk
 create mode 100644 testsuite/poke.pkl/attr-esize-4.pk
 create mode 100644 testsuite/poke.pkl/attr-esize-5.pk

diff --git a/ChangeLog b/ChangeLog
index 4efb7c67..38768635 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+2022-02-14  Jose E. Marchesi  <jemarch@gnu.org>
+
+       * libpoke/pkl-attrs.def: New attributes EOFFSET, ESIZE and ENAME.
+       * libpoke/pkl-ast.c (pkl_ast_make_binary_exp): New function.
+       * libpoke/pkl-tab.y: Rule for attributes with one argument.
+       * libpoke/pkl-ast.h (struct pkl_ast_exp): Allow three operands.
+       * libpoke/pkl-pass.c (pkl_do_pass_1): Traverse all expression
+       operands.
+       * libpoke/pkl-trans.c (pkl_trans1_ps_op_attr): Handle binary
+       attributes.
+       * libpoke/pkl-anal.c (pkl_anal1_ps_op_attr): New handler.
+       (pkl_phase_anal1): Register handler.
+       * libpoke/pkl-typify.c (pkl_typify1_ps_attr): Handle new
+       attributes.
+       * libpoke/pkl-promo.c (pkl_promo_ps_op_attr): New handler.
+       (pkl_phase_promo): Register handler.
+       * libpoke/pkl-gen.c (pkl_gen_ps_op_attr): Handle EOFFSET, ESIZE
+       and ENAME.
+       * libpoke/pvm.jitter (tyisa): New instruction.
+       (srefin): Likewise.
+       * libpoke/pkl-insn.def: Define PKL_INSN_TYISA.
+       Define PKL_INSN_SREFIN.
+       * libpoke/pkl-gen-attrs.pks (attr_eoffset): New macro.
+       (attr_eoffset): Likewise.
+       (attr_ename): Likewise.
+       * testsuite/poke.pkl/attr-diag-2.pk: New test.
+       * testsuite/poke.pkl/attr-diag-3.pk: Likewise.
+       * testsuite/poke.pkl/attr-diag-4.pk: Likewise.
+       * testsuite/poke.pkl/attr-eoffset-5.pk: Likewise.
+       * testsuite/poke.pkl/attr-eoffset-4.pk: Likewise.
+       * testsuite/poke.pkl/attr-eoffset-3.pk: Likewise.
+       * testsuite/poke.pkl/attr-eoffset-2.pk: Likewise.
+       * testsuite/poke.pkl/attr-eoffset-1.pk: Likewise.
+       * testsuite/poke.pkl/attr-esize-5.pk: Likewise.
+       * testsuite/poke.pkl/attr-esize-4.pk: Likewise.
+       * testsuite/poke.pkl/attr-esize-3.pk: Likewise.
+       * testsuite/poke.pkl/attr-esize-2.pk: Likewise.
+       * testsuite/poke.pkl/attr-esize-1.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-arr-6.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-arr-5.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-arr-4.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-arr-3.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-arr-2.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-arr-1.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-union-1.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-struct-1.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-struct-2.pk: Likewise.
+       * testsuite/poke.pkl/attr-ename-union-2.pk: Likewise.
+       * doc/poke.texi (Array Attributes): Document new attributes for
+       arrays.
+       (Struct Attributes): Ditto for structs.
+       * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
+
 2022-02-09  Jose E. Marchesi  <jemarch@gnu.org>
 
        * poke/pk-ios.c (pk_open_proc_maps): Use PRIx64 instead of %lx.
diff --git a/doc/poke.texi b/doc/poke.texi
index 83bd6b05..29b3405e 100644
--- a/doc/poke.texi
+++ b/doc/poke.texi
@@ -10485,6 +10485,33 @@ Examples:
 (poke) a'strict
 0
 @end example
+@item eoffset (@var{idx})
+Offset of the element identified by the index @var{idx} in the array.
+Examples:
+
+@example
+(poke) [1,2,3]'eoffset (1)
+32#b
+@end example
+
+If the provided index is out of bounds then @code{E_out_of_bounds} is
+raised.
+@item esize (@var{idx})
+Size of the element identified by the index @var{idx} in the array.
+Examples:
+
+@example
+(poke) ["foo","x",""]'esize (1)
+16#b
+@end example
+
+If the provided index is out of bounds then @code{E_out_of_bounds} is
+raised.
+@item ename (@var{idx})
+The string @code{".[@var{idx}]"}.
+
+If the provided index is out of bounds then @code{E_out_of_bounds} is
+raised.
 @end table
 
 @node Structs
@@ -11675,6 +11702,44 @@ We get the following results:
 Boolean indicating whether the struct is mapped.
 @item strict
 Boolean indicating whether the struct is mapped in strict mode.
+@item eoffset (@var{idx})
+Offset of the field identified by the index @var{idx} in the struct.
+Examples:
+
+@example
+(poke) type Foo = struct @{ int i; long l; @}
+(poke) Foo@{@}'eoffset (1)
+32#b
+@end example
+
+If the provided index is out of bounds then @code{E_out_of_bounds} is
+raised.
+@item esize (@var{idx})
+Size of the field identified by the index @var{idx} in the struct.
+Examples:
+
+@example
+(poke) type Foo = struct @{ int i; long l; @}
+(poke) Foo@{@}'esize (1)
+64#b
+@end example
+
+If the provided index is out of bounds then @code{E_out_of_bounds} is
+raised.
+@item ename (@var{idx})
+Name of the field identified by the index @var{idx} in the struct.  If
+the field is anonymous then the empty string.
+
+Examples:
+
+@example
+(poke) type Foo = struct @{ int foo; long bar; @}
+(poke) Foo@{@}'ename (0)
+"foo"
+@end example
+
+If the provided index is out of bounds then @code{E_out_of_bounds} is
+raised.
 @end table
 
 @node Types
diff --git a/libpoke/pkl-anal.c b/libpoke/pkl-anal.c
index 865e0c89..5089e07e 100644
--- a/libpoke/pkl-anal.c
+++ b/libpoke/pkl-anal.c
@@ -682,6 +682,42 @@ PKL_PHASE_BEGIN_HANDLER (pkl_anal1_ps_cons)
 }
 PKL_PHASE_END_HANDLER
 
+/* Some attributes are binary and thus require a second argument.
+   Make sure they have it.  */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_anal1_ps_op_attr)
+{
+  pkl_ast_node exp = PKL_PASS_NODE;
+  enum pkl_ast_attr attr = PKL_AST_EXP_ATTR (exp);
+
+  assert (attr != PKL_AST_ATTR_NONE);
+
+  switch (attr)
+    {
+    case PKL_AST_ATTR_EOFFSET:
+    case PKL_AST_ATTR_ESIZE:
+    case PKL_AST_ATTR_ENAME:
+      if (PKL_AST_EXP_NUMOPS (exp) != 2)
+        {
+          PKL_ERROR (PKL_AST_LOC (exp),
+                     "attribute requires an argument");
+          PKL_ANAL_PAYLOAD->errors++;
+          PKL_PASS_ERROR;
+        }
+      break;
+    default:
+      if (PKL_AST_EXP_NUMOPS (exp) != 1)
+        {
+          PKL_ERROR (PKL_AST_LOC (exp),
+                     "attribute doesn't take any argument");
+          PKL_ANAL_PAYLOAD->errors++;
+          PKL_PASS_ERROR;
+        }
+      break;
+    }
+}
+PKL_PHASE_END_HANDLER
+
 struct pkl_phase pkl_phase_anal1 =
   {
    PKL_PHASE_PS_HANDLER (PKL_AST_SRC, pkl_anal_ps_src),
@@ -706,6 +742,7 @@ struct pkl_phase pkl_phase_anal1 =
    PKL_PHASE_PS_TYPE_HANDLER (PKL_TYPE_FUNCTION, pkl_anal1_ps_type_function),
    PKL_PHASE_PS_TYPE_HANDLER (PKL_TYPE_OFFSET, pkl_anal1_ps_type_offset),
    PKL_PHASE_PS_OP_HANDLER (PKL_AST_OP_SL, pkl_anal1_ps_op_sl),
+   PKL_PHASE_PS_OP_HANDLER (PKL_AST_OP_ATTR, pkl_anal1_ps_op_attr),
    PKL_PHASE_PS_DEFAULT_HANDLER (pkl_anal_ps_default),
   };
 
diff --git a/libpoke/pkl-ast.c b/libpoke/pkl-ast.c
index 0a4a2a72..d585cce9 100644
--- a/libpoke/pkl-ast.c
+++ b/libpoke/pkl-ast.c
@@ -197,6 +197,32 @@ pkl_ast_make_binary_exp (pkl_ast ast,
   return exp;
 }
 
+/* Build and return an AST node for a ternary expression.  */
+
+pkl_ast_node
+pkl_ast_make_ternary_exp (pkl_ast ast,
+                          enum pkl_ast_op code,
+                          pkl_ast_node op1,
+                          pkl_ast_node op2,
+                          pkl_ast_node op3)
+{
+  pkl_ast_node exp = pkl_ast_make_node (ast, PKL_AST_EXP);
+
+  PKL_AST_EXP_CODE (exp) = code;
+  PKL_AST_EXP_ATTR (exp) = PKL_AST_ATTR_NONE;
+  PKL_AST_EXP_NUMOPS (exp) = 3;
+  PKL_AST_EXP_OPERAND (exp, 0) = ASTREF (op1);
+  PKL_AST_EXP_OPERAND (exp, 1) = ASTREF (op2);
+  PKL_AST_EXP_OPERAND (exp, 2) = ASTREF (op3);
+
+  PKL_AST_LITERAL_P (exp)
+    = (PKL_AST_LITERAL_P (op1)
+       && PKL_AST_LITERAL_P (op2)
+       && PKL_AST_LITERAL_P (op3));
+
+  return exp;
+}
+
 /* Return the written form of the given attribute code.  This returns
    NULL for PKL_AST_ATTR_NONE */
 
diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
index 36b31f89..34b7b68e 100644
--- a/libpoke/pkl-ast.h
+++ b/libpoke/pkl-ast.h
@@ -479,7 +479,7 @@ struct pkl_ast_exp
   enum pkl_ast_op code;
   enum pkl_ast_attr attr;
   uint8_t numops : 8;
-  union pkl_ast_node *operands[2];
+  union pkl_ast_node *operands[3];
   int flag;
 };
 
@@ -492,6 +492,12 @@ pkl_ast_node pkl_ast_make_binary_exp (pkl_ast ast,
                                       pkl_ast_node op1,
                                       pkl_ast_node op2);
 
+pkl_ast_node pkl_ast_make_ternary_exp (pkl_ast ast,
+                                       enum pkl_ast_op code,
+                                       pkl_ast_node op1,
+                                       pkl_ast_node op2,
+                                       pkl_ast_node op3);
+
 const char *pkl_attr_name (enum pkl_ast_attr attr);
 
 /* PKL_AST_COND_EXP nodes represent conditional expressions, having
diff --git a/libpoke/pkl-attrs.def b/libpoke/pkl-attrs.def
index 857204b8..453ec719 100644
--- a/libpoke/pkl-attrs.def
+++ b/libpoke/pkl-attrs.def
@@ -20,6 +20,7 @@
    The second column is the attribute identifier, that the user writes
    in the program code to invoke the attribute.  */
 
+/* Unary attributes.  */
 PKL_DEF_ATTR (PKL_AST_ATTR_SIZE, "size")
 PKL_DEF_ATTR (PKL_AST_ATTR_SIGNED, "signed")
 PKL_DEF_ATTR (PKL_AST_ATTR_MAGNITUDE, "magnitude")
@@ -31,6 +32,11 @@ PKL_DEF_ATTR (PKL_AST_ATTR_MAPPED, "mapped")
 PKL_DEF_ATTR (PKL_AST_ATTR_IOS, "ios")
 PKL_DEF_ATTR (PKL_AST_ATTR_STRICT, "strict")
 
+/* Binary attributes.  */
+PKL_DEF_ATTR (PKL_AST_ATTR_EOFFSET, "eoffset")
+PKL_DEF_ATTR (PKL_AST_ATTR_ESIZE, "esize")
+PKL_DEF_ATTR (PKL_AST_ATTR_ENAME, "ename")
+
 /*
 Local variables:
 mode:c
diff --git a/libpoke/pkl-gen-attrs.pks b/libpoke/pkl-gen-attrs.pks
index 8ccecad8..46583ded 100644
--- a/libpoke/pkl-gen-attrs.pks
+++ b/libpoke/pkl-gen-attrs.pks
@@ -20,7 +20,7 @@
 ;;; attributes supported in Poke.
 
 ;;; RAS_MACRO_ATTR_SIZE @type
-;;; ( VAL -- VAL OFF )
+;;; ( VAL -- OFF )
 ;;;
 ;;; Given a value on the stack, push an offset  denoting the size
 ;;; of the value.
@@ -50,7 +50,7 @@
         .end
 
 ;;; RAS_MACRO_ATTR_OFFSET @type
-;;; ( VAL -- VAL OFF )
+;;; ( VAL -- OFF )
 ;;;
 ;;; Given a value on the stack, push an offset denoting the `offset'
 ;;; of the value.
@@ -84,7 +84,7 @@
         .end
 
 ;;; RAS_MACRO_ATTR_IOS @type
-;;; ( VAL -- VAL INT )
+;;; ( VAL -- INT )
 ;;;
 ;;; Given a value on the stack, push an offset denoting the IOS
 ;;; of the value.
@@ -116,7 +116,7 @@
         .end
 
 ;;; RAS_MACRO_ATTR_STRICT @type
-;;; ( VAL -- VAL INT )
+;;; ( VAL -- INT )
 ;;;
 ;;; Given a value on the stack, push a boolean to the stack
 ;;; denoting whether the value's mapping is strict.
@@ -135,7 +135,7 @@
         .end
 
 ;;; RAS_MACRO_ATTR_MAPPED @type
-;;; ( VAL -- VAL INT )
+;;; ( VAL -- INT )
 ;;;
 ;;; Given a value on the stack, push a boolean to the stack
 ;;; denoting whether the value is mapped.
@@ -152,3 +152,130 @@
         push int<32>0
         nip
         .end
+
+;;; RAS_MACRO_ATTR_EOFFSET
+;;; ( VAL ULONG -- OFF )
+;;;
+;;; Given a composite value and the index of one of its elements
+;;; on the stack, push the offset of the element.
+
+        .macro attr_eoffset
+        ;; If the value is not composite, raise E_inval.
+        swap                    ; IDX VAL
+        tyissct                 ; IDX VAL ISSCT
+        bnzi .struct
+        drop                    ; IDX VAL
+        tyisa                   ; IDX VAL ISARR
+        bnzi .array
+        push PVM_E_INVAL
+        raise
+.struct:
+        drop                    ; IDX VAL
+        swap                    ; VAL IDX
+        srefio
+        nip                     ; VAL BOFF
+        ba .done
+.array:
+        drop                    ; IDX VAL
+        swap                    ; VAL IDX
+        arefo
+        nip                     ; VAL BOFF
+.done:
+        nip                     ; BOFF
+        ;; Build an offset value from the bit-offset.
+        push ulong<64>1         ; VAL BOFF UNIT
+        mko                     ; VAL OFF
+        .end
+
+;;; RAS_MACRO_ATTR_ESIZE
+;;; ( VAL ULONG -- OFF )
+;;;
+;;; Given a composite value and the index of one of its elements
+;;; on the stack, push the size of the element.
+
+        .macro attr_esize
+        ;; If the value is not composite, raise E_inval.
+        swap                    ; IDX VAL
+        tyissct                 ; IDX VAL ISSCT
+        bnzi .struct
+        drop                    ; IDX VAL
+        tyisa                   ; IDX VAL ISARR
+        bnzi .array
+        push PVM_E_INVAL
+        raise
+.struct:
+        drop                    ; IDX VAL
+        swap                    ; VAL IDX
+        srefi
+        nip                     ; VAL ELEM
+        siz
+        nip                     ; VAL SIZ
+        ba .done
+.array:
+        drop                    ; IDX VAL
+        swap                    ; VAL IDX
+        aref
+        nip                     ; VAL ELEM
+        siz
+        nip                     ; VAL SIZ
+.done:
+        nip                     ; SIZ
+        ;; Build an offset value from the bit-offset.
+        push ulong<64>1         ; VAL SIZ UNIT
+        mko                     ; VAL OFF
+        .end
+
+;;; RAS_MACRO_ATTR_ENAME
+;;; ( VAL ULONG -- STR )
+;;;
+;;; Given a composite value and the index of one of its elements
+;;; on the stack, push the name of the element.
+;;;
+;;; For struct values, use the names of the fields.  Anonymous
+;;; fields return the empty string.
+;;;
+;;; For array values, return ".[N]" for the Nth element.
+
+        .macro attr_ename
+        ;; If the value is not composite, raise E_inval.
+        swap                    ; IDX VAL
+        tyissct                 ; IDX VAL ISSCT
+        bnzi .struct
+        drop                    ; IDX VAL
+        tyisa                   ; IDX VAL ISARR
+        bnzi .array
+        push PVM_E_INVAL
+        raise
+.struct:
+        drop                    ; IDX VAL
+        swap                    ; VAL IDX
+        srefin
+        nip                     ; VAL STR
+        bnn .done
+        drop
+        push ""
+        ba .done
+.array:
+        drop                    ; IDX VAL
+        ;; See if the index is in the range of the array.
+        sel                     ; IDX VAL SEL
+        rot                     ; VAL SEL IDX
+        lelu                    ; VAL SEL IDX (SIZ<=IDX)
+        bzi .bound_ok
+        push PVM_E_OUT_OF_BOUNDS
+        raise
+.bound_ok:
+        drop                    ; VAL SEL IDX
+        nip                     ; VAL IDX
+        push ".["               ; VAL IDX ".["
+        swap                    ; VAL ".[" IDX
+        push int<32>10          ; VAL ".[" IDX 10
+        formatlu 64             ; VAL ".[" "IDX"
+        sconc
+        nip2                    ; VAL ".[IDX"
+        push "]"
+        sconc
+        nip2                    ; VAL ".[IDX]"
+.done:
+        nip                     ; STR
+        .end
diff --git a/libpoke/pkl-gen.c b/libpoke/pkl-gen.c
index 118f4eef..169c8e23 100644
--- a/libpoke/pkl-gen.c
+++ b/libpoke/pkl-gen.c
@@ -4356,6 +4356,7 @@ PKL_PHASE_END_HANDLER
 
 /*
  * | OPERAND1
+ * | [OPERAND2]
  * EXP
  */
 
@@ -4406,6 +4407,15 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_ps_op_attr)
       /* XXX writeme */
       assert (0);
       break;
+    case PKL_AST_ATTR_EOFFSET:
+      RAS_MACRO_ATTR_EOFFSET;
+      break;
+    case PKL_AST_ATTR_ESIZE:
+      RAS_MACRO_ATTR_ESIZE;
+      break;
+    case PKL_AST_ATTR_ENAME:
+      RAS_MACRO_ATTR_ENAME;
+      break;
     default:
       PKL_ICE (PKL_AST_LOC (exp),
                "unhandled attribute expression code #%d in code generator",
diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
index 4a70eae2..c7aa25e4 100644
--- a/libpoke/pkl-insn.def
+++ b/libpoke/pkl-insn.def
@@ -283,6 +283,7 @@ PKL_DEF_INSN(PKL_INSN_SREFO,"","srefo")
 PKL_DEF_INSN(PKL_INSN_SREFI,"","srefi")
 PKL_DEF_INSN(PKL_INSN_SREFIO,"","srefio")
 PKL_DEF_INSN(PKL_INSN_SREFIA,"","srefia")
+PKL_DEF_INSN(PKL_INSN_SREFIN,"","srefin")
 PKL_DEF_INSN(PKL_INSN_SREFMNT,"","srefmnt")
 PKL_DEF_INSN(PKL_INSN_SSET,"","sset")
 PKL_DEF_INSN(PKL_INSN_SSETI,"","sseti")
@@ -338,6 +339,7 @@ PKL_DEF_INSN(PKL_INSN_TYAGETB,"","tyagetb")
 
 PKL_DEF_INSN(PKL_INSN_TYPOF,"","typof")
 
+PKL_DEF_INSN(PKL_INSN_TYISA,"","tyisa")
 PKL_DEF_INSN(PKL_INSN_TYISC,"","tyisc")
 PKL_DEF_INSN(PKL_INSN_TYISSCT,"","tyissct")
 
diff --git a/libpoke/pkl-pass.c b/libpoke/pkl-pass.c
index 634562d1..a6f239b9 100644
--- a/libpoke/pkl-pass.c
+++ b/libpoke/pkl-pass.c
@@ -334,11 +334,12 @@ pkl_do_pass_1 (pkl_compiler compiler,
   switch (PKL_AST_CODE (node))
     {
     case PKL_AST_EXP:
-      PKL_PASS (PKL_AST_EXP_OPERAND (node, 0));
-      if (PKL_AST_EXP_NUMOPS (node) == 2)
-        PKL_PASS (PKL_AST_EXP_OPERAND (node, 1));
-
-      break;
+      {
+        int i;
+        for (i = 0; i < PKL_AST_EXP_NUMOPS (node); ++i)
+          PKL_PASS (PKL_AST_EXP_OPERAND (node, i));
+        break;
+      }
     case PKL_AST_PROGRAM:
       if (PKL_AST_PROGRAM_ELEMS (node))
         PKL_PASS_CHAIN (PKL_AST_PROGRAM_ELEMS (node));
diff --git a/libpoke/pkl-promo.c b/libpoke/pkl-promo.c
index aea02168..ada47065 100644
--- a/libpoke/pkl-promo.c
+++ b/libpoke/pkl-promo.c
@@ -1488,6 +1488,41 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_op_in)
 }
 PKL_PHASE_END_HANDLER
 
+/* Promote the arguments of some attributes.  */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_op_attr)
+{
+  pkl_ast_node exp = PKL_PASS_NODE;
+  enum pkl_ast_attr attr = PKL_AST_EXP_ATTR (exp);
+  int restart = 0;
+
+  switch (attr)
+    {
+    case PKL_AST_ATTR_EOFFSET:
+    case PKL_AST_ATTR_ESIZE:
+    case PKL_AST_ATTR_ENAME:
+
+      /* The argument of the attribute must be promoted to an unsigned
+         64-bit integer.  */
+      if (!promote_integral (PKL_PASS_AST,
+                             64, 0,
+                             &PKL_AST_EXP_OPERAND (exp, 1),
+                             &restart))
+        {
+          PKL_ICE (PKL_AST_LOC (exp),
+                   "couldn't pormote argument of attribute expression #%" 
PRIu64,
+                   PKL_AST_UID (exp));
+          PKL_PASS_ERROR;
+        }
+
+      PKL_PASS_RESTART = restart;
+      break;
+    default:
+      break;
+    }
+}
+PKL_PHASE_END_HANDLER
+
 PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_cons)
 {
   pkl_ast_node cons = PKL_PASS_NODE;
@@ -1646,6 +1681,7 @@ struct pkl_phase pkl_phase_promo =
    PKL_PHASE_PS_OP_HANDLER (PKL_AST_OP_DIV, pkl_promo_ps_op_div),
    PKL_PHASE_PS_OP_HANDLER (PKL_AST_OP_CEILDIV, pkl_promo_ps_op_div),
    PKL_PHASE_PS_OP_HANDLER (PKL_AST_OP_IN, pkl_promo_ps_op_in),
+   PKL_PHASE_PS_OP_HANDLER (PKL_AST_OP_ATTR, pkl_promo_ps_op_attr),
    PKL_PHASE_PS_HANDLER (PKL_AST_FUNC_ARG, pkl_promo_ps_func_arg),
    PKL_PHASE_PS_HANDLER (PKL_AST_MAP, pkl_promo_ps_map),
    PKL_PHASE_PS_HANDLER (PKL_AST_INDEXER, pkl_promo_ps_indexer),
diff --git a/libpoke/pkl-tab.y b/libpoke/pkl-tab.y
index 84ff02b2..138e4d92 100644
--- a/libpoke/pkl-tab.y
+++ b/libpoke/pkl-tab.y
@@ -784,7 +784,14 @@ expression:
                   $$ = pkl_ast_make_binary_exp (pkl_parser->ast, 
PKL_AST_OP_ATTR,
                                                 $1, $2);
                   PKL_AST_LOC ($2) = @2;
-                  PKL_AST_LOC ($$) = @$;
+                  PKL_AST_LOC ($$) = @2;
+                }
+        | expression ATTR '(' expression ')'
+                {
+                  $$ = pkl_ast_make_ternary_exp (pkl_parser->ast, 
PKL_AST_OP_ATTR,
+                                                 $1, $2, $4);
+                  PKL_AST_LOC ($2) = @2;
+                  PKL_AST_LOC ($$) = @2;
                 }
         | expression '+' expression
                 {
diff --git a/libpoke/pkl-trans.c b/libpoke/pkl-trans.c
index 7626de9b..eb09c351 100644
--- a/libpoke/pkl-trans.c
+++ b/libpoke/pkl-trans.c
@@ -481,7 +481,8 @@ PKL_PHASE_END_HANDLER
 
 /* Determine the attribute code of attribute expressions, emitting an
    error if the given attribute name is not defined.  Finally, turn
-   the binary expression into an unary expression.  */
+   the ternary expression into an either unary or binary expression,
+   depending whether the attribute gets an argument or it doesn't.  */
 
 PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_op_attr)
 {
@@ -512,9 +513,19 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_op_attr)
 
   PKL_AST_EXP_ATTR (exp) = attr;
 
-  /* Turn the binary expression into an unary expression.  */
-  PKL_AST_EXP_NUMOPS (exp) = 1;
-  pkl_ast_node_free (PKL_AST_EXP_OPERAND (exp, 1));
+  /* Turn the binary expression into an unary or binary
+     expression.  */
+  if (PKL_AST_EXP_NUMOPS (exp) == 2)
+    {
+      PKL_AST_EXP_NUMOPS (exp) = 1;
+      pkl_ast_node_free (PKL_AST_EXP_OPERAND (exp, 1));
+    }
+  else
+    {
+      PKL_AST_EXP_NUMOPS (exp) = 2;
+      pkl_ast_node_free (PKL_AST_EXP_OPERAND (exp, 1));
+      PKL_AST_EXP_OPERAND (exp, 1) = PKL_AST_EXP_OPERAND (exp, 2);
+    }
 }
 PKL_PHASE_END_HANDLER
 
diff --git a/libpoke/pkl-typify.c b/libpoke/pkl-typify.c
index ba190f19..d8c99b12 100644
--- a/libpoke/pkl-typify.c
+++ b/libpoke/pkl-typify.c
@@ -2398,8 +2398,9 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_try_catch_stmt)
 }
 PKL_PHASE_END_HANDLER
 
-/* Check that attribute expressions are applied to the proper types,
-   and then determine the type of the attribute expression itself.  */
+/* Check that attribute expressions are applied to the proper types
+   and that they get the right kind of arguments, and then determine
+   the type of the attribute expression itself.  */
 
 PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_attr)
 {
@@ -2502,6 +2503,54 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_attr)
       exp_type = pkl_ast_make_integral_type (PKL_PASS_AST, 32, 1);
       PKL_AST_TYPE (exp) = ASTREF (exp_type);
       break;
+    case PKL_AST_ATTR_EOFFSET:
+    case PKL_AST_ATTR_ESIZE:
+    case PKL_AST_ATTR_ENAME:
+      {
+        /* All these attributes are binary and require an integral
+           argument.  */
+
+        pkl_ast_node argument = PKL_AST_EXP_OPERAND (exp, 1);
+        pkl_ast_node argument_type = PKL_AST_TYPE (argument);
+
+        /* Integral structs shall be considered as integers in this
+           context.  */
+        if (PKL_AST_TYPE_CODE (argument_type) == PKL_TYPE_STRUCT
+            && PKL_AST_TYPE_S_ITYPE (argument_type))
+          argument_type = PKL_AST_TYPE_S_ITYPE (argument_type);
+
+        if (PKL_AST_TYPE_CODE (argument_type) != PKL_TYPE_INTEGRAL)
+          {
+            char *argument_type_str = pkl_type_str (argument_type, 1);
+
+            PKL_ERROR (PKL_AST_LOC (argument),
+                       "invalid argument to attribute\n"
+                       "expected integral, got %s",
+                       argument_type_str);
+            free (argument_type_str);
+            PKL_TYPIFY_PAYLOAD->errors++;
+            PKL_PASS_ERROR;
+          }
+
+        /* Now set the type of the resulting value depending on the
+           attribute.  */
+        if (attr == PKL_AST_ATTR_ENAME)
+          exp_type = pkl_ast_make_string_type (PKL_PASS_AST);
+        else
+          {
+            /* For both EOFFSET and ESIZE the result type is an offset
+               in bits.  */
+            offset_unit_type = pkl_ast_make_integral_type (PKL_PASS_AST, 64, 
0);
+            offset_unit = pkl_ast_make_integer (PKL_PASS_AST, 1);
+            PKL_AST_TYPE (offset_unit) = ASTREF (offset_unit_type);
+
+            exp_type = pkl_ast_make_integral_type (PKL_PASS_AST, 64, 0);
+            exp_type = pkl_ast_make_offset_type (PKL_PASS_AST, exp_type, 
offset_unit);
+          }
+
+        PKL_AST_TYPE (exp) = ASTREF (exp_type);
+        break;
+      }
     default:
       PKL_ICE (PKL_AST_LOC (exp),
                "unhandled attribute expression code #%d in typify1",
diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
index 495eaa29..ae5709d9 100644
--- a/libpoke/pvm.jitter
+++ b/libpoke/pvm.jitter
@@ -5152,6 +5152,32 @@ instruction srefio ()
   end
 end
 
+# Instruction: srefin
+#
+# Given a struct and an index, push the name of the field occupying
+# the position specified by the index in the given struct.  If the
+# field is anonymous, push PVM_NULL.  If the struct doesn't have that
+# many fields, raise PVM_E_OUT_OF_BOUNDS.
+#
+# Stack: ( SCT ULONG -- SCT ULONG STR )
+# Exceptions: PVM_E_OUT_OF_BOUNDS
+
+instruction srefin ()
+  branching # because of PVM_RAISE_DIRECT
+  code
+    pvm_val sct = JITTER_UNDER_TOP_STACK ();
+    pvm_val index = JITTER_TOP_STACK ();
+
+    if (PVM_VAL_ULONG (index) < 0
+        || (PVM_VAL_ULONG (index) >=
+            PVM_VAL_INTEGRAL (PVM_VAL_SCT_NFIELDS (sct))))
+      PVM_RAISE_DFL (PVM_E_OUT_OF_BOUNDS);
+
+    JITTER_PUSH_STACK (PVM_VAL_SCT_FIELD_NAME (sct,
+                                               PVM_VAL_ULONG (index)));
+  end
+end
+
 # Instruction: smodi
 #
 # Given a struct and an index, push the modified flags of the field
@@ -5596,6 +5622,19 @@ instruction typof ()
   end
 end
 
+# Instruction: tyisa
+#
+# Given a value, push 1 on the stack if it is an array.  Push 0
+# otherwise.
+#
+# Stack: ( VAL -- VAL INT )
+
+instruction tyisa ()
+  code
+    JITTER_PUSH_STACK (PVM_MAKE_INT (PVM_IS_ARR (JITTER_TOP_STACK ()), 32));
+  end
+end
+
 # Instruction: tyisc
 #
 # Given a value, push 1 on the stack if it is a closure.  Push 0
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 5ffc64f3..0ec44654 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -768,6 +768,29 @@ EXTRA_DIST = \
   poke.pkl/assert-diag-3.pk \
   poke.pkl/assert-diag-4.pk \
   poke.pkl/attr-diag-1.pk \
+  poke.pkl/attr-diag-2.pk \
+  poke.pkl/attr-diag-3.pk \
+  poke.pkl/attr-diag-4.pk \
+  poke.pkl/attr-ename-arr-1.pk \
+  poke.pkl/attr-ename-arr-2.pk \
+  poke.pkl/attr-ename-arr-3.pk \
+  poke.pkl/attr-ename-arr-4.pk \
+  poke.pkl/attr-ename-arr-5.pk \
+  poke.pkl/attr-ename-arr-6.pk \
+  poke.pkl/attr-ename-struct-1.pk \
+  poke.pkl/attr-ename-struct-2.pk \
+  poke.pkl/attr-ename-union-1.pk \
+  poke.pkl/attr-ename-union-2.pk \
+  poke.pkl/attr-eoffset-1.pk \
+  poke.pkl/attr-eoffset-2.pk \
+  poke.pkl/attr-eoffset-3.pk \
+  poke.pkl/attr-eoffset-4.pk \
+  poke.pkl/attr-eoffset-5.pk \
+  poke.pkl/attr-esize-1.pk \
+  poke.pkl/attr-esize-2.pk \
+  poke.pkl/attr-esize-3.pk \
+  poke.pkl/attr-esize-4.pk \
+  poke.pkl/attr-esize-5.pk \
   poke.pkl/attr-ios-1.pk \
   poke.pkl/attr-ios-2.pk \
   poke.pkl/attr-ios-diag-1.pk \
diff --git a/testsuite/poke.pkl/attr-diag-2.pk 
b/testsuite/poke.pkl/attr-diag-2.pk
new file mode 100644
index 00000000..7229e6d8
--- /dev/null
+++ b/testsuite/poke.pkl/attr-diag-2.pk
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+var a =
+  [1,2,3]'length /* { dg-error "argument" } */
+    (32);
diff --git a/testsuite/poke.pkl/attr-diag-3.pk 
b/testsuite/poke.pkl/attr-diag-3.pk
new file mode 100644
index 00000000..da1089d0
--- /dev/null
+++ b/testsuite/poke.pkl/attr-diag-3.pk
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+
+var a =
+  [1,2,3]'eoffset; /* { dg-error "argument" } */
diff --git a/testsuite/poke.pkl/attr-diag-4.pk 
b/testsuite/poke.pkl/attr-diag-4.pk
new file mode 100644
index 00000000..b41e01f1
--- /dev/null
+++ b/testsuite/poke.pkl/attr-diag-4.pk
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+
+var a =
+  [1,2,3]'eoffset (
+    "foo" + "bar" /* { dg-error "invalid argument.*\n.*expected integral" } */
+    );
diff --git a/testsuite/poke.pkl/attr-ename-arr-1.pk 
b/testsuite/poke.pkl/attr-ename-arr-1.pk
new file mode 100644
index 00000000..d5c7e4d2
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-arr-1.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {[1,2,3]'ename(0)} } */
+/* { dg-output {"[.][[]0[]]"} } */
diff --git a/testsuite/poke.pkl/attr-ename-arr-2.pk 
b/testsuite/poke.pkl/attr-ename-arr-2.pk
new file mode 100644
index 00000000..e667915d
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-arr-2.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {[1,2,3]'ename(1)} } */
+/* { dg-output {"[.][[]1[]]"} } */
diff --git a/testsuite/poke.pkl/attr-ename-arr-3.pk 
b/testsuite/poke.pkl/attr-ename-arr-3.pk
new file mode 100644
index 00000000..36b262ac
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-arr-3.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {[1,2,3]'ename(2)} } */
+/* { dg-output {"[.][[]2[]]"} } */
diff --git a/testsuite/poke.pkl/attr-ename-arr-4.pk 
b/testsuite/poke.pkl/attr-ename-arr-4.pk
new file mode 100644
index 00000000..759e44d0
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-arr-4.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {try [1,2,3]'ename(3); catch if E_out_of_bounds { print 
"caught\n"; } } } */
+/* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/attr-ename-arr-5.pk 
b/testsuite/poke.pkl/attr-ename-arr-5.pk
new file mode 100644
index 00000000..53ad3088
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-arr-5.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {try 23#B'ename(3); catch if E_inval { print "caught\n"; } } } 
*/
+/* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/attr-ename-arr-6.pk 
b/testsuite/poke.pkl/attr-ename-arr-6.pk
new file mode 100644
index 00000000..f60d61eb
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-arr-6.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {try int[]()'ename(0); catch if E_out_of_bounds { print 
"caught\n"; } } } */
+/* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/attr-ename-struct-1.pk 
b/testsuite/poke.pkl/attr-ename-struct-1.pk
new file mode 100644
index 00000000..4e630d85
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-struct-1.pk
@@ -0,0 +1,6 @@
+/* { dg-do run } */
+
+type Foo = struct { int i; long; };
+
+/* { dg-command {Foo{}'ename(0)} } */
+/* { dg-output {"i"} } */
diff --git a/testsuite/poke.pkl/attr-ename-struct-2.pk 
b/testsuite/poke.pkl/attr-ename-struct-2.pk
new file mode 100644
index 00000000..8e61660d
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-struct-2.pk
@@ -0,0 +1,6 @@
+/* { dg-do run } */
+
+type Foo = struct { int i; long; };
+
+/* { dg-command {Foo{}'ename(1)} } */
+/* { dg-output {""} } */
diff --git a/testsuite/poke.pkl/attr-ename-union-1.pk 
b/testsuite/poke.pkl/attr-ename-union-1.pk
new file mode 100644
index 00000000..cc4c0967
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-union-1.pk
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+
+var x = 10;
+type Foo = union { int i : x > 10; long bar; };
+
+/* { dg-command {Foo{}'ename(0)} } */
+/* { dg-output {"bar"} } */
diff --git a/testsuite/poke.pkl/attr-ename-union-2.pk 
b/testsuite/poke.pkl/attr-ename-union-2.pk
new file mode 100644
index 00000000..d7e01b2d
--- /dev/null
+++ b/testsuite/poke.pkl/attr-ename-union-2.pk
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+
+var x = 10;
+type Foo = union { int i : x > 10; long bar; };
+
+/* { dg-command {try Foo{}'ename(1); catch if E_out_of_bounds { print 
"caught\n"; } } } */
+/* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/attr-eoffset-1.pk 
b/testsuite/poke.pkl/attr-eoffset-1.pk
new file mode 100644
index 00000000..0397e266
--- /dev/null
+++ b/testsuite/poke.pkl/attr-eoffset-1.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {[1,2,3]'eoffset (0)} } */
+/* { dg-output "0UL#b" } */
diff --git a/testsuite/poke.pkl/attr-eoffset-2.pk 
b/testsuite/poke.pkl/attr-eoffset-2.pk
new file mode 100644
index 00000000..9296e16e
--- /dev/null
+++ b/testsuite/poke.pkl/attr-eoffset-2.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {[1,2,3]'eoffset (1)} } */
+/* { dg-output "32UL#b" } */
diff --git a/testsuite/poke.pkl/attr-eoffset-3.pk 
b/testsuite/poke.pkl/attr-eoffset-3.pk
new file mode 100644
index 00000000..fa6a22fa
--- /dev/null
+++ b/testsuite/poke.pkl/attr-eoffset-3.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {[1,2,3]'eoffset (2)} } */
+/* { dg-output "64UL#b" } */
diff --git a/testsuite/poke.pkl/attr-eoffset-4.pk 
b/testsuite/poke.pkl/attr-eoffset-4.pk
new file mode 100644
index 00000000..f8b5cedb
--- /dev/null
+++ b/testsuite/poke.pkl/attr-eoffset-4.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {try [1,2,3]'eoffset (3); catch if E_out_of_bounds { print 
"caught\n"; } } } */
+/* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/attr-eoffset-5.pk 
b/testsuite/poke.pkl/attr-eoffset-5.pk
new file mode 100644
index 00000000..061d65eb
--- /dev/null
+++ b/testsuite/poke.pkl/attr-eoffset-5.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {try "foo"'eoffset (3); catch if E_inval { print "caught\n"; } 
} } */
+/* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/attr-esize-1.pk 
b/testsuite/poke.pkl/attr-esize-1.pk
new file mode 100644
index 00000000..300ea505
--- /dev/null
+++ b/testsuite/poke.pkl/attr-esize-1.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {["foo","xxxx",""]'esize (0)} } */
+/* { dg-output "32UL#b" } */
diff --git a/testsuite/poke.pkl/attr-esize-2.pk 
b/testsuite/poke.pkl/attr-esize-2.pk
new file mode 100644
index 00000000..c231ba50
--- /dev/null
+++ b/testsuite/poke.pkl/attr-esize-2.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {["foo","xxxx",""]'esize (1)} } */
+/* { dg-output "40UL#b" } */
diff --git a/testsuite/poke.pkl/attr-esize-3.pk 
b/testsuite/poke.pkl/attr-esize-3.pk
new file mode 100644
index 00000000..3f2a390e
--- /dev/null
+++ b/testsuite/poke.pkl/attr-esize-3.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {["foo","xxxx",""]'esize (2)} } */
+/* { dg-output "8UL#b" } */
diff --git a/testsuite/poke.pkl/attr-esize-4.pk 
b/testsuite/poke.pkl/attr-esize-4.pk
new file mode 100644
index 00000000..a0f7639f
--- /dev/null
+++ b/testsuite/poke.pkl/attr-esize-4.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {try ["foo","xxxx",""]'esize (3); catch if E_out_of_bounds { 
print "caught\n"; } } } */
+/* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/attr-esize-5.pk 
b/testsuite/poke.pkl/attr-esize-5.pk
new file mode 100644
index 00000000..02e56252
--- /dev/null
+++ b/testsuite/poke.pkl/attr-esize-5.pk
@@ -0,0 +1,4 @@
+/* { dg-do run } */
+
+/* { dg-command {try 10'esize (3); catch if E_inval { print "caught\n"; } } } 
*/
+/* { dg-output "caught" } */
-- 
2.11.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]