hhh 1.0.1

The hhh Binary File Processor
Documentation
# Directives

Directives control the operation of both the hex file generator and of the parser, and can be specified in three different places.

- Directives can be in the configuration file for **hhh**
- Directives can be specified on the command line with the `-D` switch, and will override those present in the configuration file
- Directives can be in a binary description file, and will override any on the command line or in the configuration file

A complete list of directives, their arguments, and their use can be obtained with the command line switch `--list-directives`.

## Structure

A directive is specified by giving the symbolic name followed by any arguments in parentheses.  For instance:

```
bias(0x2000)
```

This sets the current bias (the amount added to offsets when generating a hex dump or the amount subtracted from offsets when parsing a binary description) to 0x2000.

If a directive does not take any arguments, you can omit the parentheses.

```
prefix
```

Arguments may use radix prefixes and may be given as expressions.

```
bias(0x2000 + 40*8)
```

A directive can be given using either hyphens or underscores, so `little_endian` and `little-endian` are treated as the same.

## Configuration File

Configuration files are explained in their own chapter.  See [Configuration](configuration.md).  Essentially, directives are given, one per line, and are evaluated in the order they are encountered.

```
// Enable prefixes
prefix
```

## Command Line

To specify a directive on the command line, given the directive after a `-D` switch.

The parentheses may be processed by the shell, so to use them on the command line you may need to surround the entire directive with single or double quotation marks.

```bash
$ echo "Hello, world!" | hhh -D'bytes-per-group(2)' -D'groups-per-line(4)' -Dprefix
0x00000000: 0x4865 0x6c6c 0x6f2c 0x2077  // Hello,.w
0x00000008: 0x6f72 0x6c64 0x210a         // orld!.
```

```bash
$ echo "Salamu, Dunia!" | hhh -D'bytes-per-group(4)' -D'groups_per-line(20/4)' -D'bias(0x1000)'
00001000: 53616c61 6d752c20 44756e69 61210a             // Salamu,.Dunia!.
```

## Binary Description File

Binary description files are discussed in their own chapter.  See [W]

Within a binary description file, directive can be given inside a double square bracket pair `[[..]]`.  Only one directive can be given at a time.

```hhh -p
[[prefix()]]
0: 0xfffe 0x4f00 0x6c00 0xe100 0x2c00 0x2000 0x6d00 0x7500
   0x6e00 0x6400 0x6f00 0x2100

// Result
// 00000000: ff fe 4f 00 6c 00 e1 00 2c 00 20 00 6d 00 75 00
// 00000010: 6e 00 64 00 6f 00 21 00
```

## All Directives

The complete list of directives at time of writing, along with their arguments and their use, is given here.  Some directives are only meaningful during parsing of a binary description file, and some are only meaningful when generating a hex dump.  This is indicated for each directive.

Directives that are closely associated are listed together.

<!--#################################################################################################################-->
~~~admonish note title="## `ascii()`<br>`no_ascii()`<br><br><small>GENERATION</small>"
~~~

Generate or suppress an ASCII preview for each line.  Any non-graphical ASCII characters are represented by a period, as are any bytes outside the ASCII range.

The command line switch `--no-ascii` is a synonym for `-Dno-ascii`.

The default behavior is `--ascii`.

```bash
$ echo 'Olá, mundo!' | hhh -Dascii
00000000: 4f 6c c3 a1 2c 20 6d 75 6e 64 6f 21 0a           // Ol..,.mundo!.
```

```bash
$ echo 'Olá, mundo!' | hhh -Dno_ascii
00000000: 4f 6c c3 a1 2c 20 6d 75 6e 64 6f 21 0a
```

<!--#################################################################################################################-->
~~~admonish note title="## `bias(number)`<br><br><small>GENERATION<br>PARSING</small>"
~~~

Set the bias to add to (parsing) or subtract from (generation) the offset.

The command line switch `--bias=number` is a synonym for `-Dbias(number)`.

The default behavior is to use a bias of zero.

**When generating:**  The bias is added to the offset.

```bash
$ echo "Howdy!" | hhh -D'bias(0x2000)'
00002000: 48 6f 77 64 79 21 0a                             // Howdy!.
```

**When parsing:**  The bias is subtracted from the offset.

```bash
$ echo "2000: 48 6f 77 64 79 21 0a" | hhh -p -D'bias(0x2000)'
Howdy!
```

