about summary refs log tree commit diff stats
path: root/README
blob: b4fde501384219f90bccb506287dbf4dfb7b8d68 (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
dwm - dynamic window manager
============================
dwm is an extremely fast, small, and dynamic window manager for X.


Requirements
------------
In order to build dwm you need the Xlib header files.


Installation
------------
Edit config.mk to match your local setup (dwm is installed into
the /usr/local namespace by default).

Afterwards enter the following command to build and install dwm (if
necessary as root):

    make clean install


Running dwm
-----------
Add the following line to your .xinitrc to start dwm using startx:

    exec dwm

In order to connect dwm to a specific display, make sure that
the DISPLAY environment variable is set correctly, e.g.:

    DISPLAY=foo.bar:1 exec dwm

(This will start dwm on display :1 of the host foo.bar.)

In order to display status info in the bar, you can do something
like this in your .xinitrc:

    while true
    do
        echo `date` `uptime | sed 's/.*,//'`
        sleep 1
    done | dwm


Configuration
-------------
The configuration of dwm is done by creating a custom config.h
and (re)compiling the source code.
r: #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 */
//: Some simple sanity checks for types, and also attempts to guess them where
//: they aren't provided.
//:
//: You still have to provide the full type the first time you mention a
//: variable in a recipe. You have to explicitly name :offset and :variant
//: every single time. You can't use the same name with multiple types in a
//: single recipe.

:(scenario transform_fails_on_reusing_name_with_different_type)
% Hide_errors = true;
def main [
  x:number <- copy 1
  x:boolean <- copy 1
]
+error: main: x used with multiple types

:(after "Begin Instruction Modifying Transforms")
Transform.push_back(check_or_set_types_by_name);  // idempotent

:(code)
void check_or_set_types_by_name(const recipe_ordinal r) {
  trace(9991, "transform") << "--- deduce types for recipe " << get(Recipe, r).name << end();
  recipe& caller = get(Recipe, r);
  set<reagent> known;
  for (int i = 0; i < SIZE(caller.steps); ++i) {
    instruction& inst = caller.steps.at(i);
    for (int in = 0; in < SIZE(inst.ingredients); ++in) {
      deduce_missing_type(known, inst.ingredients.at(in));
      check_type(known, inst.ingredients.at(in), caller);
    }
    for (int out = 0; out < SIZE(inst.products); ++out) {
      deduce_missing_type(known, inst.products.at(out));
      check_type(known, inst.products.at(out), caller);
    }
  }
}

void deduce_missing_type(set<reagent>& known, reagent& x) {
  if (x.type) return;
  if (known.find(x) == known.end()) return;
  x.type = new type_tree(*known.find(x)->type);
  trace(9992, "transform") << x.name << " <= " << names_to_string(x.type) << end();
}

void check_type(set<reagent>& known, const reagent& x, const recipe& caller) {
  if (is_literal(x)) return;
  if (is_integer(x.name)) return;  // if you use raw locations you're probably doing something unsafe
  if (!x.type) return;  // might get filled in by other logic later
  if (known.find(x) == known.end()) {
    trace(9992, "transform") << x.name << " => " << names_to_string(x.type) << end();
    known.insert(x);
  }
  if (!types_strictly_match(known.find(x)->type, x.type)) {
    raise << maybe(caller.name) << x.name << " used with multiple types\n" << end();
    return;
  }
  if (x.type->name == "array") {
    if (!x.type->right) {
      raise << maybe(caller.name) << x.name << " can't be just an array. What is it an array of?\n" << end();
      return;
    }
    if (!x.type->right->right) {
      raise << caller.name << " can't determine the size of array variable " << x.name << ". Either allocate it separately and make the type of " << x.name << " address:..., or specify the length of the array in the type of " << x.name << ".\n" << end();
      return;
    }
  }
}

:(scenario transform_fills_in_missing_types)
def main [
  x:number <- copy 1
  y:number <- add x, 1
]

:(scenario transform_fills_in_missing_types_in_product)
def main [
  x:number <- copy 1
  x <- copy 2
]

:(scenario transform_fills_in_missing_types_in_product_and_ingredient)
def main [
  x:number <- copy 1
  x <- add x, 1
]
+mem: storing 2 in location 1

:(scenario transform_fails_on_missing_types_in_first_mention)
% Hide_errors = true;
def main [
  x <- copy 1
  x:number <- copy 2
]
+error: main: missing type for x in 'x <- copy 1'

:(scenario typo_in_address_type_fails)
% Hide_errors = true;
def main [
  y:address:charcter <- new character:type
  *y <- copy 67
]
+error: main: unknown type charcter in 'y:address:charcter <- new character:type'

:(scenario array_type_without_size_fails)
% Hide_errors = true;
def main [
  x:array:number <- merge 2, 12, 13
]
+error: main can't determine the size of array variable x. Either allocate it separately and make the type of x address:..., or specify the length of the array in the type of x.

:(scenarios transform)
:(scenario transform_checks_types_of_identical_reagents_in_multiple_spaces)
def foo [  # dummy
]
def main [
  local-scope
  0:address:array:location/names:foo <- copy 0  # specify surrounding space
  x:boolean <- copy 1/true
  x:number/space:1 <- copy 34
  x/space:1 <- copy 35
]
$error: 0