From: Philippe Proulx Date: Sun, 1 Oct 2023 02:13:50 +0000 (-0400) Subject: Add offset alignment support X-Git-Tag: v0.7.0 X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=676f618984ab41126985277a7513260af9b10b61;p=normand.git Add offset alignment support This patch adds a new item which is meant to update the current offset so that it satisfies a given alignment. The form is: @32 @64~39 @16~0xcc What follows `@` is the alignment value in bits (any multiple of eight greater than zero). The optional part starting with `~` is the value of the padding bytes to add to satisfy the alignment requirement. See the new tests and the `README.adoc` examples to learn more. `@` used to be an insignificant symbol, but it's not anymore (not consider as a comment). Also fixing missing repr() calls at some places. Change-Id: I9f5ac1da6988c060391640bf2784567a76e9fc48 Signed-off-by: Philippe Proulx --- diff --git a/README.adoc b/README.adoc index 44e62c5..954f354 100644 --- a/README.adoc +++ b/README.adoc @@ -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.6, meaning both the Normand +WARNING: This version of Normand is 0.7, meaning both the Normand language and the module/CLI interface aren't stable. ifdef::env-github[] @@ -192,6 +192,25 @@ aa bb bb bb bb bb cc 79 65 61 68 00 79 65 61 68 ┆ •••••••yeah 00 79 65 61 68 00 79 65 61 68 00 79 65 61 68 00 ┆ •yeah•yeah•yeah• ---- +Alignment:: ++ +Input: ++ +---- +{be} + + {199:32} +@64 {43:64} +@16 {-123:16} +@32~255 {5584:32} +---- ++ +Output: ++ +---- +00 00 00 c7 00 00 00 00 00 00 00 00 00 00 00 2b +ff 85 ff ff 00 00 15 d0 +---- Multilevel grouping:: + @@ -285,7 +304,10 @@ number>>, <>, and Each generated byte increments the current offset. A <> may change the -current offset. +current offset without generating data. + +An <> generates +padding bytes to make the current offset satisfy a given alignment. |`init_offset` parameter of the `parse()` function. |`--offset` option. @@ -329,6 +351,8 @@ The available items are: * A <>. +* A <>. + * A <>, that is, a named constant holding the current offset. + @@ -358,7 +382,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 @@ -784,6 +808,82 @@ aa bb cc dd ee ff 11 22 33 44 55 04 0f ┆ •••••••"3DU•• ---- ==== +=== Current offset alignment + +An _current offset alignment_ represents zero or more padding bytes to +make the <> meet a given +https://en.wikipedia.org/wiki/Data_structure_alignment[alignment] value. + +More specifically, for an alignment value of{nbsp}__**N**__{nbsp}bits, +a current offset alignment represents the required padding bytes until +the current offset is a multiple of __**N**__{nbsp}/{nbsp}8. + +A current offset alignment is: + +. The `@` prefix. + +. A positive integer (hexadecimal starting with `0x` or `0X` accepted) + which is the alignment value in _bits_. ++ +This value must be greater than zero and a multiple of{nbsp}8. + +. **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 align the + <>. +-- ++ +Without this section, the padding byte value is zero. + +==== +Input: + +---- +11 22 (@32 aa bb cc) * 3 +---- + +Output: + +---- +11 22 00 00 aa bb cc 00 aa bb cc 00 aa bb cc +---- +==== + +==== +Input: + +---- +{le} +77 88 +@32~0xcc {-893.5:32} +@128~0x55 "meow" +---- + +Output: + +---- +77 88 cc cc 00 60 5f c4 55 55 55 55 55 55 55 55 ┆ w••••`_•UUUUUUUU +6d 65 6f 77 ┆ meow +---- +==== + +==== +Input: + +---- +aa bb cc <29> @64~255 "zoom" +---- + +Output: + +---- +aa bb cc ff ff ff 7a 6f 6f 6d ┆ ••••••zoom +---- +==== + === Label A _label_ associates a name to the <>. @@ -927,7 +1027,13 @@ of times. A repetition is: -. Any item. +. Any item except: + +** A <>. +** A <>. +** A <>. +** A <>. +** A <>. . The ``pass:[*]`` character. diff --git a/normand/normand.py b/normand/normand.py index 1824e5d..c3c76ad 100644 --- a/normand/normand.py +++ b/normand/normand.py @@ -30,7 +30,7 @@ # Upstream repository: . __author__ = "Philippe Proulx" -__version__ = "0.6.2" +__version__ = "0.7.0" __all__ = [ "ByteOrder", "parse", @@ -54,7 +54,6 @@ from typing import ( Set, Dict, List, - Tuple, Union, Pattern, Callable, @@ -133,7 +132,7 @@ class _Byte(_ScalarItem, _RepableItem): return 1 def __repr__(self): - return "_Byte({}, {})".format(hex(self._val), self._text_loc) + return "_Byte({}, {})".format(hex(self._val), repr(self._text_loc)) # String. @@ -152,7 +151,7 @@ class _Str(_ScalarItem, _RepableItem): return len(self._data) def __repr__(self): - return "_Str({}, {})".format(repr(self._data), self._text_loc) + return "_Str({}, {})".format(repr(self._data), repr(self._text_loc)) # Byte order. @@ -176,7 +175,7 @@ class _SetBo(_Item): return self._bo def __repr__(self): - return "_SetBo({}, {})".format(repr(self._bo), self._text_loc) + return "_SetBo({}, {})".format(repr(self._bo), repr(self._text_loc)) # Label. @@ -191,7 +190,7 @@ class _Label(_Item): return self._name def __repr__(self): - return "_Label({}, {})".format(repr(self._name), self._text_loc) + return "_Label({}, {})".format(repr(self._name), repr(self._text_loc)) # Offset setting. @@ -200,13 +199,36 @@ class _SetOffset(_Item): super().__init__(text_loc) self._val = val - # Offset value. + # Offset value (bytes). @property def val(self): return self._val def __repr__(self): - return "_SetOffset({}, {})".format(repr(self._val), self._text_loc) + return "_SetOffset({}, {})".format(repr(self._val), repr(self._text_loc)) + + +# Offset alignment. +class _AlignOffset(_Item): + def __init__(self, val: int, pad_val: int, text_loc: TextLoc): + super().__init__(text_loc) + self._val = val + self._pad_val = pad_val + + # Alignment value (bits). + @property + def val(self): + return self._val + + # Padding byte value. + @property + def pad_val(self): + return self._pad_val + + def __repr__(self): + return "_AlignOffset({}, {}, {})".format( + repr(self._val), repr(self._pad_val), repr(self._text_loc) + ) # Mixin of containing an AST expression and its string. @@ -242,7 +264,10 @@ class _VarAssign(_Item, _ExprMixin): def __repr__(self): return "_VarAssign({}, {}, {}, {})".format( - repr(self._name), repr(self._expr_str), repr(self._expr), self._text_loc + repr(self._name), + repr(self._expr_str), + repr(self._expr), + repr(self._text_loc), ) @@ -266,7 +291,10 @@ class _FlNum(_ScalarItem, _RepableItem, _ExprMixin): def __repr__(self): return "_FlNum({}, {}, {}, {})".format( - repr(self._expr_str), repr(self._expr), repr(self._len), self._text_loc + repr(self._expr_str), + repr(self._expr), + repr(self._len), + repr(self._text_loc), ) @@ -281,7 +309,7 @@ class _Leb128Int(_Item, _RepableItem, _ExprMixin): self.__class__.__name__, repr(self._expr_str), repr(self._expr), - self._text_loc, + repr(self._text_loc), ) @@ -307,7 +335,7 @@ class _Group(_Item, _RepableItem): return self._items def __repr__(self): - return "_Group({}, {})".format(repr(self._items), self._text_loc) + return "_Group({}, {})".format(repr(self._items), repr(self._text_loc)) # Repetition item. @@ -326,7 +354,10 @@ class _Rep(_Item, _ExprMixin): def __repr__(self): return "_Rep({}, {}, {}, {})".format( - repr(self._item), repr(self._expr_str), repr(self._expr), self._text_loc + repr(self._item), + repr(self._expr_str), + repr(self._expr), + repr(self._text_loc), ) @@ -454,7 +485,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 @@ -874,6 +905,57 @@ class _Parser: self._expect_pat(self._label_set_offset_suffix_pat, "Expecting `>`") return item + # Patterns for _try_parse_align_offset() + _align_offset_prefix_pat = re.compile(r"@\s*") + _align_offset_val_pat = re.compile(r"(\d+)\s*") + _align_offset_pad_val_prefix_pat = re.compile(r"~\s*") + + # Tries to parse an offset alignment, returning an offset alignment + # item on success. + def _try_parse_align_offset(self): + begin_text_loc = self._text_loc + + # Match prefix + if self._try_parse_pat(self._align_offset_prefix_pat) is None: + # No match + return + + align_text_loc = self._text_loc + m = self._expect_pat( + self._align_offset_val_pat, + "Expecting an alignment (positive multiple of eight bits)", + ) + + # Validate alignment + val = int(m.group(1)) + + if val <= 0 or (val % 8) != 0: + _raise_error( + "Invalid alignment value {} (not a positive multiple of eight)".format( + val + ), + align_text_loc, + ) + + # Padding value? + pad_val = 0 + + if self._try_parse_pat(self._align_offset_pad_val_prefix_pat) is not None: + pad_val_text_loc = self._text_loc + m = self._expect_pat(self._pos_const_int_pat, "Expecting a 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 item + return _AlignOffset(val, pad_val, begin_text_loc) + # Tries to parse a base item (anything except a repetition), # returning it on success. def _try_parse_base_item(self): @@ -898,6 +980,12 @@ class _Parser: # Label or offset setting item? item = self._try_parse_label_or_set_offset() + if item is not None: + return item + + # Offset alignment item? + item = self._try_parse_align_offset() + if item is not None: return item @@ -1396,6 +1484,12 @@ class _Gen: # Seven bits per byte return math.ceil(bits / 7) + # Returns the offset `offset` aligned according to `item`. + @staticmethod + def _align_offset(offset: int, item: _AlignOffset): + align_bytes = item.val // 8 + return (offset + align_bytes - 1) // align_bytes * align_bytes + # Computes the effective value for each repetition and LEB128 # integer instance, filling `instance_vals` (if not `None`) and # returning `instance_vals`. @@ -1440,6 +1534,8 @@ class _Gen: ) elif type(item) is _SetOffset: state.offset = item.val + elif type(item) is _AlignOffset: + state.offset = _Gen._align_offset(state.offset, item) elif isinstance(item, _Leb128Int): # Evaluate the expression val = _Gen._eval_item_expr(item, state, True) @@ -1489,49 +1585,64 @@ class _Gen: return instance_vals - def _zero_item_size(self, item: _Item, next_vl_instance: int): - return 0, next_vl_instance + def _update_offset_noop(self, item: _Item, state: _GenState, next_vl_instance: int): + return next_vl_instance - def _scalar_item_size(self, item: _ScalarItem, next_vl_instance: int): - return item.size, next_vl_instance + def _dry_handle_scalar_item( + self, item: _ScalarItem, state: _GenState, next_vl_instance: int + ): + state.offset += item.size + return next_vl_instance - def _leb128_int_item_size(self, item: _Leb128Int, next_vl_instance: int): + def _dry_handle_leb128_int_item( + self, item: _Leb128Int, state: _GenState, next_vl_instance: int + ): # Get the value from `self._vl_instance_vals` _before_ # incrementing `next_vl_instance` to honor the order of # _compute_vl_instance_vals(). - return ( - self._leb128_size_for_val( - self._vl_instance_vals[next_vl_instance], type(item) is _SLeb128Int - ), - next_vl_instance + 1, + state.offset += self._leb128_size_for_val( + self._vl_instance_vals[next_vl_instance], type(item) is _SLeb128Int ) - def _group_item_size(self, item: _Group, next_vl_instance: int): - size = 0 + return next_vl_instance + 1 + def _dry_handle_group_item( + self, item: _Group, state: _GenState, next_vl_instance: int + ): for subitem in item.items: - subitem_size, next_vl_instance = self._item_size(subitem, next_vl_instance) - size += subitem_size + next_vl_instance = self._dry_handle_item(subitem, state, next_vl_instance) - return size, next_vl_instance + return next_vl_instance - def _rep_item_size(self, item: _Rep, next_vl_instance: int): + def _dry_handle_rep_item(self, item: _Rep, state: _GenState, next_vl_instance: int): # Get the value from `self._vl_instance_vals` _before_ # incrementing `next_vl_instance` to honor the order of # _compute_vl_instance_vals(). mul = self._vl_instance_vals[next_vl_instance] next_vl_instance += 1 - size = 0 for _ in range(mul): - iter_size, next_vl_instance = self._item_size(item.item, next_vl_instance) - size += iter_size + next_vl_instance = self._dry_handle_item(item.item, state, next_vl_instance) - return size, next_vl_instance + return next_vl_instance - # Returns the size of `item` and the new next repetition instance. - def _item_size(self, item: _Item, next_vl_instance: int): - return self._item_size_funcs[type(item)](item, next_vl_instance) + def _dry_handle_align_offset_item( + self, item: _AlignOffset, state: _GenState, next_vl_instance: int + ): + state.offset = self._align_offset(state.offset, item) + return next_vl_instance + + def _dry_handle_set_offset_item( + self, item: _SetOffset, state: _GenState, next_vl_instance: int + ): + state.offset = item.val + return next_vl_instance + + # Updates `state.offset` considering the generated data of `item`, + # without generating any, and returns the updated next + # variable-length item instance. + def _dry_handle_item(self, item: _Item, state: _GenState, next_vl_instance: int): + return self._dry_handle_item_funcs[type(item)](item, state, next_vl_instance) # Handles the byte item `item`. def _handle_byte_item(self, item: _Byte, state: _GenState, next_vl_instance: int): @@ -1677,23 +1788,19 @@ class _Gen: ): # Compute the values of the immediate (not nested) labels. Those # labels are reachable by any expression within the group. - offset = state.offset + tmp_state = _GenState({}, {}, state.offset, None) immediate_label_names = set() # type: Set[str] tmp_next_vl_instance = next_vl_instance for subitem in item.items: - if type(subitem) is _SetOffset: - # Update offset - offset = subitem.val - elif type(subitem) is _Label: + if type(subitem) is _Label: # New immediate label - state.labels[subitem.name] = offset + state.labels[subitem.name] = tmp_state.offset immediate_label_names.add(subitem.name) - subitem_size, tmp_next_vl_instance = self._item_size( - subitem, tmp_next_vl_instance + tmp_next_vl_instance = self._dry_handle_item( + subitem, tmp_state, tmp_next_vl_instance ) - offset += subitem_size # Handle each item now with the actual state for subitem in item.items: @@ -1727,6 +1834,15 @@ class _Gen: state.offset = item.val return next_vl_instance + # Handles offset alignment item `item` (adds padding). + def _handle_align_offset_item( + self, item: _AlignOffset, state: _GenState, next_vl_instance: int + ): + init_offset = state.offset + state.offset = self._align_offset(state.offset, item) + self._data += bytes([item.pad_val] * (state.offset - init_offset)) + return next_vl_instance + # Handles the label item `item`. def _handle_label_item(self, item: _Label, state: _GenState, next_vl_instance: int): return next_vl_instance @@ -1744,6 +1860,7 @@ class _Gen: # Item handlers self._item_handlers = { + _AlignOffset: self._handle_align_offset_item, _Byte: self._handle_byte_item, _FlNum: self._handle_fl_num_item, _Group: self._handle_group_item, @@ -1757,20 +1874,21 @@ class _Gen: _VarAssign: self._handle_var_assign_item, } # type: Dict[type, Callable[[Any, _GenState, int], int]] - # Item size getters - self._item_size_funcs = { - _Byte: self._scalar_item_size, - _FlNum: self._scalar_item_size, - _Group: self._group_item_size, - _Label: self._zero_item_size, - _Rep: self._rep_item_size, - _SetBo: self._zero_item_size, - _SetOffset: self._zero_item_size, - _SLeb128Int: self._leb128_int_item_size, - _Str: self._scalar_item_size, - _ULeb128Int: self._leb128_int_item_size, - _VarAssign: self._zero_item_size, - } # type: Dict[type, Callable[[Any, int], Tuple[int, int]]] + # Dry item handlers (only updates the state offset) + self._dry_handle_item_funcs = { + _AlignOffset: self._dry_handle_align_offset_item, + _Byte: self._dry_handle_scalar_item, + _FlNum: self._dry_handle_scalar_item, + _Group: self._dry_handle_group_item, + _Label: self._update_offset_noop, + _Rep: self._dry_handle_rep_item, + _SetBo: self._update_offset_noop, + _SetOffset: self._dry_handle_set_offset_item, + _SLeb128Int: self._dry_handle_leb128_int_item, + _Str: self._dry_handle_scalar_item, + _ULeb128Int: self._dry_handle_leb128_int_item, + _VarAssign: self._update_offset_noop, + } # type: Dict[type, Callable[[Any, _GenState, int], int]] # Handle the group item, _not_ removing the immediate labels # because the `labels` property offers them. diff --git a/pyproject.toml b/pyproject.toml index a68a799..f131ef7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ [tool.poetry] name = 'normand' -version = '0.6.2' +version = '0.7.0' description = 'Text-to-binary processor with its own language' license = 'MIT' authors = ['Philippe Proulx '] diff --git a/tests/fail-align-inval-pad-val-neg.nt b/tests/fail-align-inval-pad-val-neg.nt new file mode 100644 index 0000000..d31aa48 --- /dev/null +++ b/tests/fail-align-inval-pad-val-neg.nt @@ -0,0 +1,4 @@ +88 44 @16~-45 "meow" +@ 56 ~ 127 $132 +--- +1:11 - Expecting a byte value diff --git a/tests/fail-align-inval-pad-val-str.nt b/tests/fail-align-inval-pad-val-str.nt new file mode 100644 index 0000000..fa9458e --- /dev/null +++ b/tests/fail-align-inval-pad-val-str.nt @@ -0,0 +1,4 @@ +88 44 @16~yo "meow" +@ 56 ~ 127 $132 +--- +1:11 - Expecting a byte value diff --git a/tests/fail-align-inval-val-neg.nt b/tests/fail-align-inval-val-neg.nt new file mode 100644 index 0000000..b0c7136 --- /dev/null +++ b/tests/fail-align-inval-val-neg.nt @@ -0,0 +1,4 @@ +88 44 @-16 "meow" +@ 56 ~ 127 $132 +--- +1:8 - Expecting an alignment (positive multiple of eight bits) diff --git a/tests/fail-align-inval-val-str.nt b/tests/fail-align-inval-val-str.nt new file mode 100644 index 0000000..e9e8153 --- /dev/null +++ b/tests/fail-align-inval-val-str.nt @@ -0,0 +1,4 @@ +88 44 @yo "meow" +@ 56 ~ 127 $132 +--- +1:8 - Expecting an alignment (positive multiple of eight bits) diff --git a/tests/fail-align-pad-val-out-of-range.nt b/tests/fail-align-pad-val-out-of-range.nt new file mode 100644 index 0000000..8bd43c7 --- /dev/null +++ b/tests/fail-align-pad-val-out-of-range.nt @@ -0,0 +1,4 @@ +88 44 @16~256 "meow" +@ 56 ~ 127 $132 +--- +1:11 - Invalid padding byte value 256 diff --git a/tests/fail-align-zero.nt b/tests/fail-align-zero.nt new file mode 100644 index 0000000..2d1bfd8 --- /dev/null +++ b/tests/fail-align-zero.nt @@ -0,0 +1,3 @@ +aa bb cc @0 "zoom" +--- +1:11 - Invalid alignment value 0 (not a positive multiple of eight) diff --git a/tests/pass-align-256b.nt b/tests/pass-align-256b.nt new file mode 100644 index 0000000..071bdcd --- /dev/null +++ b/tests/pass-align-256b.nt @@ -0,0 +1,6 @@ +88 44 @256 "meow" +--- +88 44 +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 +6d 65 6f 77 diff --git a/tests/pass-align-32b.nt b/tests/pass-align-32b.nt new file mode 100644 index 0000000..8391ea0 --- /dev/null +++ b/tests/pass-align-32b.nt @@ -0,0 +1,5 @@ +88 44 @32 "meow" +--- +88 44 +00 00 +6d 65 6f 77 diff --git a/tests/pass-align-8b.nt b/tests/pass-align-8b.nt new file mode 100644 index 0000000..3acd71e --- /dev/null +++ b/tests/pass-align-8b.nt @@ -0,0 +1,4 @@ +88 44 @8 "meow" +--- +88 44 +6d 65 6f 77 diff --git a/tests/pass-align-pad-val.nt b/tests/pass-align-pad-val.nt new file mode 100644 index 0000000..339688b --- /dev/null +++ b/tests/pass-align-pad-val.nt @@ -0,0 +1,8 @@ +88 44 @32~0x99 "meow" +@ 56 ~ 127 $132 +--- +88 44 +99 99 +6d 65 6f 77 +7f 7f 7f 7f 7f 7f +84 diff --git a/tests/pass-comment-sym-bin-const.nt b/tests/pass-comment-sym-bin-const.nt index 9a43ce1..4e666f0 100644 --- a/tests/pass-comment-sym-bin-const.nt +++ b/tests/pass-comment-sym-bin-const.nt @@ -1,5 +1,5 @@ -%!1@0/1\0?1&0:1;0 %.0,1+0[1]0_1=0|1 %1111-0000 -% ! 1 @ 0 / 1 \ 0 ? 1 & 0 : 1 ; 0 +%!1/01\0?1&0:1;0 %.0,1+0[1]0_1=0|1 %1111-0000 +% 1! 0 / 1 \ 0 ? 1 & 0 : 1 ; 0 % . 0 , 1 + 0 [ 1 ] 0 _ 1 = 0 | 1 % 1111 - 0000 --- diff --git a/tests/pass-comment-sym-group.nt b/tests/pass-comment-sym-group.nt index 98fc0bb..7ceea98 100644 --- a/tests/pass-comment-sym-group.nt +++ b/tests/pass-comment-sym-group.nt @@ -1,3 +1,3 @@ -(0!1@2/3\4?5&6:7;8.9,a+b[c]d_e=f|0-1(!@/\?&:;.,+[]_=|-)) +(0!12/3\4?5&6:7;8.9,a+b[c]d_e=f|0-1(!/\?&:;.,+[]_=|-)) --- 01 23 45 67 89 ab cd ef 01 diff --git a/tests/pass-comment-sym-hex-const.nt b/tests/pass-comment-sym-hex-const.nt index d52cc95..3b6be9a 100644 --- a/tests/pass-comment-sym-hex-const.nt +++ b/tests/pass-comment-sym-hex-const.nt @@ -1,6 +1,6 @@ -! @ / \ ? & : ; . , + [ ] _ = | - -0!1@2/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 +! / \ ? & : ; . , + [ ] _ = | - +0!12/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 --- 01 23 45 67 89 ab cd ef 01 01 23 45 67 89 ab cd ef 01 diff --git a/tests/pass-comment-sym-rep.nt b/tests/pass-comment-sym-rep.nt index 9ae3242..b58bcc8 100644 --- a/tests/pass-comment-sym-rep.nt +++ b/tests/pass-comment-sym-rep.nt @@ -1,4 +1,4 @@ # repetition -ff!@/\?&:;.,+[]_=|-*!@/\?&:;.,+[]_=|-5 +ff!/\?&:;.,+[]_=|-*!/\?&:;.,+[]_=|-5 --- ff ff ff ff ff diff --git a/tests/pass-readme-intro-align.nt b/tests/pass-readme-intro-align.nt new file mode 100644 index 0000000..4ebc94d --- /dev/null +++ b/tests/pass-readme-intro-align.nt @@ -0,0 +1,9 @@ +{be} + + {199:32} +@64 {43:64} +@16 {-123:16} +@32~255 {5584:32} +--- +00 00 00 c7 00 00 00 00 00 00 00 00 00 00 00 2b +ff 85 ff ff 00 00 15 d0 diff --git a/tests/pass-readme-learn-align-1.nt b/tests/pass-readme-learn-align-1.nt new file mode 100644 index 0000000..4c0122e --- /dev/null +++ b/tests/pass-readme-learn-align-1.nt @@ -0,0 +1,3 @@ +11 22 (@32 aa bb cc) * 3 +--- +11 22 00 00 aa bb cc 00 aa bb cc 00 aa bb cc diff --git a/tests/pass-readme-learn-align-2.nt b/tests/pass-readme-learn-align-2.nt new file mode 100644 index 0000000..6af3b7f --- /dev/null +++ b/tests/pass-readme-learn-align-2.nt @@ -0,0 +1,7 @@ +{le} +77 88 +@32~0xcc {-893.5:32} +@128~0x55 "meow" +--- +77 88 cc cc 00 60 5f c4 55 55 55 55 55 55 55 55 +6d 65 6f 77 diff --git a/tests/pass-readme-learn-align-3.nt b/tests/pass-readme-learn-align-3.nt new file mode 100644 index 0000000..feac973 --- /dev/null +++ b/tests/pass-readme-learn-align-3.nt @@ -0,0 +1,3 @@ +aa bb cc <29> @64~255 "zoom" +--- +aa bb cc ff ff ff 7a 6f 6f 6d