```hhh -p
[[bias(0x2000)]]
00002000: 48 6f 77 64 79 21 0a

// Result
// 00000000: 48 6f 77 64 79 21 0a
```

<!--#################################################################################################################-->
~~~admonish note title="## `big-endian()`<br>`little-endian()`<br><br><small>GENERATION<br>PARSING</small>"
~~~

Specify the order of bytes in unprefixed byte blocks.

The command line switch `--little-endian` is a synonym for `-Dlittle-endian`.

The default behavior is `-Dbig-endian`.

**When generating:**  Specifying little endian order reverses the order of the bytes in each unprefixed byte block.

```bash
$ echo "1234" | hhh -b2 --no-ascii -Dlittle-endian
00000000: 3231 3433   0a
```

It does not reverse the order of bytes written as part of a prefixed number.  That is, if radix prefixes are enabled, then this directive has no effect.

```bash
$ echo "1234" | hhh -b2 --no-ascii -Dlittle-endian -r
0x00000000: 0x3132 0x3334 0x0a
```

**When parsing:**  Specifying little endian order reverses the order of bytes in each unprefixed byte block.

```bash
$ echo "3231 3433" | hhh -p -Dlittle-endian
1234
```

It does not reverse the order of bytes written as part of a prefixed number.  That is, if radix prefixes are enabled, then this directive has no effect.

```bash
$ echo "0x3231 0x3433" | hhh -r -p -Dlittle-endian
2143
```

<!--#################################################################################################################-->
~~~admonish note title="## `bytes-per-group([1..255])`<br>`groups-per-line([1..255])`<br>`group-separator(string)`<br><br><small>GENERATION</small>"
~~~

Specify the number of bytes to include in a single group (or in a single prefixed number) in the output (`bytes-per-group`).  Specify the number of groups to include on a line (`groups-per-line`).  Specify a string to use to separate groups (`group-separator`).

The command line switches `--bytes-per-group=number` and `-b number` are synonyms for `-Dbytes-per-group(number)`.

The command line switches `--group-per-line=number` and `-g number` are synonyms for `-Dgroups-per-line(number)`.

The command line switches `--group-separator=string` and `-s string` are synonyms for `-Dgroup-separator(string)`.

The default behavior is one byte per group.

```bash
$ echo "Only in Ohio" | hhh -b2 -g4
00000000: 4f6e 6c79 2069 6e20  // Only.in.
00000008: 4f68 696f 0a         // Ohio.
```

```bash
$ echo "Only in Ohio" | hhh -b8 -g2 -s", "
00000000: 4f6e6c7920696e20, 4f68696f0a        // Only.in.Ohio.
```

<!--#################################################################################################################-->
~~~admonish note title="## `lowercase()`<br>`uppercase()`<br><br><small>GENERATION</small>"
~~~

Use lower case or upper case letters for hexadecimal output.

The command line switch `--uppercase` is a synonym for `-Duppercase`.

The default behavior is to use lower case.

```bash
$ echo "xyzzy" | hhh --uppercase
00000000: 78 79 7A 7A 79 0A                                // xyzzy.
```

<!--#################################################################################################################-->
~~~admonish note title="## `metadata()`<br>`no-metadata()`<br>set-metadata(string,string)`<br><br><small>GENERATION</small>"
~~~

Whether to write a commented metadata block at the top of the generated hex dump (`metadata`) or not (`no-metadata`).

Add or remove metadata elements (`set-metadata`) by giving the metadata name and value as strings.  If the value is the empty string, then the metadata item is suppressed.

The command line switches `--meta` and `-m` are synonyms for `-Dmetadata`.

The command line switches `--set-meta=name=value` and `-Mname=value` are synonyms for `-Dset-metadata(name, value)`.

The default behavior is to not write metadata.  When metadata is written, then default is to include the command line and the current date and time.

```bash
$ hhh --meta test_files/hello -MUTC= | head -4
// Command-Line: "--no-configuration-file" "--meta" "test_files/hello" "-MUTC="
00000000: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  // .ELF............
00000010: 02 00 3e 00 01 00 00 00 00 10 40 00 00 00 00 00  // ..>.......@.....
00000020: 40 00 00 00 00 00 00 00 40 11 00 00 00 00 00 00  // @.......@.......
```

