Add "fill until" support v0.12.0
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 5 Oct 2023 01:30:36 +0000 (21:30 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 6 Oct 2023 16:03:17 +0000 (12:03 -0400)
This patch adds an item to add bytes until some offset is reached:

    89 89 aa ff cc dd +0x3c {ICITTE:8}

Result:

    89 89 aa ff cc dd 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 3c           ┆ ••••••••••••<

The item forms are:

    +EXPR
    +EXPR~PAD

where EXPR is a positive constant integer, a name, or an expression
between `{` and `}`, and PAD is a positive constant integer padding byte
value (0 by default).

The item `+EXPR~PAD` is functionally equivalent to
`PAD * {(EXPR) - ICITTE}`: it's just an alias for what I think is a
common operation.

For example, you might only want to write the first few fields of some
header:

    {le}
    "FRMT"          # Magic
    {0x7855:32}     # Total pixel count
    {data_beg:32}   # Data beginning pointer
    +0x80

    <data_beg>
    "the pixels"    # Here they are

Result:

    46 52 4d 54 55 78 00 00  80 00 00 00 00 00 00 00  ┆ FRMTUx••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
    74 68 65 20 70 69 78 65  6c 73                    ┆ the pixels

Change-Id: Ibd3a2bd243c15e1d4f9a9d5b5aa0076e19f9f9f7
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
24 files changed:
README.adoc
normand/normand.py
pyproject.toml
tests/fail-align-inval-pad-val-neg.nt
tests/fail-align-inval-pad-val-str.nt
tests/fail-fill-before.nt [new file with mode: 0644]
tests/fail-fill-inval-pad-val-neg.nt [new file with mode: 0644]
tests/fail-fill-inval-pad-val-str.nt [new file with mode: 0644]
tests/fail-fill-inval-val-neg.nt [new file with mode: 0644]
tests/fail-fill-inval-val-str.nt [new file with mode: 0644]
tests/fail-fill-pad-val-out-of-range.nt [new file with mode: 0644]
tests/fail-fill-unknown-name-1.nt [new file with mode: 0644]
tests/fail-fill-unknown-name-2.nt [new file with mode: 0644]
tests/pass-comment-sym-bin-const.nt
tests/pass-comment-sym-group.nt
tests/pass-comment-sym-hex-const.nt
tests/pass-comment-sym-rep-post.nt
tests/pass-fill-cur-offset.nt [new file with mode: 0644]
tests/pass-fill-name.nt [new file with mode: 0644]
tests/pass-fill-pad-val.nt [new file with mode: 0644]
tests/pass-fill.nt [new file with mode: 0644]
tests/pass-readme-intro-fill.nt [new file with mode: 0644]
tests/pass-readme-learn-fill-1.nt [new file with mode: 0644]
tests/pass-readme-learn-fill-2.nt [new file with mode: 0644]

index e98e63703460cdb5d478f26b95f2ba9593c36f08..ce8673359d23d13543b8b7e0ee037d81e13e519b 100644 (file)
@@ -29,7 +29,7 @@ _**Normand**_ is a text-to-binary processor with its own language.
 This package offers both a portable {py3} module and a command-line
 tool.
 
-WARNING: This version of Normand is 0.11, meaning both the Normand
+WARNING: This version of Normand is 0.12, meaning both the Normand
 language and the module/CLI interface aren't stable.
 
 ifdef::env-github[]
@@ -241,6 +241,40 @@ Output:
 ff 85 ff ff 00 00 15 d0
 ----
 
+Filling::
++
+Input:
++
+----
+{le}
+{0xdeadbeef:32}
+{-1993:16}
+{9:16}
++0x40
+{ICITTE:8}
+"meow mix"
++200~0xff
+{ICITTE:8}
+----
++
+Output:
++
+----
+ef be ad de 37 f8 09 00  00 00 00 00 00 00 00 00  ┆ ••••7•••••••••••
+00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
+00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
+00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
+40 6d 65 6f 77 20 6d 69  78 ff ff ff ff ff ff ff  ┆ @meow mix•••••••
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  ┆ ••••••••••••••••
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  ┆ ••••••••••••••••
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  ┆ ••••••••••••••••
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  ┆ ••••••••••••••••
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  ┆ ••••••••••••••••
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  ┆ ••••••••••••••••
+ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  ┆ ••••••••••••••••
+ff ff ff ff ff ff ff ff  c8                       ┆ •••••••••
+----
+
 Multilevel grouping::
 +
 Input:
@@ -417,6 +451,8 @@ The available items are:
 
 * A <<current-offset-alignment,current offset alignment>>.
 
+* A <<filling,filling>>.
+
 * A <<label,label>>, that is, a named constant holding the current
   offset.
 +
@@ -458,7 +494,7 @@ the following symbol characters are also considered comments where a
 comment may exist:
 
 ----
-/ \ ? & : ; . , [ ] _ = | -
+/ \ ? & : ; . , [ ] _ = | -
 ----
 
 The latter serve to improve readability so that you may write, for
@@ -962,6 +998,114 @@ aa bb cc ff ff ff 7a 6f  6f 6d  ┆ ••••••zoom
 ----
 ====
 
+=== Filling
+
+A _filling_ represents zero or more padding bytes to make the
+<<cur-offset,current offset>> reach a given value.
+
+A filling is:
+
+. The ``pass:[+]`` prefix.
+
+. One of:
+
+** A positive integer (hexadecimal starting with `0x` or `0X` accepted)
+   which is the current offset target.
+
+** The ``pass:[{]`` prefix, a valid {py3} expression of which the
+   evaluation result type is `int` or `bool` (automatically converted to
+   `int`), and the ``pass:[}]`` suffix.
++
+For a filling at some source location{nbsp}__**L**__, this expression
+may contain:
++
+--
+* The name of any <<label,label>> defined before{nbsp}__**L**__
+  which isn't within a nested group.
+* The name of any <<variable-assignment,variable>> known
+  at{nbsp}__**L**__.
+--
++
+The value of the special name `ICITTE` (`int` type) in this expression
+is the <<cur-offset,current offset>> (before handling the items to
+repeat).
+
+** A valid {py3} name.
++
+For the name `__NAME__`, this is equivalent to the
+`pass:[{]__NAME__pass:[}]` form above.
+
++
+This value must be greater than or equal to the current offset where
+it's used.
+
+. **Optional**:
++
+--
+. The ``pass:[~]`` prefix.
+. A positive integer (hexadecimal starting with `0x` or `0X` accepted)
+  which is the value of the byte to use as padding to reach the
+  current offset target.
+--
++
+Without this section, the padding byte value is zero.
+
+====
+Input:
+
+----
+aa bb cc dd
++0x40
+"hello world"
+----
+
+Output:
+
+----
+aa bb cc dd 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
+00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
+00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
+00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ┆ ••••••••••••••••
+68 65 6c 6c 6f 20 77 6f  72 6c 64                 ┆ hello world
+----
+====
+
+====
+Input:
+
+----
+!macro part(iter, fill)
+  <0> "particular security " {ord('0') + iter : 8} +fill~0x80
+!end
+
+{iter = 1}
+
+!repeat 5
+  m:part(iter, {32 + 4 * iter})
+  {iter = iter + 1}
+!end
+----
+
+Output:
+
+----
+70 61 72 74 69 63 75 6c  61 72 20 73 65 63 75 72  ┆ particular secur
+69 74 79 20 31 80 80 80  80 80 80 80 80 80 80 80  ┆ ity 1•••••••••••
+80 80 80 80 70 61 72 74  69 63 75 6c 61 72 20 73  ┆ ••••particular s
+65 63 75 72 69 74 79 20  32 80 80 80 80 80 80 80  ┆ ecurity 2•••••••
+80 80 80 80 80 80 80 80  80 80 80 80 70 61 72 74  ┆ ••••••••••••part
+69 63 75 6c 61 72 20 73  65 63 75 72 69 74 79 20  ┆ icular security
+33 80 80 80 80 80 80 80  80 80 80 80 80 80 80 80  ┆ 3•••••••••••••••
+80 80 80 80 80 80 80 80  70 61 72 74 69 63 75 6c  ┆ ••••••••particul
+61 72 20 73 65 63 75 72  69 74 79 20 34 80 80 80  ┆ ar security 4•••
+80 80 80 80 80 80 80 80  80 80 80 80 80 80 80 80  ┆ ••••••••••••••••
+80 80 80 80 80 80 80 80  70 61 72 74 69 63 75 6c  ┆ ••••••••particul
+61 72 20 73 65 63 75 72  69 74 79 20 35 80 80 80  ┆ ar security 5•••
+80 80 80 80 80 80 80 80  80 80 80 80 80 80 80 80  ┆ ••••••••••••••••
+80 80 80 80 80 80 80 80  80 80 80 80              ┆ ••••••••••••
+----
+====
+
 === Label
 
 A _label_ associates a name to the <<cur-offset,current offset>>.
index 935e8459b41f6c6542602f43807156e768a295a7..c44373d9d722d5f6e919f0d86ae1dfd498baaf55 100644 (file)
@@ -30,7 +30,7 @@
 # Upstream repository: <https://github.com/efficios/normand>.
 
 __author__ = "Philippe Proulx"
-__version__ = "0.11.0"
+__version__ = "0.12.0"
 __all__ = [
     "__author__",
     "__version__",
@@ -241,6 +241,29 @@ class _ExprMixin:
         return self._expr
 
 
+# Fill until some offset.
+class _FillUntil(_Item, _ExprMixin):
+    def __init__(
+        self, expr_str: str, expr: ast.Expression, pad_val: int, text_loc: TextLocation
+    ):
+        super().__init__(text_loc)
+        _ExprMixin.__init__(self, expr_str, expr)
+        self._pad_val = pad_val
+
+    # Padding byte value.
+    @property
+    def pad_val(self):
+        return self._pad_val
+
+    def __repr__(self):
+        return "_FillUntil({}, {}, {}, {})".format(
+            repr(self._expr_str),
+            repr(self._expr),
+            repr(self._pad_val),
+            repr(self._text_loc),
+        )
+
+
 # Variable assignment.
 class _VarAssign(_Item, _ExprMixin):
     def __init__(
@@ -603,7 +626,7 @@ class _Parser:
 
     # Pattern for _skip_ws_and_comments()
     _ws_or_syms_or_comments_pat = re.compile(
-        r"(?:[\s/\\?&:;.,+[\]_=|-]|#[^#]*?(?:\n|#))*"
+        r"(?:[\s/\\?&:;.,[\]_=|-]|#[^#]*?(?:\n|#))*"
     )
 
     # Skips as many whitespaces, insignificant symbol characters, and
@@ -1050,10 +1073,38 @@ class _Parser:
         self._expect_pat(self._label_set_offset_suffix_pat, "Expecting `>`")
         return item
 
+    # Pattern for _parse_pad_val()
+    _pad_val_prefix_pat = re.compile(r"~")
+
+    # Tries to parse a padding value, returning the padding value, or 0
+    # if none.
+    def _parse_pad_val(self):
+        # Padding value?
+        self._skip_ws()
+        pad_val = 0
+
+        if self._try_parse_pat(self._pad_val_prefix_pat) is not None:
+            self._skip_ws()
+            pad_val_text_loc = self._text_loc
+            m = self._expect_pat(
+                self._pos_const_int_pat,
+                "Expecting a positive constant integer (byte value)",
+            )
+
+            # Validate
+            pad_val = int(m.group(0), 0)
+
+            if pad_val > 255:
+                _raise_error(
+                    "Invalid padding byte value {}".format(pad_val),
+                    pad_val_text_loc,
+                )
+
+        return pad_val
+
     # Patterns for _try_parse_align_offset()
     _align_offset_prefix_pat = re.compile(r"@")
     _align_offset_val_pat = re.compile(r"\d+")
-    _align_offset_pad_val_prefix_pat = re.compile(r"~")
 
     # Tries to parse an offset alignment, returning an offset alignment
     # item on success.
@@ -1065,9 +1116,8 @@ class _Parser:
             # No match
             return
 
-        self._skip_ws()
-
         # Expect an alignment
+        self._skip_ws()
         align_text_loc = self._text_loc
         m = self._expect_pat(
             self._align_offset_val_pat,
@@ -1085,26 +1135,34 @@ class _Parser:
                 align_text_loc,
             )
 
-        # Padding value?
-        self._skip_ws()
-        pad_val = 0
+        # Padding value
+        pad_val = self._parse_pad_val()
 
-        if self._try_parse_pat(self._align_offset_pad_val_prefix_pat) is not None:
-            self._skip_ws()
-            pad_val_text_loc = self._text_loc
-            m = self._expect_pat(self._pos_const_int_pat, "Expecting a byte value")
+        # Return item
+        return _AlignOffset(val, pad_val, begin_text_loc)
 
-            # Validate
-            pad_val = int(m.group(0), 0)
+    # Patterns for _try_parse_fill_until()
+    _fill_until_prefix_pat = re.compile(r"\+")
+    _fill_until_pad_val_prefix_pat = re.compile(r"~")
 
-            if pad_val > 255:
-                _raise_error(
-                    "Invalid padding byte value {}".format(pad_val),
-                    pad_val_text_loc,
-                )
+    # Tries to parse a filling, returning a filling item on success.
+    def _try_parse_fill_until(self):
+        begin_text_loc = self._text_loc
+
+        # Match prefix
+        if self._try_parse_pat(self._fill_until_prefix_pat) is None:
+            # No match
+            return
+
+        # Expect expression
+        self._skip_ws()
+        expr_str, expr = self._expect_const_int_name_expr(True)
+
+        # Padding value
+        pad_val = self._parse_pad_val()
 
         # Return item
-        return _AlignOffset(val, pad_val, begin_text_loc)
+        return _FillUntil(expr_str, expr, pad_val, begin_text_loc)
 
     # Patterns for _expect_rep_mul_expr()
     _inner_expr_prefix_pat = re.compile(r"\{")
@@ -1424,6 +1482,12 @@ class _Parser:
         # Offset alignment item?
         item = self._try_parse_align_offset()
 
+        if item is not None:
+            return item
+
+        # Filling item?
+        item = self._try_parse_fill_until()
+
         if item is not None:
             return item
 
@@ -1835,7 +1899,7 @@ class _Gen:
     # `float` too.
     @staticmethod
     def _eval_item_expr(
-        item: Union[_FlNum, _Leb128Int, _VarAssign, _Rep, _Cond],
+        item: Union[_FlNum, _Leb128Int, _FillUntil, _VarAssign, _Rep, _Cond],
         state: _GenState,
         allow_float: bool = False,
     ):
@@ -2018,13 +2082,33 @@ class _Gen:
     def _handle_set_offset_item(self, item: _SetOffset, state: _GenState):
         state.offset = item.val
 
-    # Handles offset alignment item `item` (adds padding).
+    # Handles the offset alignment item `item` (adds padding).
     def _handle_align_offset_item(self, item: _AlignOffset, state: _GenState):
         init_offset = state.offset
         align_bytes = item.val // 8
         state.offset = (state.offset + align_bytes - 1) // align_bytes * align_bytes
         self._data += bytes([item.pad_val] * (state.offset - init_offset))
 
+    # Handles the filling item `item` (adds padding).
+    def _handle_fill_until_item(self, item: _FillUntil, state: _GenState):
+        # Compute the new offset
+        new_offset = _Gen._eval_item_expr(item, state)
+
+        # Validate the new offset
+        if new_offset < state.offset:
+            _raise_error_for_item(
+                "Invalid expression `{}`: new offset {:,} is less than current offset {:,}".format(
+                    item.expr_str, new_offset, state.offset
+                ),
+                item,
+            )
+
+        # Fill
+        self._data += bytes([item.pad_val] * (new_offset - state.offset))
+
+        # Update offset
+        state.offset = new_offset
+
     # Handles the label item `item`.
     def _handle_label_item(self, item: _Label, state: _GenState):
         state.labels[item.name] = state.offset
@@ -2125,6 +2209,7 @@ class _Gen:
             _AlignOffset: self._handle_align_offset_item,
             _Byte: self._handle_byte_item,
             _Cond: self._handle_cond_item,
+            _FillUntil: self._handle_fill_until_item,
             _FlNum: self._handle_fl_num_item,
             _Group: self._handle_group_item,
             _Label: self._handle_label_item,
index 556430f422276510e416daca8e2676e3b8e50008..bcf5751ae9ec6ecf33e8ed18939065a8936f0ba1 100644 (file)
@@ -23,7 +23,7 @@
 
 [tool.poetry]
 name = 'normand'
-version = '0.11.0'
+version = '0.12.0'
 description = 'Text-to-binary processor with its own language'
 license = 'MIT'
 authors = ['Philippe Proulx <eeppeliteloop@gmail.com>']
index d31aa48ea07c42a7b4d782d25d83ba53d0d367fb..3a87a9a62849fee7c4e6bc6cf3933936c833aeae 100644 (file)
@@ -1,4 +1,4 @@
 88 44 @16~-45 "meow"
 @ 56 ~ 127 $132
 ---
-1:11 - Expecting a byte value
+1:11 - Expecting a positive constant integer (byte value)
index fa9458e069ff17979d2cee516ef5ebb2d0a38b25..911e1a2bc9bafda20d1c6f4eccccbd1f3a8e487c 100644 (file)
@@ -1,4 +1,4 @@
 88 44 @16~yo "meow"
 @ 56 ~ 127 $132
 ---
-1:11 - Expecting a byte value
+1:11 - Expecting a positive constant integer (byte value)
diff --git a/tests/fail-fill-before.nt b/tests/fail-fill-before.nt
new file mode 100644 (file)
index 0000000..3788b2d
--- /dev/null
@@ -0,0 +1,3 @@
+aa bb cc +2 "zoom"
+---
+1:10 - Invalid expression `2`: new offset 2 is less than current offset 3
diff --git a/tests/fail-fill-inval-pad-val-neg.nt b/tests/fail-fill-inval-pad-val-neg.nt
new file mode 100644 (file)
index 0000000..a064bc8
--- /dev/null
@@ -0,0 +1,4 @@
+88 44 +16~-45 "meow"
++ 100 ~ 127 $132
+---
+1:11 - Expecting a positive constant integer (byte value)
diff --git a/tests/fail-fill-inval-pad-val-str.nt b/tests/fail-fill-inval-pad-val-str.nt
new file mode 100644 (file)
index 0000000..e21acf5
--- /dev/null
@@ -0,0 +1,4 @@
+88 44 +16~yo "meow"
++ 56 ~ 127 $132
+---
+1:11 - Expecting a positive constant integer (byte value)
diff --git a/tests/fail-fill-inval-val-neg.nt b/tests/fail-fill-inval-val-neg.nt
new file mode 100644 (file)
index 0000000..ac01c79
--- /dev/null
@@ -0,0 +1,4 @@
+88 44 +-16 "meow"
++ 56 ~ 127 $132
+---
+1:8 - Expecting a positive constant integer
diff --git a/tests/fail-fill-inval-val-str.nt b/tests/fail-fill-inval-val-str.nt
new file mode 100644 (file)
index 0000000..b7432f3
--- /dev/null
@@ -0,0 +1,4 @@
+88 44 +"yo" "meow"
++ 56 ~ 127 $132
+---
+1:8 - Expecting a positive constant integer, a name, or `{`
diff --git a/tests/fail-fill-pad-val-out-of-range.nt b/tests/fail-fill-pad-val-out-of-range.nt
new file mode 100644 (file)
index 0000000..e7dd14d
--- /dev/null
@@ -0,0 +1,4 @@
+88 44 +16~256 "meow"
++ 56 ~ 127 $132
+---
+1:11 - Invalid padding byte value 256
diff --git a/tests/fail-fill-unknown-name-1.nt b/tests/fail-fill-unknown-name-1.nt
new file mode 100644 (file)
index 0000000..3fe6b2a
--- /dev/null
@@ -0,0 +1,4 @@
+{zoom = 32}
+aa bb cc +yo "zoom"
+---
+2:10 - Illegal (unknown or unreachable) variable/label name `yo` in expression `yo`; the legal names are {`ICITTE`, `zoom`}
diff --git a/tests/fail-fill-unknown-name-2.nt b/tests/fail-fill-unknown-name-2.nt
new file mode 100644 (file)
index 0000000..e691272
--- /dev/null
@@ -0,0 +1,5 @@
+{zoom = 32}
+aa bb cc +yo "zoom"
+{yo = 0x99}
+---
+2:10 - Illegal (unknown or unreachable) variable/label name `yo` in expression `yo`; the legal names are {`ICITTE`, `zoom`}
index 2e39488d6e535eb75c6591bebfdf81571b2084cc..ff490234d3ed163695ebaaf11326d1d694be28ee 100644 (file)
@@ -1,6 +1,6 @@
-%1/01\0?1&0:1;0 %.0,1+0[1]0_1=0|1 %1111-0000
+%1/01\0?1&0:1;0 %.0,10[1]0_1=0|1 %1111-0000
 % 1 0 / 1 \ 0 ? 1 & 0 : 1 ; 0
-% . 0 , 1 + 0 [ 1 ] 0 _ 1 = 0 | 1
+% . 0 , 1  0 [ 1 ] 0 _ 1 = 0 | 1
 % 1111 - 0000
 ---
 aa 55 f0
index 0b33c27766717219ea9cd53f50a9fe4f4a878d09..bcc7db9f4bfb0b723856afc43193e24ecac0787a 100644 (file)
@@ -1,3 +1,3 @@
-(012/3\4?5&6:7;8.9,a+b[c]d_e=f|0-1(/\?&:;.,+[]_=|-))
+(012/3\4?5&6:7;8.9,ab[c]d_e=f|0-1(/\?&:;.,[]_=|-))
 ---
 01 23 45 67 89 ab cd ef 01
index 4c3b99002d3ec10e4327ce2e59e4ee917de08373..c7706911e583c08700f32861170184934a50caeb 100644 (file)
@@ -1,6 +1,6 @@
-/ \ ? & : ; . , [ ] _ = | -
-012/3\4?5&6:7;8.9,a+b[c]d_e=f|0-1
-0 1 2 / 3 \ 4 ? 5 & 6 : 7 ; 8 . 9 , a b [ c ] d_e = f | 0 - 1
+/ \ ? & : ; . , [ ] _ = | -
+012/3\4?5&6:7;8.9,ab[c]d_e=f|0-1
+0 1 2 / 3 \ 4 ? 5 & 6 : 7 ; 8 . 9 , a b [ c ] d_e = f | 0 - 1
 ---
 01 23 45 67 89 ab cd ef 01
 01 23 45 67 89 ab cd ef 01
index 08dc0c39d1b2d54f4fe846d4dc9fbc41f1322712..98c94bcb6794609dfe352ae40a0cdd5932170ded 100644 (file)
@@ -1,4 +1,4 @@
 # repetition
-ff/\?&:;.,+[]_=|-*/\?&:;.,+[]_=|-5
+ff/\?&:;.,[]_=|-*/\?&:;.,[]_=|-5
 ---
 ff ff ff ff ff
diff --git a/tests/pass-fill-cur-offset.nt b/tests/pass-fill-cur-offset.nt
new file mode 100644 (file)
index 0000000..c0f9a96
--- /dev/null
@@ -0,0 +1,3 @@
+aa bb cc +{ICITTE} {ICITTE:8}
+---
+aa bb cc 03
diff --git a/tests/pass-fill-name.nt b/tests/pass-fill-name.nt
new file mode 100644 (file)
index 0000000..aeecbd5
--- /dev/null
@@ -0,0 +1,5 @@
+aa {zoom = 10} bb cc +zoom {ICITTE:8}
+---
+aa bb cc 00 00
+00 00 00 00 00
+0a
diff --git a/tests/pass-fill-pad-val.nt b/tests/pass-fill-pad-val.nt
new file mode 100644 (file)
index 0000000..ba43a7f
--- /dev/null
@@ -0,0 +1,7 @@
+aa {zoom = 10} bb cc +zoom~0xcc {ICITTE:8}
++ 15 ~ 255 {ICITTE:8}
+---
+aa bb cc cc cc
+cc cc cc cc cc
+0a ff ff ff ff
+0f
diff --git a/tests/pass-fill.nt b/tests/pass-fill.nt
new file mode 100644 (file)
index 0000000..15e7a94
--- /dev/null
@@ -0,0 +1,5 @@
+aa bb cc +10 {ICITTE:8}
+---
+aa bb cc 00 00
+00 00 00 00 00
+0a
diff --git a/tests/pass-readme-intro-fill.nt b/tests/pass-readme-intro-fill.nt
new file mode 100644 (file)
index 0000000..1ef55a2
--- /dev/null
@@ -0,0 +1,23 @@
+{le}
+{0xdeadbeef:32}
+{-1993:16}
+{9:16}
++0x40
+{ICITTE:8}
+"meow mix"
++200~0xff
+{ICITTE:8}
+---
+ef be ad de 37 f8 09 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+40 6d 65 6f 77 20 6d 69 78 ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+ff ff ff ff ff ff ff ff c8
diff --git a/tests/pass-readme-learn-fill-1.nt b/tests/pass-readme-learn-fill-1.nt
new file mode 100644 (file)
index 0000000..6fb6b3f
--- /dev/null
@@ -0,0 +1,9 @@
+aa bb cc dd
++0x40
+"hello world"
+---
+aa bb cc dd 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+68 65 6c 6c 6f 20 77 6f 72 6c 64
diff --git a/tests/pass-readme-learn-fill-2.nt b/tests/pass-readme-learn-fill-2.nt
new file mode 100644 (file)
index 0000000..fed70e9
--- /dev/null
@@ -0,0 +1,25 @@
+!macro part(iter, fill)
+  <0> "particular security " {ord('0') + iter : 8} +fill~0x80
+!end
+
+{iter = 1}
+
+!repeat 5
+  m:part(iter, {32 + 4 * iter})
+  {iter = iter + 1}
+!end
+---
+70 61 72 74 69 63 75 6c 61 72 20 73 65 63 75 72
+69 74 79 20 31 80 80 80 80 80 80 80 80 80 80 80
+80 80 80 80 70 61 72 74 69 63 75 6c 61 72 20 73
+65 63 75 72 69 74 79 20 32 80 80 80 80 80 80 80
+80 80 80 80 80 80 80 80 80 80 80 80 70 61 72 74
+69 63 75 6c 61 72 20 73 65 63 75 72 69 74 79 20
+33 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
+80 80 80 80 80 80 80 80 70 61 72 74 69 63 75 6c
+61 72 20 73 65 63 75 72 69 74 79 20 34 80 80 80
+80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
+80 80 80 80 80 80 80 80 70 61 72 74 69 63 75 6c
+61 72 20 73 65 63 75 72 69 74 79 20 35 80 80 80
+80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
+80 80 80 80 80 80 80 80 80 80 80 80
This page took 0.035647 seconds and 4 git commands to generate.