about summary refs log tree commit diff stats
path: root/examples/ex11.subx
blob: ba75c1d3b648113234389d24094b0963213379c7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
ranger v.1.7.2
==============

[![Build Status](https://travis-ci.org/ranger/ranger.svg?branch=master)](https://travis-ci.org/ranger/ranger)

ranger is a console file manager with VI key bindings.  It provides a
minimalistic and nice curses interface with a view on the directory hierarchy.
It ships with "rifle", a file launcher that is good at automatically finding
out which program to use for what file type.

![screenshot](https://raw.githubusercontent.com/ranger/ranger-assets/master/screenshots/screenshot.png)

This file describes ranger and how to get it to run.  For instructions on the
usage, please read the man page.  See HACKING.md for development specific
information.  For configuration, check the files in ranger/config/ or copy the
default config to ~/.config/ranger with ranger's --copy-config option.  The
examples/ directory contains several scripts and plugins that demonstrate how
ranger can be extended or combined with other programs.  These files can be
found in the git repository or in /usr/share/doc/ranger.

A note to packagers:  Versions meant for packaging are listed in the changelog
on the website.


About
-----
* Authors:     see "AUTHORS" file
* License:     GNU General Public License Version 3
* Website:     http://ranger.nongnu.org/
* Download:    http://ranger.nongnu.org/ranger-stable.tar.gz
* Bug reports: https://github.com/hut/ranger/issues
* git clone    http://git.sv.gnu.org/r/ranger.git


Design Goals
------------
* An easily maintainable file manager in a high level language
* A quick way to switch directories and browse the file system
* Keep it small but useful, do one thing and do it well
* Console based, with smooth integration into the unix shell


Features
--------
* UTF-8 Support  (if your python copy supports it)
* Multi-column display
* Preview of the selected file/directory
* Common file operations (create/chmod/copy/delete/...)
* Renaming multiple files at once
* VIM-like console and hotkeys
* Automatically determine file types and run them with correct programs
* Change the directory of your shell after exiting ranger
* Tabs, Bookmarks, Mouse support


Dependencies
------------
* Python (tested with version 2.6, 2.7, 3.1-3.5) with the "curses" module
# Null-terminated vs length-prefixed ascii strings.
#
# By default we create strings with a 4-byte length prefix rather than a null suffix.
# However we still need null-prefixed strings when interacting with the Linux
# kernel in a few places. This layer implements a function for comparing
# a null-terminated 'kernel string' with a length-prefixed 'SubX string'.
#
# To run (from the subx directory):
#   $ ./subx translate examples/ex11.subx -o examples/ex11
#   $ ./subx run examples/ex11  # runs a series of tests
#   ......  # all tests pass
#
# (We can't yet run the tests when given a "test" commandline argument,
# because checking for it would require the function being tested! Breakage
# would cause tests to not run, rather than to fail as we'd like.)

== code 0x09000000
#   instruction                     effective address                                                   register    displacement    immediate
# . op          subop               mod             rm32          base        index         scale       r32
# . 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes

Entry:  # run all tests
    e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
    # syscall(exit, EAX)
    89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # copy EAX to EBX
    b8/copy-to-EAX  1/imm32/exit
    cd/syscall  0x80/imm8

# compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
# reason for the name: the only place we should have null-terminated ascii strings is from commandline args
kernel-string-equal?:  # s : null-terminated ascii string, benchmark : length-prefixed ascii string -> EAX : boolean
    # pseudocode:
    #   n = benchmark->length
    #   s1 = s
    #   s2 = benchmark->data
    #   i = 0
    #   while i < n
    #     c1 = *s1
    #     c2 = *s2
    #     if (c1 == 0) return false
    #     if (c1 != c2) return false
    #     ++s1, ++s2, ++i
    #   return *s1 == 0
    #
    # registers:
    #   i: ECX
    #   n: EDX
    #   s1: EDI
    #   s2: ESI
    #   c1: EAX
    #   c2: EBX
    #
    # . prolog
    55/push-EBP
    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    # . save registers
    51/push-ECX
    52/push-EDX
    53/push-EBX
    56/push-ESI
    57/push-EDI
    # s1/EDI = s
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
    # n/EDX = benchmark->length
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
    8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
    # s2/ESI = benchmark->data
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
    81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               4/imm32           # add to ESI
    # i/ECX = c1/EAX = c2/EBX = 0
    b9/copy-to-ECX  0/imm32/exit
    b8/copy-to-EAX  0/imm32
    bb/copy-to-EBX  0/imm32
$kernel-string-equal?:loop:
    # if (i >= n) break
    39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # compare ECX with EDX
    7d/jump-if-greater-or-equal  $kernel-string-equal?:break/disp8
    # c1 = *s1
    8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/AL    .               .                 # copy byte at *EDI to AL
    # c2 = *s2
    8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/BL    .               .                 # copy byte at *ESI to BL
    # if (c1 == 0) return false
    3d/compare-EAX-and  0/imm32
    74/jump-if-equal  $kernel-string-equal?:false/disp8
    # if (c1 != c2) return false
    39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
    75/jump-if-not-equal  $kernel-string-equal?:false/disp8
    # ++i
    41/increment-ECX
    # ++s1
    47/increment-EDI
    # ++s2
    46/increment-ESI
    eb/jump  $kernel-string-equal?:loop/disp8
$kernel-string-equal?:break:
    # return *s1 == 0
    8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/AL    .               .                 # copy byte at *EDI to AL
    3d/compare-EAX-and  0/imm32
    75/jump-if-not-equal  $kernel-string-equal?:false/disp8
$kernel-string-equal?:true:
    b8/copy-to-EAX  1/imm32
    eb/jump  $kernel-string-equal?:end/disp8
$kernel-string-equal?:false:
    b8/copy-to-EAX  0/imm32
$kernel-string-equal?:end:
    # . restore registers
    5f/pop-to-EDI
    5e/pop-to-ESI
    5b/pop-to-EBX
    5a/pop-to-EDX
    59/pop-to-ECX
    # . epilog
    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    5d/pop-to-EBP
    c3/return

# - tests

test-compare-null-kernel-string-with-empty-array:
    # EAX = kernel-string-equal?(Null-kernel-string, "")
    # . . push args
    68/push  ""/imm32
    68/push  Null-kernel-string/imm32
    # . . call
    e8/call  kernel-string-equal?/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-ints-equal(EAX, 1, msg)
    # . . push args
    68/push  "F - test-compare-null-kernel-string-with-empty-array"/imm32
    68/push  1/imm32/true
    50/push-EAX
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    c3/return

test-compare-null-kernel-string-with-non-empty-array:
    # EAX = kernel-string-equal?(Null-kernel-string, "Abc")
    # . . push args
    68/push  "Abc"/imm32
    68/push  Null-kernel-string/imm32
    # . . call
    e8/call  kernel-string-equal?/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-ints-equal(EAX, 0, msg)
    # . . push args
    68/push  "F - test-compare-null-kernel-string-with-non-empty-array"/imm32
    68/push  0/imm32/false
    50/push-EAX
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    c3/return

test-compare-kernel-string-with-equal-array:
    # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Abc")
    # . . push args
    68/push  "Abc"/imm32
    68/push  _test-Abc-kernel-string/imm32
    # . . call
    e8/call  kernel-string-equal?/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-ints-equal(EAX, 1, msg)
    # . . push args
    68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
    68/push  1/imm32/true
    50/push-EAX
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    c3/return

test-compare-kernel-string-with-inequal-array:
    # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Adc")
    # . . push args
    68/push  "Adc"/imm32
    68/push  _test-Abc-kernel-string/imm32
    # . . call
    e8/call  kernel-string-equal?/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-ints-equal(EAX, 0, msg)
    # . . push args
    68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
    68/push  0/imm32/false
    50/push-EAX
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    c3/return

test-compare-kernel-string-with-empty-array:
    # EAX = kernel-string-equal?(_test-Abc-kernel-string, "")
    # . . push args
    68/push  ""/imm32
    68/push  _test-Abc-kernel-string/imm32
    # . . call
    e8/call  kernel-string-equal?/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-ints-equal(EAX, 0, msg)
    # . . push args
    68/push  "F - test-compare-kernel-string-with-equal-array"/imm32
    68/push  0/imm32/false
    50/push-EAX
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    c3/return

test-compare-kernel-string-with-shorter-array:
    # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Ab")
    # . . push args
    68/push  "Ab"/imm32
    68/push  _test-Abc-kernel-string/imm32
    # . . call
    e8/call  kernel-string-equal?/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-ints-equal(EAX, 0, msg)
    # . . push args
    68/push  "F - test-compare-kernel-string-with-shorter-array"/imm32
    68/push  0/imm32/false
    50/push-EAX
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    c3/return

test-compare-kernel-string-with-longer-array:
    # EAX = kernel-string-equal?(_test-Abc-kernel-string, "Abcd")
    # . . push args
    68/push  "Abcd"/imm32
    68/push  _test-Abc-kernel-string/imm32
    # . . call
    e8/call  kernel-string-equal?/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    # check-ints-equal(EAX, 0, msg)
    # . . push args
    68/push  "F - test-compare-kernel-string-with-longer-array"/imm32
    68/push  0/imm32/false
    50/push-EAX
    # . . call
    e8/call  check-ints-equal/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    c3/return

# - helpers

# print msg to stderr if a != b, otherwise print "."
check-ints-equal:  # (a : int, b : int, msg : (address array byte)) -> boolean
    # . prolog
    55/push-EBP
    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    # . save registers
    51/push-ECX
    53/push-EBX
    # load args into EAX, EBX and ECX
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(EBP+8) to EAX
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
    # if (EAX == b/EBX) print('.') and return
    39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
    75/jump-if-unequal  $check-ints-equal:else/disp8
    # . write-stderr('.')
    # . . push args
    68/push  "."/imm32
    # . . call
    e8/call  write-stderr/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # . return
    eb/jump  $check-ints-equal:end/disp8
    # otherwise print(msg)
$check-ints-equal:else:
    # copy msg into ECX
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   0x10/disp8       .                # copy *(EBP+16) to ECX
    # print(ECX)
    # . . push args
    51/push-ECX
    # . . call
    e8/call  write-stderr/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    # print newline
    # . . push args
    68/push  Newline/imm32
    # . . call
    e8/call  write-stderr/disp32
    # . . discard args
    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
$check-ints-equal:end:
    # . restore registers
    5b/pop-to-EBX
    59/pop-to-ECX
    # end
    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    5d/pop-to-EBP
    c3/return

write-stderr:  # s : (address array byte) -> <void>
    # . prolog
    55/push-EBP
    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    # . save registers
    50/push-EAX
    51/push-ECX
    52/push-EDX
    53/push-EBX
    # syscall(write, 2/stderr, (data) s+4, (size) *s)
    # . . fd = 2 (stderr)
    bb/copy-to-EBX  2/imm32
    # . . x = s+4
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
    81          0/subop/add         3/mod/direct    1/rm32/ECX    .           .             .           .           .               4/imm32           # add to ECX
    # . . size = *s
    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   8/disp8         .                 # copy *(EBP+8) to EDX
    8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           2/r32/EDX   .               .                 # copy *EDX to EDX
    # . . syscall
    b8/copy-to-EAX  4/imm32/write
    cd/syscall  0x80/imm8
    # . restore registers
    5b/pop-to-EBX
    5a/pop-to-EDX
    59/pop-to-ECX
    58/pop-to-EAX
    # . end
    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    5d/pop-to-EBP
    c3/return

== data 0x0a000000

Newline:
    # size
    1/imm32
    # data
    0a/newline

# for kernel-string-equal tests
Null-kernel-string:
    00/null

_test-Abc-kernel-string:
    41/A 62/b 63/c 00/null

# . . vim:nowrap:textwidth=0