```bash
$ hhh -Dmeta test_files/hello -MProject=1704 -D'set-metadata("Command-Line","")' -MUTC= | head -6
// Project: 1704
00000000: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  // .ELF............
00000010: 02 00 3e 00 01 00 00 00 00 10 40 00 00 00 00 00  // ..>.......@.....
00000020: 40 00 00 00 00 00 00 00 40 11 00 00 00 00 00 00  // @.......@.......
00000030: 00 00 00 00 40 00 38 00 02 00 40 00 05 00 04 00  // ....@.8...@.....
00000040: 01 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00  // ................
```

<!--#################################################################################################################-->
~~~admonish note title="## `offsets()`<br>`no-offsets()`<br>`offset-width([0..255])`<br><br><small>GENERATION</small>"
~~~

Include or suppress the offset value at the start of each line, or specify the minimum number of digits to display for the offset.

The command line switch `--no-offset` is a synonym for `-Dno-offset`.

The command line switch `--offset-width=number` is a synonym for `-Doffset-width(number)`.

The default behavior is to include an offset at the start of each line and to use eight digits.

```bash
$ echo "Lorem ipsum" | hhh --no-offset
4c 6f 72 65 6d 20 69 70 73 75 6d 0a              // Lorem.ipsum.
```

```bash
$ echo "Lorem ipsum" | hhh -g1 -b4 --offset-width=2
00: 4c6f7265  // Lore
04: 6d206970  // m.ip
08: 73756d0a  // sum.
```

<!--#################################################################################################################-->
~~~admonish note title="## `prefix()`<br>`no-prefix`<br><br><small>GENERATION<br>PARSING</small>"
~~~

Specify whether to use radix prefixes.

The command line switches `--radix-prefixes` and `-r` are synonyms for `-Dprefix`.

The default behavior is to not use or expect radix prefixes.

**When generating:** If radix prefixes are enabled then byte order directives are ignored and byte groups are treated as numbers is the specified radix (currently only hexadecimal is used).

```bash
$ echo "0123456" | hhh -b2 -g2 -Dprefix
0x00000000: 0x3031 0x3233  // 0123
0x00000004: 0x3435 0x360a  // 456.
```

**When parsing:** Numbers are assumed to be decimal unless prefixed with a radix specifier (`0x`, `0o`, or `0b`) and byte order directives are ignored.

```hhh -p
0000: 4561737920

[[prefix]]

0x617320 0x3120 0x3220 0x330a

// Result
// 00000000: 45 61 73 79 20 61 73 20 31 20 32 20 33 0a
```

<!--#################################################################################################################-->
~~~admonish note title="## `relative(number)`<br><br><small>PARSING</small>"
~~~

Set a bias that makes the current offset into the offset given by the number.

The defaul behavior is to use a bias of zero.

```hhh -p
[[relative(0x4000)]]

4000: "This is a test"

[[bias(0)]]

21 0a

// Result
// 00000000: 54 68 69 73 20 69 73 20 61 20 74 65 73 74 21 0a
```

<!--#################################################################################################################-->
~~~admonish note title="## `set(variable, number)`<br><br><small>PARSING</small>"
~~~

Set a variable.

By default only `$_`, representing the current offset, is specified.

```hhh -p
[[ set( "first", 0x31323334 ) ]]

0: $first/4

// Result
// 00000000: 31 32 33 34
```

<!--#################################################################################################################-->
~~~admonish note title="## `stoic()`<br>`no-stoic()`<br><br><small>PARSING</small>"
~~~

Disable (`stoic`) or enable (`no-stoic`) all errors and make a best attempt to parse.

The default is to stop on an error.

```hhh -p
[[stoic]]
[[relative(0x4000)]]


/usr/bin/ls:     file format elf64-x86-64


Disassembly of section .init:

0000000000004000 <.init>:
    4000:       f3 0f 1e fa             endbr64
    4004:       48 83 ec 08             sub    rsp,0x8
    4008:       48 8b 05 a9 ef 01 00    mov    rax,QWORD PTR [rip+0x1efa9]
    400f:       48 85 c0                test   rax,rax
    4012:       74 02                   je     4016 <free@plt-0x61a>
    4014:       ff d0                   call   rax
    4016:       48 83 c4 08             add    rsp,0x8
    401a:       c3                      ret

"END"

// Result
// 00000000: f3 0f 1e fa 48 83 ec 08 48 8b 05 a9 ef 01 00 48
// 00000010: 85 c0 74 02 ff d0 48 83 c4 08 c3 45 4e 44
```