-
Notifications
You must be signed in to change notification settings - Fork 8
Mcstruct
mcstruct shows a binary file as a tree of named fields instead of a hex dump. The layout of the file comes from a text "def-file" written in STL5. Fields can be edited in place and written back. The tool is a panel plugin with its own screen, in the spirit of the DOS program Struct Look; its def-file format is compatible with Struct Look 4.00.

-
mcstruct FILE [DEF]from the shell (mcstructis a symlink tomc).DEFis a def-file name without.stl, or a path. - In the file panel: F3 on a file that a
magic.inigroup hands to the plugin (.dbf, uImage, DTB, MBR out of the box), or F9 -> Command -> Struct look for any file. - In the viewer: Shift-F4 opens the file in mcstruct at the current offset; Shift-F4 or F10 in mcstruct goes back to the viewer at the byte you were on.
Which def-file is used, in this order: the name given on the command line or
in the magic.ini group ([mcstruct-dbf] means dbf.stl), a signature or
a name pattern from stl.als, <extension>.stl, else a list to choose from.
Def-files are searched in ~/.config/mc6/mcstruct/, /etc/mc/mcstruct/ and
the plugin's own data directory, the first hit wins. Put your own files and
your stl.als into the first one.
mcstruct sample.dbf dbf.stl DBF
+-- DBF: 252 bytes at 00000000 3/25 records ----+ +-- dbf.stl line 9/134 ---------+
| 00000000 version b 03 (dBASE III) | | 7 ver: b 'dbf_version |
| 00000001 last update u8[3] 126 8 28 | | 8 u8 3 |
| 00000004 records u32 3 | | 9 nrec: u32 1 records |
+-------------------------------------------------+ +--------------------------------+
offset 00000004 (4) local +4 field 4 bytes file 252 bytes
00000000 03 7E 08 1C 03 00 00 00 A1 00 1E 00 ...

Three zones, all synced: the structure tree, the hex dump and the def-file. Moving in the tree highlights the field's bytes in the dump and the def-file line that produced it; moving the hex cursor selects the field under it.
On terminals narrower than 120 columns the def-file goes below the hex dump.
| key | action |
|---|---|
| Up Down PgUp PgDn Home End | move |
| Right, Enter | expand; on an array, table or #repeat open it as a grid; on a jump follow it |
| Left | collapse or go to the parent |
| Backspace | back from a jump |
| 1..9, * | expand to depth, expand all |
| Tab | next zone (tree, hex, def-file) |
| F2 | write pending edits |
| F3 | choose a structure and an offset to apply it at |
| F4 | edit the current field |
| F5 | go to an offset (an expression, labels of the current structure allowed) |
| F6, Shift-F6 | choose a def-file; open the current one in mcedit at the current line |
| F7, Shift-F7 | search a field name or value; next |
| F8 | hide or show the hex zone |
| F9 | parse errors of the def-file, Enter opens mcedit at the line |
| Alt-= | calculator with the labels of the current structure |
| Alt-F9 | zoom the focused zone |
| F10, Esc, Shift-F4 | quit (asks when edits are pending) |

In the grid: Left/Right move between cells, < and > scroll the columns,
F4 edits the cell, Enter follows a jump cell, Esc returns to the tree.
In the hex zone: Tab switches between the hex and the text column, typing edits the byte under the cursor.
F4 shows the value in the form of its type: hex for b w d q, decimal for
u* i*, text for strings, a bit string for t*, SEG:OFF for pointers,
YYYY-MM-DD HH:MM:SS for dates. The bytes are replaced in place, the
structure is re-evaluated, F2 writes the file. Only fixed-width edits: the
file never changes size. The first edit takes the file lock as mcedit does.
A def-file starts with a version line and holds structures, tables and
legends. Files tagged STL 4.00 are read in strict compatibility mode;
STL 5.00 enables the extensions marked below.
STL 5.00
; a comment
/Name ; a structure
/_Hidden ; not offered in the F3 list, but usable
/:Table ; a table: one row per record
/'legend ; value legend (enum)
/`flags ; bit legendA field line:
[label:] TYPE follower [title] ; commentTypes: c chars, b w d q hex 1/2/4/8 bytes, i8..i64 and u8..u64
decimal, t8..t64 bit fields, m8..m64 big-endian hex, f32 f64 f80
float, sp Pascal string, sc C string, td tu DOS and unix time,
j8..j64 jumps, s8 s16 fixed-size UTF-8 and UTF-16 strings (5.00). Any
numeric type takes a .le or .be suffix (5.00).
The follower is a count (for c a length, for sc a maximum), a label, an
expression, a legend reference ('name or `name), or for t* a bit
split like 745 (7+4+5 bits). 0 reads the field but hides it.
Other lines:
:text a remark row
+ N - N skip forward or back
. N seek to a local offset (from the structure start)
.. N seek to an absolute file offset (5.00)
* N Struct N nested structures, or * N :Table
j32 Struct=expr title a jump: the value, Enter opens Struct at exprDirectives:
#if expr / #elseif expr / #else / #fi
#endian big|little byte order from here on (5.00)
#repeat N ... #end N passes (5.00)
#repeat while expr ... #end
#set label = expr a label without bytes (5.00)
#include "file" (5.00)
crc32 a..b == label a check field, also sum8 and sum16 (5.00)Expressions: integers, + - * / % & | ^ ~ << >> ! && ||, comparisons,
labels, @ the value at the current offset, @u32 read as that type,
@u32(addr) read at an absolute offset (5.00), ^label the file offset of
a label, ^ the structure start, $size the file size. "PK" is a packed
literal that compares equal to a little-endian read of the bytes PK.
A title written as =expr is read from the file as a C string (5.00), so a
record layout that comes from the file can name its fields. Nested
structures can read the labels of the structure they are in (5.00).
STL 5.00
/Walker
#set ptr = 0x10
#repeat while ptr != 0
.. ptr
* 1 Node
#set ptr = @u32(ptr)
#end
/Node
next: u32 1 next
u8 1 value#endian big
c 8 signature
#repeat while ^@ + 12 <= $size
len: u32 1 length
type: c 4 type
+ len
crc: d 1 crc
crc32 ^type..^type+4+len == crc crc check
#endThe shipped def-files (zip exe dbf elf mbr fat_boot uimage dtb png bmp wav)
are the reference for the language.
elf.stl: *.so *.o @0:7F454C46
png.stl: @0:89504E470D0A1A0A
mbr.stl: *.img @510:55AAName patterns match the file name, @offset:hexbytes the file contents.
Manage plugins -> mcstruct, or ~/.config/mc6/mcstruct/mcstruct.ini:
[mcstruct]
TreeLines=14 ; rows of the tree, 0 = the rest
HexLines=4 ; rows of the hex zone, 0 hides it
DefLines=0 ; rows of the def-file zone, 0 = the rest
DefLayout=auto ; auto (right of the tree when wide), right, bottom
DefWidth=45 ; percent, when on the right
NameWidth=16 ; the field name column
OffsetColumn=global ; none, local, global
ShowHiddenStructures=false
LazyRows=64 ; arrays longer than this are built on expand
FloatingPointFormat=%gThree sections, one per zone; a missing section falls back to the core colors.
[mcstruct-tree] _default_ frame frame-active head selected
offset name type value struct jump remark error
[mcstruct-hex] _default_ head offset mark changed cursor frame
[mcstruct-def] _default_ frame frame-active head selected
lineno directive comment labeldefault.ini and darkfar.ini carry them.