1 // Show ToC at a specific location for a GitHub rendering
10 // This is to mimic what GitHub does so that anchors work in an offline
21 image::normand-logo.png[]
24 image:https://img.shields.io/pypi/v/normand.svg?label=Latest%20version[link="https://pypi.python.org/pypi/normand"]
27 _**Normand**_ is a text-to-binary processor with its own language.
29 This package offers both a portable {py3} module and a command-line
32 WARNING: This version of Normand is 0.19, meaning both the Normand
33 language and the module/CLI interface aren't stable.
36 // ToC location for a GitHub rendering
42 The purpose of Normand is to consume human-readable text representing
43 bytes and to produce the corresponding binary data.
47 Consider the following Normand input:
50 4f 55 32 bb $167 fe %10100111 a9 $-32
53 The generated nine bytes are:
56 4f 55 32 bb a7 fe a7 a9 e0
60 As you can see in the last example, the fundamental unit of the Normand
61 language is the _byte_. The order in which you list bytes will be the
62 order of the generated data.
64 The Normand language is more than simple lists of bytes, though. Its
67 Comments, including a bunch of insignificant symbols which may improve readability::
72 ff bb %1101:0010 # This is a comment
73 78 29 af $192 # This too # 99 $-80
74 fe80::6257:18ff:fea3:4229
76 10839636-5d65-4a68-8e6a-21608ddf7258
82 ff bb d2 78 29 af c0 99 b0 fe 80 62 57 18 ff fe
83 a3 42 29 60 57 18 a3 42 29 10 83 96 36 5d 65 4a
84 68 8e 6a 21 60 8d df 72 58
87 Hexadecimal, decimal, and binary byte constants::
92 aa bb $247 $-89 %0011_0010 %11.01= 10/10
107 u16le"stress\nverdict 🤣"
108 s:latin3{hex(ICITTE)}
114 68 65 6c 6c 6f 20 77 6f 72 6c 64 21 00 73 00 74 ┆ hello world!•s•t
115 00 72 00 65 00 73 00 73 00 0a 00 76 00 65 00 72 ┆ •r•e•s•s•••v•e•r
116 00 64 00 69 00 63 00 74 00 20 00 3e d8 23 dd 30 ┆ •d•i•c•t• •>•#•0
120 Labels: special variables holding the offset where they're defined::
123 <beg> b2 52 e3 bc 91 05
124 $100 $50 <chair> 33 9f fe
131 5e 65 {tower = 47} c6 7f f2 c4
132 44 {hurl = tower - 14} b5 {tower = hurl} 26 2d
135 The value of a variable assignment is the evaluation of a valid {py3}
136 expression which may include label and variable names.
138 Fixed-length number with a given length (8{nbsp}bits to 64{nbsp}bits) and byte order::
144 {be} 67 <lbl> 44 $178 {(end - lbl) * 8 + strength : 16} $99 <end>
152 67 44 b2 00 2c 63 37 f8 ff ff 7f bd c2 82 fb 21
156 The encoded number is the evaluation of a valid {py3} expression which
157 may include label and variable names.
159 https://en.wikipedia.org/wiki/LEB128[LEB128] integer::
164 aa bb cc {-1993 : sleb128} <meow> dd ee ff
165 {meow * 199 : uleb128}
171 aa bb cc b7 70 dd ee ff e3 07
174 The encoded integer is the evaluation of a valid {py3} expression which
175 may include label and variable names.
198 aa bb cc 66 6f 6f 66 69 67 68 74 66 6f 6f 66 69 ┆ •••foofightfoofi
199 67 68 74 66 6f 6f 62 61 72 66 6f 6f 62 61 72 ┆ ghtfoobarfoobar
207 aa bb * 5 cc <zoom> "yeah\0" * {zoom * 3}
217 aa bb bb bb bb bb cc 79 65 61 68 00 79 65 61 68 ┆ •••••••yeah•yeah
218 00 79 65 61 68 00 79 65 61 68 00 79 65 61 68 00 ┆ •yeah•yeah•yeah•
219 79 65 61 68 00 79 65 61 68 00 79 65 61 68 00 79 ┆ yeah•yeah•yeah•y
220 65 61 68 00 79 65 61 68 00 79 65 61 68 00 79 65 ┆ eah•yeah•yeah•ye
221 61 68 00 79 65 61 68 00 79 65 61 68 00 79 65 61 ┆ ah•yeah•yeah•yea
222 68 00 79 65 61 68 00 79 65 61 68 00 79 65 61 68 ┆ h•yeah•yeah•yeah
223 00 79 65 61 68 00 79 65 61 68 00 79 65 61 68 00 ┆ •yeah•yeah•yeah•
224 ff ee 6a 75 69 63 65 ff ee 6a 75 69 63 65 ff ee ┆ ••juice••juice••
225 6a 75 69 63 65 ┆ juice
244 00 00 00 c7 00 00 00 00 00 00 00 00 00 00 00 2b
245 ff 85 ff ff 00 00 15 d0
267 ef be ad de 37 f8 09 00 00 00 00 00 00 00 00 00 ┆ ••••7•••••••••••
268 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ┆ ••••••••••••••••
269 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ┆ ••••••••••••••••
270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ┆ ••••••••••••••••
271 40 6d 65 6f 77 20 6d 69 78 ff ff ff ff ff ff ff ┆ @meow mix•••••••
272 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ┆ ••••••••••••••••
273 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ┆ ••••••••••••••••
274 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ┆ ••••••••••••••••
275 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ┆ ••••••••••••••••
276 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ┆ ••••••••••••••••
277 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ┆ ••••••••••••••••
278 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ┆ ••••••••••••••••
279 ff ff ff ff ff ff ff ff c8 ┆ •••••••••
282 Multilevel grouping::
287 ff ((aa bb "zoom" cc) * 5) * 3 $-34 * 4
293 ff aa bb 7a 6f 6f 6d cc aa bb 7a 6f 6f 6d cc aa ┆ •••zoom•••zoom••
294 bb 7a 6f 6f 6d cc aa bb 7a 6f 6f 6d cc aa bb 7a ┆ •zoom•••zoom•••z
295 6f 6f 6d cc aa bb 7a 6f 6f 6d cc aa bb 7a 6f 6f ┆ oom•••zoom•••zoo
296 6d cc aa bb 7a 6f 6f 6d cc aa bb 7a 6f 6f 6d cc ┆ m•••zoom•••zoom•
297 aa bb 7a 6f 6f 6d cc aa bb 7a 6f 6f 6d cc aa bb ┆ ••zoom•••zoom•••
298 7a 6f 6f 6d cc aa bb 7a 6f 6f 6d cc aa bb 7a 6f ┆ zoom•••zoom•••zo
299 6f 6d cc aa bb 7a 6f 6f 6d cc de de de de ┆ om•••zoom•••••
309 !if world " world" !end
314 m:hello({ICITTE > 15 and ICITTE < 60})
321 ff ff ff ff 68 65 6c 6c 6f ff ff ff ff 68 65 6c ┆ ••••hello••••hel
322 6c 6f ff ff ff ff 68 65 6c 6c 6f 20 77 6f 72 6c ┆ lo••••hello worl
323 64 ff ff ff ff 68 65 6c 6c 6f 20 77 6f 72 6c 64 ┆ d••••hello world
324 ff ff ff ff 68 65 6c 6c 6f 20 77 6f 72 6c 64 ff ┆ ••••hello world•
325 ff ff ff 68 65 6c 6c 6f ff ff ff ff 68 65 6c 6c ┆ •••hello••••hell
326 6f ff ff ff ff 68 65 6c 6c 6f ff ff ff ff 68 65 ┆ o••••hello••••he
327 6c 6c 6f ff ff ff ff 68 65 6c 6c 6f ff ff ff ff ┆ llo••••hello••••
328 68 65 6c 6c 6f ff ff ff ff 68 65 6c 6c 6f ff ff ┆ hello••••hello••
329 ff ff 68 65 6c 6c 6f ff ff ff ff 68 65 6c 6c 6f ┆ ••hello••••hello
330 ff ff ff ff 68 65 6c 6c 6f ff ff ff ff 68 65 6c ┆ ••••hello••••hel
331 6c 6f ff ff ff ff 68 65 6c 6c 6f ┆ lo••••hello
334 Precise error reporting::
337 /tmp/meow.normand:10:24 - Expecting a bit (`0` or `1`).
341 /tmp/meow.normand:32:6 - Unexpected character `k`.
345 /tmp/meow.normand:24:19 - Illegal (unknown or unreachable) variable/label name `meow` in expression `(meow - 45) // 8`; the legal names are {`ICITTE`, `mix`, `zoom`}.
349 /tmp/meow.normand:32:19 - While expanding the macro `meow`:
350 /tmp/meow.normand:35:5 - While expanding the macro `zzz`:
351 /tmp/meow.normand:18:9 - Value 315 is outside the 8-bit range when evaluating expression `end - ICITTE`.
354 You can use Normand to track data source files in your favorite VCS
355 instead of raw binary files. The binary files that Normand generates can
356 be used to test file format decoding, including malformatted data, for
357 example, as well as for education.
359 See <<learn-normand>> to explore all the Normand features.
363 Normand requires Python ≥ 3.4.
368 $ python3 -m pip install --user normand
372 https://packaging.python.org/en/latest/tutorials/installing-packages/#installing-to-the-user-site[Installing to the User Site]
373 to learn more about a user site installation.
377 Normand has a single module file, `normand.py`, which you can copy as is
378 to your project to use it (both the <<python3-api,`normand.parse()`>>
379 function and the <<command-line-tool,command-line tool>>).
381 `normand.py` has _no external dependencies_, but if you're using
382 Python{nbsp}3.4, you'll need a local copy of the standard `typing`
388 The design goals of Normand are:
391 We're making sure `normand.py` works with Python{nbsp}≥{nbsp}3.4 and
392 doesn't have any external dependencies so that you may just copy the
393 module as is to your own project.
396 The most basic Normand input is a sequence of hexadecimal constants
397 (for example, `4e6f726d616e64`) which produce exactly what you'd
400 Most Normand features map to programming language concepts you already
401 know and understand: constant integers, literal strings, variables,
402 conditionals, repetitions/loops, and the rest.
404 Concise and readable input::
405 We could have chosen XML or YAML as the input format, but having a
406 DSL here makes a Normand input compact and easy to read, two
407 important traits when using Normand to write tests, for example.
409 Compare the following Normand input and some hypothetical XML
410 equivalent, for example:
412 .Actual normand input.
414 ff dd 01 ab $192 $-128 %1101:0011
421 # five times because xyz
423 "hello world " {iter:8}
431 .Hypothetical Normand XML input.
434 <?xml version="1.0" encoding="utf-8" ?>
436 <byte base="x" val="ff" />
437 <byte base="x" val="dd" />
438 <byte base="x" val="1" />
439 <byte base="x" val="ab" />
440 <byte base="d" val="192" />
441 <byte base="d" val="-128" />
442 <byte base="b" val="11010011" />
443 <fixed-len-num expr="end" len="8" />
444 <var-assign name="iter" expr="1" />
445 <cond expr="not something">
446 <!-- five times because xyz -->
448 <str>hello world </str>
449 <fixed-len-num expr="iter" len="8" />
450 <var-assign name="iter" expr="iter + 1" />
459 A Normand text input is a sequence of items which represent a sequence
462 [[state]] During the processing of items to data, Normand relies on a
467 |State variable |Description |Initial value: <<python3-api,{py3} API>> |Initial value: <<command-line-tool,CLI>>
469 |[[cur-offset]] Current offset
471 The current offset has an effect on the value of <<label,labels>> and of
472 the special `ICITTE` name in <<fixed-length-number,fixed-length
473 number>>, <<leb-128-integer,LEB128 integer>>, <<string,string>>,
474 <<filling,filling>>, <<variable-assignment,variable assignment>>,
475 <<conditional-block,conditional block>>, <<repetition-block,repetition
476 block>>, <<macro-expansion,macro expansion>>, and
477 <<post-item-repetition,post-item repetition>> expression evaluation.
479 Each generated byte increments the current offset.
481 A <<current-offset-setting,current offset setting>> may change the
482 current offset without generating data.
484 An <<current-offset-alignment,current offset alignment>> generates
485 padding bytes to make the current offset satisfy a given alignment.
486 |`init_offset` parameter of the `parse()` function.
489 |[[cur-bo]] Current byte order
491 The current byte order has an effect on the encoding of
492 <<fixed-length-number,fixed-length numbers>>.
494 A <<current-byte-order-setting,current byte order setting>> may change
495 the current byte order.
496 |`init_byte_order` parameter of the `parse()` function.
497 |`--byte-order` option.
500 |Mapping of label names to integral values.
501 |`init_labels` parameter of the `parse()` function.
502 |One or more `--label` options.
504 |<<variable-assignment,Variables>>
505 |Mapping of variable names to integral or floating point number values.
506 |`init_variables` parameter of the `parse()` function.
507 |One or more `--var` or `--var-str` options.
510 The available items are:
512 * A <<byte-constant,constant integer>> representing one or more
515 * A <<literal-string,literal string>> representing a constant sequence
516 of bytes encoding UTF-8, UTF-16, UTF-32, or Latin-1 to Latin-10 data.
518 * A <<current-byte-order-setting,current byte order setting>> (big or
521 * A <<fixed-length-number,fixed-length number>> (integer or
522 floating point) using the <<cur-bo,current byte order>> and of which
523 the value is the result of a {py3} expression.
525 * An <<leb128-integer,LEB128 integer>> of which the value is the result
526 of a {py3} expression.
528 * A <<string,string>> representing a sequence of bytes encoding UTF-8,
529 UTF-16, UTF-32, or Latin-1 to Latin-10 data, and of which the value is
530 the result of a {py3} expression.
532 * A <<current-offset-setting,current offset setting>>.
534 * A <<current-offset-alignment,current offset alignment>>.
536 * A <<filling,filling>>.
538 * A <<label,label>>, that is, a named constant holding the current
541 This is similar to an assembly label.
543 * A <<variable-assignment,variable assignment>> associating a name to
544 the integral result of an evaluated {py3} expression.
546 * A <<group,group>>, that is, a scoped sequence of items.
548 * A <<conditional-block,conditional block>>.
550 * A <<repetition-block,repetition block>>.
552 * A <<macro-definition-block,macro definition block>>.
554 * A <<macro-expansion,macro expansion>>.
556 Moreover, you can repeat many items above a constant or variable number
557 of times with the ``pass:[*]`` operator _after_ the item to repeat. This
558 is called a <<post-item-repetition,post-item repetition>>.
560 A Normand comment may exist:
562 * Between items, possibly within a group.
563 * Between the nibbles of a constant hexadecimal byte.
564 * Between the bits of a constant binary byte.
565 * Between the last item and the ``pass:[*]`` character of a post-item
566 repetition, and between that ``pass:[*]`` character and the following
567 number or expression.
568 * Between the ``!repeat``/``!r`` block opening and the following
569 constant integer, name, or expression of a repetition block.
570 * Between the ``!if`` block opening and the following name or expression
571 of a conditional block.
573 A comment is anything between two ``pass:[#]`` characters on the same
574 line, or from ``pass:[#]`` until the end of the line. Whitespaces and
575 the following symbol characters are also considered comments where a
579 / \ ? & : ; . , [ ] _ = | -
582 The latter serve to improve readability so that you may write, for
583 example, a MAC address or a UUID as is.
585 [[const-int]] Many items require a _constant integer_, possibly
586 negative, in which case it may start with `-` for a negative integer. A
587 positive constant integer is any of:
590 One or mode digits (`0` to `9`).
595 * The `0x` or `0X` prefix followed with one or more hexadecimal digits
596 (`0` to `9`, `a` to `f`, or `A` to `F`).
597 * One or more hexadecimal digits followed with the `h` or `H` suffix.
602 * The `0o` or `0O` prefix followed with one or more octal digits
604 * One or more octal digits followed with the `o`, `O`, `q`, or `Q`
610 * The `0b` or `0B` prefix followed with one or more bits (`0` or `1`).
611 * One or more bits followed with the `b` or `B` suffix.
613 You can test the examples of this section with the `normand`
614 <<command-line-tool,command-line tool>> as such:
617 $ normand file | hexdump -C
620 where `file` is the name of a file containing the Normand input.
624 A _byte constant_ represents one or more constant bytes.
629 Two consecutive hexadecimal digits representing a single byte.
632 One or more digits after the `$` prefix representing a single byte.
634 Binary form:: {empty}
637 . __**N**__ `%` prefixes (at least one).
639 The number of `%` characters is the number of subsequent expected bytes.
641 . __**N**__{nbsp}×{nbsp}8 bits (`0` or `1`).
662 $192 %1100/0011 $ -77
676 58f64689-6316-4d55-8a1a-04cada366172
677 fe80::6257:18ff:fea3:4229
683 58 f6 46 89 63 16 4d 55 8a 1a 04 ca da 36 61 72 ┆ X•F•c•MU•••••6ar
684 fe 80 62 57 18 ff fe a3 42 29 ┆ ••bW••••B)
692 %01110011 %01100001 %01101100 %01110101 %01110100
693 %%%1101:0010 11111111 #A#11 #B#00 #C#011 #D#1
699 73 61 6c 75 74 d2 ff c7 ┆ salut•••
705 A _literal string_ represents the encoded bytes of a literal string
706 using the UTF-8, UTF-16, UTF-32, or Latin-1 to Latin-10 encoding.
708 The string to encode isn't implicitly null-terminated: use `\0` at the
709 end of the string to add a null character.
713 . **Optional**: one of the following encodings instead of the default
769 . The ``pass:["]`` prefix.
771 . A sequence of zero or more characters, possibly containing escape
774 An escape sequence is the ``\`` character followed by one of:
780 `b`:: Backspace (U+0008)
781 `e`:: Escape (U+001B)
782 `f`:: Form feed (U+000C)
783 `n`:: End of line (U+000A)
784 `r`:: Carriage return (U+000D)
785 `t`:: Character tabulation (U+0009)
786 `v`:: Line tabulation (U+000B)
787 ``\``:: Reverse solidus (U+005C)
788 ``pass:["]``:: Quotation mark (U+0022)
791 . The ``pass:["]`` suffix.
797 "coucou tout le monde!"
803 63 6f 75 63 6f 75 20 74 6f 75 74 20 6c 65 20 6d ┆ coucou tout le m
804 6f 6e 64 65 21 ┆ onde!
812 u16le"I am not young enough to know everything."
818 49 00 20 00 61 00 6d 00 20 00 6e 00 6f 00 74 00 ┆ I• •a•m• •n•o•t•
819 20 00 79 00 6f 00 75 00 6e 00 67 00 20 00 65 00 ┆ •y•o•u•n•g• •e•
820 6e 00 6f 00 75 00 67 00 68 00 20 00 74 00 6f 00 ┆ n•o•u•g•h• •t•o•
821 20 00 6b 00 6e 00 6f 00 77 00 20 00 65 00 76 00 ┆ •k•n•o•w• •e•v•
822 65 00 72 00 79 00 74 00 68 00 69 00 6e 00 67 00 ┆ e•r•y•t•h•i•n•g•
831 s:u32be "\"illusion is the first\nof all pleasures\" 🦉"
837 00 00 00 22 00 00 00 69 00 00 00 6c 00 00 00 6c ┆ •••"•••i•••l•••l
838 00 00 00 75 00 00 00 73 00 00 00 69 00 00 00 6f ┆ •••u•••s•••i•••o
839 00 00 00 6e 00 00 00 20 00 00 00 69 00 00 00 73 ┆ •••n••• •••i•••s
840 00 00 00 20 00 00 00 74 00 00 00 68 00 00 00 65 ┆ ••• •••t•••h•••e
841 00 00 00 20 00 00 00 66 00 00 00 69 00 00 00 72 ┆ ••• •••f•••i•••r
842 00 00 00 73 00 00 00 74 00 00 00 0a 00 00 00 6f ┆ •••s•••t•••••••o
843 00 00 00 66 00 00 00 20 00 00 00 61 00 00 00 6c ┆ •••f••• •••a•••l
844 00 00 00 6c 00 00 00 20 00 00 00 70 00 00 00 6c ┆ •••l••• •••p•••l
845 00 00 00 65 00 00 00 61 00 00 00 73 00 00 00 75 ┆ •••e•••a•••s•••u
846 00 00 00 72 00 00 00 65 00 00 00 73 00 00 00 22 ┆ •••r•••e•••s•••"
847 00 00 00 20 00 01 f9 89 ┆ ••• ••••
855 s:latin1 "Paul Piché"
861 50 61 75 6c 20 50 69 63 68 e9 ┆ Paul Pich•
865 === Current byte order setting
867 This special item sets the <<cur-bo,_current byte order_>>.
869 The two accepted forms are:
872 ``pass:[{be}]``:: Set the current byte order to big endian.
873 ``pass:[{le}]``:: Set the current byte order to little endian.
875 === Fixed-length number
877 A _fixed-length number_ represents a fixed number of bytes encoding
880 * An unsigned or signed integer (two's complement).
882 The available lengths are 8, 16, 24, 32, 40, 48, 56, and 64.
884 * A floating point number
885 (https://standards.ieee.org/standard/754-2008.html[IEEE{nbsp}754-2008]).
887 The available length are 32 (_binary32_) and 64 (_binary64_).
889 The value is the result of evaluating a {py3} expression using the
890 <<cur-bo,current byte order>>.
892 A fixed-length number is:
894 . The ``pass:[{]`` prefix.
896 . A valid {py3} expression.
898 For a fixed-length number at some source location{nbsp}__**L**__, this
899 expression may contain the name of any accessible <<label,label>> (not
900 within a nested group), including the name of a label defined
901 after{nbsp}__**L**__, as well as the name of any
902 <<variable-assignment,variable>> known at{nbsp}__**L**__.
904 The value of the special name `ICITTE` (`int` type) in this expression
905 is the <<cur-offset,current offset>> (before encoding the number).
909 . An encoding length in bits amongst:
912 The expression evaluates to an `int` or `bool` value::
913 `8`, `16`, `24`, `32`, `40`, `48`, `56`, and `64`.
915 NOTE: Normand automatically converts a `bool` value to `int`.
917 The expression evaluates to a `float` value::
944 # String length in bits
945 {8 * (str_end - str_beg) : 16}
956 00 60 68 65 6c 6c 6f 20 77 6f 72 6c 64 21 ┆ •`hello world!
964 {20 - ICITTE : 8} * 10
970 14 13 12 11 10 0f 0e 0d 0c 0b
991 An _LEB128 integer_ represents a variable number of bytes encoding an
992 unsigned or signed integer which is the result of evaluating a {py3}
993 expression following the https://en.wikipedia.org/wiki/LEB128[LEB128]
996 An LEB128 integer is:
998 . The ``pass:[{]`` prefix.
1000 . A valid {py3} expression of which the evaluation result type
1001 is `int` or `bool` (automatically converted to `int`).
1003 For an LEB128 integer at some source location{nbsp}__**L**__, this
1004 expression may contain:
1007 * The name of any <<label,label>> defined before{nbsp}__**L**__
1008 which isn't within a nested group.
1009 * The name of any <<variable-assignment,variable>> known
1013 The value of the special name `ICITTE` (`int` type) in this expression
1014 is the <<cur-offset,current offset>> (before encoding the integer).
1016 . The `:` character.
1022 `uleb128`:: Use the unsigned LEB128 format.
1023 `sleb128`:: Use the signed LEB128 format.
1049 {-981238311 + (meow * -23) : sleb128}
1056 aa bb cc dd ee ff fd fa 8d ac 7c 68 65 6c 6c 6f ┆ ••••••••••|hello
1062 A _string_ represents a variable number of bytes encoding a string which
1063 is the result of evaluating a {py3} expression using the UTF-8, UTF-16,
1064 UTF-32, or Latin-1 to Latin-10 encoding.
1066 A string has two possible forms:
1068 Encoding prefix form:: {empty}
1070 . An encoding amongst:
1125 . The ``pass:[{]`` prefix.
1127 . A valid {py3} expression of which the evaluation result type
1128 is `bool`, `int`, `float`, or `str` (the first three automatically
1129 converted to `str`).
1131 For a string at some source location{nbsp}__**L**__, this expression may
1135 * The name of any <<label,label>> defined before{nbsp}__**L**__
1136 which isn't within a nested group.
1137 * The name of any <<variable-assignment,variable>> known
1141 The value of the special name `ICITTE` (`int` type) in this expression
1142 is the <<cur-offset,current offset>> (before encoding the string).
1146 Encoding suffix form:: {empty}
1148 . The ``pass:[{]`` prefix.
1150 . A valid {py3} expression of which the evaluation result type
1151 is `bool`, `int`, `float`, or `str` (the first three automatically
1152 converted to `str`).
1154 For a string at some source location{nbsp}__**L**__, this expression may
1158 * The name of any <<label,label>> defined before{nbsp}__**L**__
1159 which isn't within a nested group.
1160 * The name of any <<variable-assignment,variable>> known
1164 The value of the special name `ICITTE` (`int` type) in this expression
1165 is the <<cur-offset,current offset>> (before encoding the string).
1167 . The `:` character.
1169 . A string encoding amongst:
1236 31 20 32 20 33 20 34 20 35 20 36 20 37 20 38 20 ┆ 1 2 3 4 5 6 7 8
1237 39 20 31 30 20 ┆ 9 10
1245 {meow = 'salut jérémie'}
1246 {meow.upper() : s:latin1}
1252 53 41 4c 55 54 20 4a c9 52 c9 4d 49 45 ┆ SALUT J•R•MIE
1256 === Current offset setting
1258 This special item sets the <<cur-offset,_current offset_>>.
1260 A current offset setting is:
1264 . A <<const-int,positive constant integer>> which is the new current
1274 <0x61> {ICITTE : 8} * 8
1280 00 01 02 03 04 05 06 07 61 62 63 64 65 66 67 68 ┆ ••••••••abcdefgh
1288 aa bb cc dd <meow> ee ff
1289 <12> 11 22 33 <mix> 44 55
1290 {meow : 8} {mix : 8}
1296 aa bb cc dd ee ff 11 22 33 44 55 04 0f ┆ •••••••"3DU••
1300 === Current offset alignment
1302 A _current offset alignment_ represents zero or more padding bytes to
1303 make the <<cur-offset,current offset>> meet a given
1304 https://en.wikipedia.org/wiki/Data_structure_alignment[alignment] value.
1306 More specifically, for an alignment value of{nbsp}__**N**__{nbsp}bits,
1307 a current offset alignment represents the required padding bytes until
1308 the current offset is a multiple of __**N**__{nbsp}/{nbsp}8.
1310 A current offset alignment is:
1314 . A <<const-int,positive constant integer>> which is the alignment value
1317 This value must be greater than zero and a multiple of{nbsp}8.
1322 . The ``pass:[~]`` prefix.
1323 . A <<const-int,positive constant integer>> which is the value of the
1324 byte to use as padding to align the <<cur-offset,current offset>>.
1327 Without this section, the padding byte value is zero.
1333 11 22 (@32 aa bb cc) * 3
1339 11 22 00 00 aa bb cc 00 aa bb cc 00 aa bb cc
1349 @32~0xcc {-893.5:32}
1356 77 88 cc cc 00 60 5f c4 55 55 55 55 55 55 55 55 ┆ w••••`_•UUUUUUUU
1357 6d 65 6f 77 ┆ meow
1365 aa bb cc <29> @64~255 "zoom"
1371 aa bb cc ff ff ff 7a 6f 6f 6d ┆ ••••••zoom
1377 A _filling_ represents zero or more padding bytes to make the
1378 <<cur-offset,current offset>> reach a given value.
1382 . The ``pass:[+]`` prefix.
1386 ** A <<const-int,positive constant integer>> which is the current offset
1389 ** The ``pass:[{]`` prefix, a valid {py3} expression of which the
1390 evaluation result type is `int` or `bool` (automatically converted to
1391 `int`), and the ``pass:[}]`` suffix.
1393 For a filling at some source location{nbsp}__**L**__, this expression
1397 * The name of any <<label,label>> defined before{nbsp}__**L**__
1398 which isn't within a nested group.
1399 * The name of any <<variable-assignment,variable>> known
1403 The value of the special name `ICITTE` (`int` type) in this expression
1404 is the <<cur-offset,current offset>> (before handling the items to
1407 ** A valid {py3} name.
1409 For the name `__NAME__`, this is equivalent to the
1410 `pass:[{]__NAME__pass:[}]` form above.
1413 This value must be greater than or equal to the current offset where
1419 . The ``pass:[~]`` prefix.
1420 . A <<const-int,positive constant integer>> which is the value of the
1421 byte to use as padding to reach the current offset target.
1424 Without this section, the padding byte value is zero.
1438 aa bb cc dd 00 00 00 00 00 00 00 00 00 00 00 00 ┆ ••••••••••••••••
1439 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ┆ ••••••••••••••••
1440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ┆ ••••••••••••••••
1441 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ┆ ••••••••••••••••
1442 68 65 6c 6c 6f 20 77 6f 72 6c 64 ┆ hello world
1450 !macro part(iter, fill)
1451 <0> "particular security " {ord('0') + iter : 8} +fill~0x80
1457 m:part(iter, {32 + 4 * iter})
1465 70 61 72 74 69 63 75 6c 61 72 20 73 65 63 75 72 ┆ particular secur
1466 69 74 79 20 31 80 80 80 80 80 80 80 80 80 80 80 ┆ ity 1•••••••••••
1467 80 80 80 80 70 61 72 74 69 63 75 6c 61 72 20 73 ┆ ••••particular s
1468 65 63 75 72 69 74 79 20 32 80 80 80 80 80 80 80 ┆ ecurity 2•••••••
1469 80 80 80 80 80 80 80 80 80 80 80 80 70 61 72 74 ┆ ••••••••••••part
1470 69 63 75 6c 61 72 20 73 65 63 75 72 69 74 79 20 ┆ icular security
1471 33 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ┆ 3•••••••••••••••
1472 80 80 80 80 80 80 80 80 70 61 72 74 69 63 75 6c ┆ ••••••••particul
1473 61 72 20 73 65 63 75 72 69 74 79 20 34 80 80 80 ┆ ar security 4•••
1474 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ┆ ••••••••••••••••
1475 80 80 80 80 80 80 80 80 70 61 72 74 69 63 75 6c ┆ ••••••••particul
1476 61 72 20 73 65 63 75 72 69 74 79 20 35 80 80 80 ┆ ar security 5•••
1477 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 ┆ ••••••••••••••••
1478 80 80 80 80 80 80 80 80 80 80 80 80 ┆ ••••••••••••
1484 A _label_ associates a name to the <<cur-offset,current offset>>.
1486 All the labels of a whole Normand input must have unique names.
1488 A label must not share the name of a <<variable-assignment,variable>>
1495 . A valid {py3} name which is not `ICITTE`.
1499 === Variable assignment
1501 A _variable assignment_ associates a name to the integral result of an
1502 evaluated {py3} expression.
1504 A variable assignment is:
1506 . The ``pass:[{]`` prefix.
1508 . A valid {py3} name which is not `ICITTE`.
1510 . The `=` character.
1512 . A valid {py3} expression of which the evaluation result type is `int`,
1513 `float`, or `bool` (automatically converted to `int`), or `str`.
1515 For a variable assignment at some source location{nbsp}__**L**__, this
1516 expression may contain:
1519 * The name of any <<label,label>> defined before{nbsp}__**L**__
1520 which isn't within a nested group.
1521 * The name of any <<variable-assignment,variable>> known
1525 The value of the special name `ICITTE` (`int` type) in this expression
1526 is the <<cur-offset,current offset>>.
1535 {meow = 42} 11 22 {meow:8} 33 {meow = ICITTE + 17}
1536 "yooo" {meow + mix : 16}
1542 11 22 2a 33 79 6f 6f 6f 7a 00 ┆ •"*3yoooz•
1548 A _group_ is a scoped sequence of items.
1550 The <<label,labels>> within a group aren't visible outside of it.
1552 The main purpose of a group is to <<post-item-repetition,repeat>> more
1553 than a single item and to isolate labels.
1557 . The `(`, `!group`, or `!g` opening.
1559 . Zero or more items.
1561 . Depending on the group opening:
1576 ((aa bb cc) dd () ee) "leclerc"
1582 aa bb cc dd ee 6c 65 63 6c 65 72 63 ┆ •••••leclerc
1591 (aa bb cc) * 3 dd ee
1598 aa bb cc aa bb cc aa bb cc dd ee aa bb cc aa bb
1599 cc aa bb cc dd ee aa bb cc aa bb cc aa bb cc dd
1600 ee aa bb cc aa bb cc aa bb cc dd ee aa bb cc aa
1601 bb cc aa bb cc dd ee
1611 <str_beg> u16le"sébastien diaz" <str_end>
1612 {ICITTE - str_beg : 8}
1613 {(end - str_beg) * 5 : 24}
1621 73 00 e9 00 62 00 61 00 73 00 74 00 69 00 65 00 ┆ s•••b•a•s•t•i•e•
1622 6e 00 20 00 64 00 69 00 61 00 7a 00 1c 00 01 e0 ┆ n• •d•i•a•z•••••
1623 73 00 e9 00 62 00 61 00 73 00 74 00 69 00 65 00 ┆ s•••b•a•s•t•i•e•
1624 6e 00 20 00 64 00 69 00 61 00 7a 00 1c 00 01 40 ┆ n• •d•i•a•z••••@
1625 73 00 e9 00 62 00 61 00 73 00 74 00 69 00 65 00 ┆ s•••b•a•s•t•i•e•
1626 6e 00 20 00 64 00 69 00 61 00 7a 00 1c 00 00 a0 ┆ n• •d•i•a•z•••••
1630 === Conditional block
1632 A _conditional block_ represents either the bytes of zero or more items
1633 if some expression is true, or the bytes of zero or more other items if
1636 A conditional block is:
1638 . The `!if` opening.
1642 ** The ``pass:[{]`` prefix, a valid {py3} expression of which the
1643 evaluation result type is `int` or `bool` (automatically converted to
1644 `int`), and the ``pass:[}]`` suffix.
1646 For a conditional block at some source location{nbsp}__**L**__, this
1647 expression may contain:
1650 * The name of any <<label,label>> defined before{nbsp}__**L**__
1651 which isn't within a nested group.
1652 * The name of any <<variable-assignment,variable>> known
1656 The value of the special name `ICITTE` (`int` type) in this expression
1657 is the <<cur-offset,current offset>> (before handling the contained
1660 ** A valid {py3} name.
1662 For the name `__NAME__`, this is equivalent to the
1663 `pass:[{]__NAME__pass:[}]` form above.
1665 . Zero or more items to be handled when the condition is true.
1669 .. The `!else` opening.
1670 .. Zero or more items to be handled when the condition is false.
1672 . The `!end` closing.
1690 !if {at < rep_count} 20 !end
1699 6d 65 6f 77 20 7a 6f 6f 6d 20 6d 65 6f 77 20 7a ┆ meow zoom meow z
1700 6f 6f 6d 20 6d 65 6f 77 20 7a 6f 6f 6d 20 6d 65 ┆ oom meow zoom me
1701 6f 77 20 6d 69 78 20 6d 65 6f 77 20 6d 69 78 20 ┆ ow mix meow mix
1702 6d 65 6f 77 20 6d 69 78 20 6d 65 6f 77 20 6d 69 ┆ meow mix meow mi
1703 78 20 6d 65 6f 77 20 6d 69 78 20 6d 65 6f 77 20 ┆ x meow mix meow
1716 !if {str_end - str_beg > 10}
1724 6d 00 65 00 6f 00 77 00 20 00 6d 00 69 00 78 00 ┆ m•e•o•w• •m•i•x•
1725 21 00 20 42 49 47 ┆ !• BIG
1729 === Repetition block
1731 A _repetition block_ represents the bytes of one or more items repeated
1732 a given number of times.
1734 A repetition block is:
1736 . The `!repeat` or `!r` opening.
1740 ** A <<const-int,positive constant integer>> which is the number of
1741 times to repeat the previous item.
1743 ** The ``pass:[{]`` prefix, a valid {py3} expression of which the
1744 evaluation result type is `int` or `bool` (automatically converted to
1745 `int`), and the ``pass:[}]`` suffix.
1747 For a repetition block at some source location{nbsp}__**L**__, this
1748 expression may contain:
1751 * The name of any <<label,label>> defined before{nbsp}__**L**__
1752 which isn't within a nested group.
1753 * The name of any <<variable-assignment,variable>> known
1757 The value of the special name `ICITTE` (`int` type) in this expression
1758 is the <<cur-offset,current offset>> (before handling the items to
1761 ** A valid {py3} name.
1763 For the name `__NAME__`, this is equivalent to the
1764 `pass:[{]__NAME__pass:[}]` form above.
1766 . Zero or more items.
1768 . The `!end` closing.
1770 You may also use a <<post-item-repetition,post-item repetition>> after
1771 some items. The form ``!repeat{nbsp}__X__{nbsp}__ITEMS__{nbsp}!end``
1772 is equivalent to ``(__ITEMS__){nbsp}pass:[*]{nbsp}__X__``.
1779 {end - ICITTE - 1 : 8}
1788 ff fe fd fc fb fa f9 f8 f7 f6 f5 f4 f3 f2 f1 f0 ┆ ••••••••••••••••
1789 ef ee ed ec eb ea e9 e8 e7 e6 e5 e4 e3 e2 e1 e0 ┆ ••••••••••••••••
1790 df de dd dc db da d9 d8 d7 d6 d5 d4 d3 d2 d1 d0 ┆ ••••••••••••••••
1791 cf ce cd cc cb ca c9 c8 c7 c6 c5 c4 c3 c2 c1 c0 ┆ ••••••••••••••••
1792 bf be bd bc bb ba b9 b8 b7 b6 b5 b4 b3 b2 b1 b0 ┆ ••••••••••••••••
1793 af ae ad ac ab aa a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 ┆ ••••••••••••••••
1794 9f 9e 9d 9c 9b 9a 99 98 97 96 95 94 93 92 91 90 ┆ ••••••••••••••••
1795 8f 8e 8d 8c 8b 8a 89 88 87 86 85 84 83 82 81 80 ┆ ••••••••••••••••
1796 7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70 ┆ •~}|{zyxwvutsrqp
1797 6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60 ┆ onmlkjihgfedcba`
1798 5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50 ┆ _^]\[ZYXWVUTSRQP
1799 4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40 ┆ ONMLKJIHGFEDCBA@
1800 3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30 ┆ ?>=<;:9876543210
1801 2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20 ┆ /.-,+*)('&%$#"!
1802 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 ┆ ••••••••••••••••
1803 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 ┆ ••••••••••••••••
1822 11 22 !repeat times 33 !end
1833 aa bb cc dd ee ff ee ff ee ff ee ff ee ff 11 22 ┆ •••••••••••••••"
1834 33 ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ 3•••••••••••••••
1835 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
1836 ff ee ff ee ff 11 22 33 33 ee ff ee ff ee ff ee ┆ ••••••"33•••••••
1837 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
1838 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
1839 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
1840 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
1841 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
1842 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
1843 ff ee ff ee ff ee ff ee ff ee ff ee ff 11 22 33 ┆ ••••••••••••••"3
1844 33 33 63 6f 75 63 6f 75 21 ┆ 33coucou!
1848 === Macro definition block
1850 A _macro definition block_ associates a name and parameter names to
1853 A macro definition block doesn't lead to generated bytes itself: a
1854 <<macro-expansion,macro expansion>> does so.
1856 A macro definition may only exist at the root level, that is, not within
1857 a <<group,group>>, a <<repetition-block,repetition block>>, a
1858 <<conditional-block,conditional block>>, or another
1859 <<macro-definition-block,macro definition block>>.
1861 All macro definitions must have unique names.
1863 A macro definition is:
1865 . The `!macro` or `!m` opening.
1867 . A valid {py3} name (the macro name).
1869 . The `(` parameter name list prefix.
1871 . A comma-separated list of zero or more unique parameter names,
1872 each one being a valid {py3} name.
1874 . The `)` parameter name list suffix.
1876 . Zero or more items except, recursively, a macro definition block.
1878 . The `!end` closing.
1883 {le} {ICITTE * 8 : 16}
1884 u16le"predict explode"
1891 !macro nail(rep, with_extra, val)
1895 {val + iter : uleb128}
1909 A _macro expansion_ expands the items of a defined
1910 <<macro-definition-block,macro>>.
1912 The macro to expand must be defined _before_ the expansion.
1914 The <<state,state>> before handling the first item of the chosen macro
1917 <<cur-offset,Current offset>>::
1920 <<cur-bo,Current byte order>>::
1924 The only available variables initially are the macro parameters.
1929 The state after having handled the last item of the chosen macro is:
1932 The one before handling the first item of the macro plus the size
1933 of the generated data of the macro expansion.
1935 IMPORTANT: This means <<current-offset-setting,current offset setting>>
1936 items within the expanded macro don't impact the final current offset.
1938 Current byte order::
1939 The one before handling the first item of the macro.
1942 The ones before handling the first item of the macro.
1945 The ones before handling the first item of the macro.
1947 A macro expansion is:
1951 . A valid {py3} name (the name of the macro to expand).
1953 . The `(` parameter value list prefix.
1955 . A comma-separated list of zero or more unique parameter values.
1957 The number of parameter values must match the number of parameter
1958 names of the definition of the chosen macro.
1960 A parameter value is one of:
1963 * A <<const-int,constant integer>>, possibly negative.
1965 * A constant floating point number.
1967 * The ``pass:[{]`` prefix, a valid {py3} expression of which the
1968 evaluation result type is `int` or `bool` (automatically converted to
1969 `int`), and the ``pass:[}]`` suffix.
1971 For a macro expansion at some source location{nbsp}__**L**__, this
1972 expression may contain:
1974 ** The name of any <<label,label>> defined before{nbsp}__**L**__
1975 which isn't within a nested group.
1976 ** The name of any <<variable-assignment,variable>> known
1980 The value of the special name `ICITTE` (`int` type) in this expression
1981 is the <<cur-offset,current offset>> (before handling the items of the
1984 * A valid {py3} name.
1986 For the name `__NAME__`, this is equivalent to the
1987 `pass:[{]__NAME__pass:[}]` form above.
1990 . The `)` parameter value list suffix.
1997 {le} {ICITTE * 8 : 16}
1998 u16le"predict explode"
2001 "hello [" m:bake() "] world"
2009 68 65 6c 6c 6f 20 5b 38 00 70 00 72 00 65 00 64 ┆ hello [8•p•r•e•d
2010 00 69 00 63 00 74 00 20 00 65 00 78 00 70 00 6c ┆ •i•c•t• •e•x•p•l
2011 00 6f 00 64 00 65 00 5d 20 77 6f 72 6c 64 70 01 ┆ •o•d•e•] worldp•
2012 70 00 72 00 65 00 64 00 69 00 63 00 74 00 20 00 ┆ p•r•e•d•i•c•t• •
2013 65 00 78 00 70 00 6c 00 6f 00 64 00 65 00 70 02 ┆ e•x•p•l•o•d•e•p•
2014 70 00 72 00 65 00 64 00 69 00 63 00 74 00 20 00 ┆ p•r•e•d•i•c•t• •
2015 65 00 78 00 70 00 6c 00 6f 00 64 00 65 00 70 03 ┆ e•x•p•l•o•d•e•p•
2016 70 00 72 00 65 00 64 00 69 00 63 00 74 00 20 00 ┆ p•r•e•d•i•c•t• •
2017 65 00 78 00 70 00 6c 00 6f 00 64 00 65 00 70 04 ┆ e•x•p•l•o•d•e•p•
2018 70 00 72 00 65 00 64 00 69 00 63 00 74 00 20 00 ┆ p•r•e•d•i•c•t• •
2019 65 00 78 00 70 00 6c 00 6f 00 64 00 65 00 70 05 ┆ e•x•p•l•o•d•e•p•
2020 70 00 72 00 65 00 64 00 69 00 63 00 74 00 20 00 ┆ p•r•e•d•i•c•t• •
2021 65 00 78 00 70 00 6c 00 6f 00 64 00 65 00 ┆ e•x•p•l•o•d•e•
2029 !macro A(val, is_be)
2039 !macro B(rep, is_be)
2043 m:A({iter * 3}, is_be)
2055 00 03 00 06 00 09 00 0c 00 0f 03 00 06 00 09 00
2063 !macro flt32be(val) {be} {val : 32} !end
2073 43 48 45 45 54 4f 53 c2 28 ae 14 3b b8 41 25 ┆ CHEETOS•(••;•A%
2077 === Post-item repetition
2079 A _post-item repetition_ represents the bytes of an item repeated a
2080 given number of times.
2082 A post-item repetition is:
2084 . One of those items:
2086 ** A <<byte-constant,byte constant>>.
2087 ** A <<literal-string,literal string>>.
2088 ** A <<fixed-length-number,fixed-length number>>.
2089 ** An <<leb128-integer,LEB128 integer>>.
2090 ** A <<string,string>>.
2091 ** A <<macro-expansion,macro-expansion>>.
2092 ** A <<group,group>>.
2094 . The ``pass:[*]`` character.
2098 ** A positive integer (hexadecimal starting with `0x` or `0X` accepted)
2099 which is the number of times to repeat the previous item.
2101 ** The ``pass:[{]`` prefix, a valid {py3} expression of which the
2102 evaluation result type is `int` or `bool` (automatically converted to
2103 `int`), and the ``pass:[}]`` suffix.
2105 For a post-item repetition at some source location{nbsp}__**L**__, this
2106 expression may contain:
2109 * The name of any <<label,label>> defined before{nbsp}__**L**__
2110 which isn't within a nested group and
2111 which isn't part of the repeated item.
2112 * The name of any <<variable-assignment,variable>> known
2113 at{nbsp}__**L**__, which isn't part of its repeated item, and which
2117 The value of the special name `ICITTE` (`int` type) in this expression
2118 is the <<cur-offset,current offset>> (before handling the items to
2121 ** A valid {py3} name.
2123 For the name `__NAME__`, this is equivalent to the
2124 `pass:[{]__NAME__pass:[}]` form above.
2126 You may also use a <<repetition-block,repetition block>>. The form
2127 ``__ITEM__{nbsp}pass:[*]{nbsp}__X__`` is equivalent to
2128 ``!repeat{nbsp}__X__{nbsp}__ITEM__{nbsp}!end``.
2134 {end - ICITTE - 1 : 8} * 0x100 <end>
2140 ff fe fd fc fb fa f9 f8 f7 f6 f5 f4 f3 f2 f1 f0 ┆ ••••••••••••••••
2141 ef ee ed ec eb ea e9 e8 e7 e6 e5 e4 e3 e2 e1 e0 ┆ ••••••••••••••••
2142 df de dd dc db da d9 d8 d7 d6 d5 d4 d3 d2 d1 d0 ┆ ••••••••••••••••
2143 cf ce cd cc cb ca c9 c8 c7 c6 c5 c4 c3 c2 c1 c0 ┆ ••••••••••••••••
2144 bf be bd bc bb ba b9 b8 b7 b6 b5 b4 b3 b2 b1 b0 ┆ ••••••••••••••••
2145 af ae ad ac ab aa a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 ┆ ••••••••••••••••
2146 9f 9e 9d 9c 9b 9a 99 98 97 96 95 94 93 92 91 90 ┆ ••••••••••••••••
2147 8f 8e 8d 8c 8b 8a 89 88 87 86 85 84 83 82 81 80 ┆ ••••••••••••••••
2148 7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70 ┆ •~}|{zyxwvutsrqp
2149 6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60 ┆ onmlkjihgfedcba`
2150 5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50 ┆ _^]\[ZYXWVUTSRQP
2151 4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40 ┆ ONMLKJIHGFEDCBA@
2152 3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30 ┆ ?>=<;:9876543210
2153 2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20 ┆ /.-,+*)('&%$#"!
2154 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 ┆ ••••••••••••••••
2155 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 ┆ ••••••••••••••••
2167 (ee ff) * {here + 1}
2177 aa bb cc dd ee ff ee ff ee ff ee ff ee ff 11 22 ┆ •••••••••••••••"
2178 33 ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ 3•••••••••••••••
2179 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
2180 ff ee ff ee ff 11 22 33 33 ee ff ee ff ee ff ee ┆ ••••••"33•••••••
2181 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
2182 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
2183 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
2184 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
2185 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
2186 ff ee ff ee ff ee ff ee ff ee ff ee ff ee ff ee ┆ ••••••••••••••••
2187 ff ee ff ee ff ee ff ee ff ee ff ee ff 11 22 33 ┆ ••••••••••••••"3
2188 33 33 63 6f 75 63 6f 75 21 ┆ 33coucou!
2192 == Command-line tool
2194 If you <<install-normand,installed>> the `normand` package, then you
2195 can use the `normand` command-line tool:
2198 $ normand <<< '"ma gang de malades"' | hexdump -C
2202 00000000 6d 61 20 67 61 6e 67 20 64 65 20 6d 61 6c 61 64 |ma gang de malad|
2206 If you copy the `normand.py` module to your own project, then you can
2207 run the module itself:
2210 $ python3 -m normand <<< '"ma gang de malades"' | hexdump -C
2214 00000000 6d 61 20 67 61 6e 67 20 64 65 20 6d 61 6c 61 64 |ma gang de malad|
2218 Without a path argument, the `normand` tool reads from the standard
2221 The `normand` tool prints the generated binary data to the standard
2224 Various options control the initial <<state,state>> of the processor:
2225 use the `--help` option to learn more.
2229 The whole `normand` package/module public API is:
2234 class ByteOrder(enum.Enum):
2246 def line_no(self) -> int:
2251 def col_no(self) -> int:
2255 # Parsing error message.
2256 class ParseErrorMessage:
2262 # Source text location.
2264 def text_location(self):
2269 class ParseError(RuntimeError):
2270 # Parsing error messages.
2272 # The first message is the most _specific_ one.
2278 # Variables dictionary type (for type hints).
2279 VariablesT = typing.Dict[str, typing.Union[int, float]]
2282 # Labels dictionary type (for type hints).
2283 LabelsT = typing.Dict[str, int]
2290 def data(self) -> bytearray:
2293 # Updated variable values.
2295 def variables(self) -> SymbolsT:
2298 # Updated main group label values.
2300 def labels(self) -> SymbolsT:
2305 def offset(self) -> int:
2310 def byte_order(self) -> typing.Optional[ByteOrder]:
2314 # Parses the `normand` input using the initial state defined by
2315 # `init_variables`, `init_labels`, `init_offset`, and `init_byte_order`,
2316 # and returns the corresponding parsing result.
2317 def parse(normand: str,
2318 init_variables: typing.Optional[SymbolsT] = None,
2319 init_labels: typing.Optional[SymbolsT] = None,
2320 init_offset: int = 0,
2321 init_byte_order: typing.Optional[ByteOrder] = None) -> ParseResult:
2325 The `normand` parameter is the actual <<learn-normand,Normand input>>
2326 while the other parameters control the initial <<state,state>>.
2328 The `parse()` function raises a `ParseError` instance should it fail to
2329 parse the `normand` string for any reason.
2333 Normand is a https://python-poetry.org/[Poetry] project.
2335 To develop it, install it through Poetry and enter the virtual
2341 $ normand <<< '"lol" * 10 0a'
2344 `normand.py` is processed by:
2346 * https://microsoft.github.io/pyright/[Pyright]
2347 * https://github.com/psf/black[Black]
2348 * https://pycqa.github.io/isort/[isort]
2352 Use https://docs.pytest.org/[pytest] to test Normand once the package is
2353 part of your virtual environment, for example:
2357 $ poetry run pip3 install pytest
2361 The `pytest` project is currently not a development dependency in
2362 `pyproject.toml` due to backward compatibiliy issues with
2365 In the `tests` directory, each `*.nt` file is a test. The file name
2366 prefix indicates what it's meant to test:
2369 Everything above the `---` line is the valid Normand input
2372 Everything below the `---` line is the expected data
2373 (whitespace-separated hexadecimal bytes).
2376 Everything above the `---` line is the invalid Normand input
2379 Everything below the `---` line is the expected error message having
2388 Normand uses https://review.lttng.org/admin/repos/normand,general[Gerrit]
2391 To report a bug, https://github.com/efficios/normand/issues/new[create a