# Function calls in a single line. # # To run (on Linux): # $ ./translate_subx init.linux [012]*.subx subx-params.subx calls.subx # $ mv a.elf calls # # Example 1: # $ echo '(foo %eax)' | calls # # . (foo %eax) # output has comments # ff 6/subop/push %eax # push # e8/call foo/disp32 # call # 81 0/subop/add %esp 4/imm32 # undo push # # Example 2: # $ echo '(foo Var1 *(eax + 4) "blah")' | calls # # . (foo Var1 *(eax + 4) "blah") # 68/push "blah"/imm32 # ff 6/subop/push *(eax + 4) # push args in.. # 68/push Var1/imm32 # ..reverse order # e8/call foo/disp32 # 81 0/subop/add %esp 0xc/imm32 # undo pushes # # Calls always begin with '(' as the first non-whitespace on a line. == code Entry: # run tests if necessary, convert stdin if not # . prologue 89/<- %ebp 4/r32/esp # initialize heap # . Heap = new-segment(Heap-size) # . . push args 68/push Heap/imm32 ff 6/subop/push *Heap-size # . . call e8/call new-segment/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # - if argc > 1 and argv[1] == "test", then return run_tests() # if (argc <= 1) goto run-main 81 7/subop/compare *ebp 1/imm32 7e/jump-if-<= $subx-calls-main:interactive/disp8 # if (!kernel-string-equal?(argv[1], "test")) goto run-main # . eax = kernel-string-equal?(argv[1], "test") # . . push args 68/push "test"/imm32 ff 6/subop/push *(ebp+8) # . . call e8/call kernel-string-equal?/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # . if (eax == false) goto run-main 3d/compare-eax-and 0/imm32/false 74/jump-if-= $subx-calls-main:interactive/disp8 # run-tests() e8/call run-tests/disp32 # syscall_exit(*Num-test-failures) 8b/-> *Num-test-failures 3/r32/ebx eb/jump $subx-calls-main:end/disp8 $subx-calls-main:interactive: # - otherwise convert stdin # subx-calls(Stdin, Stdout) # . . push args 68/push Stdout/imm32 68/push Stdin/imm32 # . . call e8/call subx-calls/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # syscall_exit(0) bb/copy-to-ebx 0/imm32 $subx-calls-main:end: e8/call syscall_exit/disp32 subx-calls: # in: (addr buffered-file), out: (addr buffered-file) # pseudocode: # var line: (stream byte 512) # var words: (stream slice 16) # at most function name and 15 args # while true # clear-stream(line) # read-line-buffered(in, line) # if (line->write == 0) break # end of file # skip-chars-matching(line, ' ') # if line->data[line->read] != '(' # write-stream-data(out, line) # continue # # emit comment # write-buffered(out, "# . ") # write-stream-data(out, line) # # emit code # ++line->read to skip '(' # clear-stream(words) # words = parse-line(line) # emit-call(out, words) # flush(out) # # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 50/push-eax 51/push-ecx 52/push-edx 56/push-esi # var line/esi: (stream byte 512) 81 5/subop/subtract %esp 0x200/imm32 68/push 0x200/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/<- %esi 4/r32/esp # var words/edx: (stream slice 128) # 16 rows * 8 bytes/row 81 5/subop/subtract %esp 0x80/imm32 68/push 0x80/imm32/length 68/push 0/imm32/read 68/push 0/imm32/write 89/<- %edx 4/r32/esp $subx-calls:loop: # clear-stream(line) # . . push args 56/push-esi # . . call e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 # read-line-buffered(in, line) # . . push args 56/push-esi ff 6/subop/push *(ebp+8) # . . call e8/call read-line-buffered/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 $subx-calls:check0: # if (line->write == 0) break 81 7/subop/compare *esi 0/imm32 0f 84/jump-if-= $subx-calls:break/disp32 # skip-chars-matching(line, ' ') # . . push args 68/push 0x20/imm32/space 56/push-esi # . . call e8/call skip-chars-matching/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # if (line->data[line->read] == '(') goto convert-call # . ecx = line->read 8b/-> *(esi+4) 1/r32/ecx # . eax = line->data[line->read] 31/xor-with %eax 0/r32/eax 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL # . if (eax == '(') goto convert-call 3d/compare-eax-and 0x28/imm32/open-paren 74/jump-if-= $subx-calls:convert-call/disp8 $subx-calls:pass-through: # write-stream-data(out, line) # . . push args 56/push-esi ff 6/subop/push *(ebp+0xc) # . . call e8/call write-stream-data/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # continue eb/jump $subx-calls:loop/disp8 $subx-calls:convert-call: # - emit comment # write-buffered(out, "# . ") # . . push args 68/push "# . "/imm32 ff 6/subop/push *(ebp+0xc) # . . call e8/call write-buffered/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # write-stream-data(out, line) # . . push args 56/push-esi ff 6/subop/push *(ebp+0xc) # . . call e8/call write-stream-data/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # - emit code # ++line->read to skip '(' ff 0/subop/increment *(esi+4) # clear-stream(words) # . . push args 52/push-edx # . . call e8/call clear-stream/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 # words = parse-line(line) # . . push args 52/push-edx 56/push-esi # . . call e8/call parse-line/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # emit-call(out, words) # . . push args 52/push-edx ff 6/subop/push *(ebp+0xc) # . . call e8/call emit-call/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 # loop e9/jump $subx-calls:loop/disp32 $subx-calls:break: # flush(out) # . . push args ff 6/subop/push *(ebp+0xc) # . . call e8/call flush/disp32 # . . discard args 81 0/subop/add %esp 4/imm32 $subx-calls:end: # . reclaim locals 81 0/subop/add %esp 0x298/imm32 # 0x20c + 0x8c # . restore registers 5e/pop-to-esi 5a/pop-to-edx 59/pop-to-ecx 58/pop-to-eax # . epilogue 89/<- %esp 5/r32/ebp 5d/pop-to-ebp c3/return parse-line: # line: (addr stream byte), words: (addr stream slice) # pseudocode: # var word-slice: slice # while true # word-slice = next-word-string-or-expression-without-metadata(line) # if slice-empty?(word-slice) # break # end of line # write-int(words, word-slice->start) # write-int(words, word-slice->end) # # . prologue 55/push-ebp 89/<- %ebp 4/r32/esp # . save registers 51/push-ecx # var word-slice/ecx: slice 68/push 0/imm32/end 68/push 0/imm32/start 89/<- %ecx 4/r32/esp $parse-line:loop: # word-slice = next-word-string-or-expression-without-metadata(line) # . . push args 51/push-ecx ff 6/subop/push *(ebp+8) # . . call e8/call next-word-string-or-expression-without-metadata/disp32 # . . discard args 81 0/subop/add %esp 8/imm32 $parse-line:check1: # if (slice-empty?(word-slice)) break # . eax = slice-empty?(word-slice) # . . push args 51/push-ecx
.TH DWM 1 dwm-VERSION
.SH NAME
dwm \- dynamic window manager
.SH SYNOPSIS
.B dwm
.RB [ \-v ]
.SH DESCRIPTION
.B dwm
is a dynamic window manager for X. It manages windows in tiling and floating
modes. Either mode can be applied dynamically, optimizing the environment for
the application in use and the task performed.
.P
In tiling mode windows are managed in a master and stacking column. The master
column contains the window which currently needs most attention, whereas the
stacking column contains all other windows. In floating mode windows can be
resized and moved freely. Dialog windows are always managed floating,
regardless of the mode selected.
.P
Windows are grouped by tags. Each window can be tagged with one or multiple
tags. Selecting a certain tag for viewing will display all windows with that
tag.
.P
.B dwm
contains a small status bar which displays all available tags, the mode, the
title of the focused window, and the text read from standard input. The tags of
the focused window are highlighted with a small point.
.P
.B dwm
draws a 1-pixel border around windows to indicate the focus state.
Unfocused windows contain a small bar in front of them displaying their title.
.SH OPTIONS
.TP
.B \-v
prints version information to standard output, then exits.
.SH USAGE
.SS Status bar
.TP
.B Standard input
is read and displayed in the status text area.
.TP
.B Button1
click on a tag label views all windows with that
.BR tag .
.TP
.B Button3
click on a tag label adds/removes all windows with that
.B tag
to/from the view.
.SS Keyboard commands
.TP
.B Mod1-Shift-Return
Start
.BR xterm (1).
.TP
.B Mod1-Tab
Focus next
.BR window .
.TP
.B Mod1-Shift-Tab
Focus previous
.BR window .
.TP
.B Mod1-Return
Zoom current
.B window
to the
.B master
column
.RB ( tiling
mode only).
.TP
.B Mod1-m
Maximize current
.BR window .
.TP
.B Mod1-Shift-[0..n]
Apply
.B nth tag
to current
.BR window .
.TP
.B Mod1-Control-Shift-[0..n]
Add/remove
.B nth tag
to/from current
.BR window .
.TP
.B Mod1-Shift-c
Close focused
.B window.
.TP
.B Mod1-space
Toggle between
.B tiled
and
.B floating
mode (affects
.BR "all windows" ).
.TP
.B Mod1-[0..n]
View all windows with
.BR "tag n" .
.TP
.B Mod1-Control-[0..n]
Add/remove all windows with
.B tag n
to/from the view.
.TP
.B Mod1-Shift-q
Quit
.B dwm.
.SS Mouse commands
.TP
.B Mod1-Button1
Move current
.B window
while dragging
.RB ( floating
mode only).
.TP
.B Mod1-Button2
Zoom current
.B window
to the
.B master
column
.RB ( tiling
mode only).
.TP
.B Mod1-Button3
Resize current
.B window
while dragging
.RB ( floating
mode only).
.SH CUSTOMIZATION
.B dwm
is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
.SH CAVEATS
The status bar may display
.B broken pipe
when
.B dwm
has been started by
.BR xdm (1),
because it closes standard output before executing
.BR dwm .
.SH SEE ALSO
.BR dmenu (1)