about summary refs log tree commit diff stats
path: root/util.c
blob: 2414b394fc7a2fe81b5b3043ea1c937be7cb9e2d (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
/*
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
 * See LICENSE file for license details.
 */
#include "dwm.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

/* static */

static void
bad_malloc(unsigned int size)
{
	eprint("fatal: could not malloc() %u bytes\n", size);
}

/* extern */

void *
emallocz(unsigned int size)
{
	void *res = calloc(1, size);

	if(!res)
		bad_malloc(size);
	return res;
}

void
eprint(const char *errstr, ...)
{
	va_list ap;

	va_start(ap, errstr);
	vfprintf(stderr, errstr, ap);
	va_end(ap);
	exit(EXIT_FAILURE);
}

void *
erealloc(void *ptr, unsigned int size)
{
	void *res = realloc(ptr, size);
	if(!res)
		bad_malloc(size);
	return res;
}

void
spawn(Arg *arg)
{
	static char *shell = NULL;

	if(!shell && !(shell = getenv("SHELL")))
		shell = "/bin/sh";

	if(!arg->cmd)
		return;
	if(fork() == 0) {
		if(fork() == 0) {
			if(dpy)
				close(ConnectionNumber(dpy));
			setsid();
			execl(shell, shell, "-c", arg->cmd, NULL);
			fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg->cmd);
			perror(" failed");
		}
		exit(0);
	}
	wait(0);
}
class="m">0 } type render-state { current-state: int # enum 0: normal, 1: bold, 2: heading } # decide how to lay out pages on screen fn render in: (addr buffered-file), nrows: int, ncols: int { # Fit multiple pages on screen on separate columns, each wide enough to read # comfortably. # Pages are separated horizontally by a 'page margin'. Among other reasons, # this allows the odd line to bleed out on the right if necessary. # # hardcoded parameters: # top-margin # page-margin # page-width var _r: render-state var r/edi: (addr render-state) <- address _r var toprow/eax: int <- copy 2 # top-margin var botrow/ecx: int <- copy nrows var leftcol/edx: int <- copy 5 # page-margin var rightcol/ebx: int <- copy leftcol rightcol <- add 0x40 # page-width = 64 characters start-color-on-screen 0xec, 7 # 236 = darkish gray { compare rightcol, ncols break-if->= render-page in, toprow, leftcol, botrow, rightcol, r leftcol <- copy rightcol leftcol <- add 5 # page-margin rightcol <- copy leftcol rightcol <- add 0x40 # page-width loop } } fn render-page in: (addr buffered-file), toprow: int, leftcol: int, botrow: int, rightcol: int, _r: (addr render-state) { var r/edi: (addr render-state) <- copy _r var state/esi: (addr int) <- get r, current-state clear toprow, leftcol, botrow, rightcol var row/ecx: int <- copy toprow $line-loop: { compare row, botrow break-if->= var col/edx: int <- copy leftcol move-cursor-on-screen row, col $char-loop: { compare col, rightcol break-if->= var c/eax: byte <- read-byte-buffered in compare c, 0xffffffff # EOF marker break-if-= $line-loop $update-attributes:check-state: { compare *state, 0 # normal { break-if-!= compare c, 0x2a # '*' { break-if-!= # r->current-state == 0 && c == '*' => bold text start-bold-on-screen copy-to *state, 1 break $update-attributes:check-state } compare c, 0x5f # '_' { break-if-!= # r->current-state == 0 && c == '_' => bold text start-bold-on-screen copy-to *state, 1 break $update-attributes:check-state } break $update-attributes:check-state } compare *state, 1 # bold { break-if-!= compare c, 0x2a # '*' { break-if-!= # r->current-state == 1 && c == '*' => print c, then normal text print-byte-to-screen c col <- increment reset-formatting-on-screen start-color-on-screen 0xec, 7 # 236 = darkish gray copy-to *state, 0 loop $char-loop } compare c, 0x5f # '_' { break-if-!= # r->current-state == 1 && c == '_' => print c, then normal text print-byte-to-screen c col <- increment reset-formatting-on-screen start-color-on-screen 0xec, 7 # 236 = darkish gray copy-to *state, 0 loop $char-loop } break $update-attributes:check-state } } # $change-state compare c, 0xa # newline break-if-= # no need to print newlines # print c print-byte-to-screen c col <- increment loop } # $char-loop row <- increment loop } # $line-loop } fn clear toprow: int, leftcol: int, botrow: int, rightcol: int { var row/ecx: int <- copy toprow { compare row, botrow break-if->= var col/edx: int <- copy leftcol move-cursor-on-screen row, col { compare col, rightcol break-if->= print-string-to-screen " " col <- increment loop } row <- increment loop } } fn first-arg args-on-stack: (addr array (addr array byte)) -> out/eax: (addr array byte) { var args/eax: (addr array (addr array byte)) <- copy args-on-stack var result/eax: (addr addr array byte) <- index args, 1 out <- copy *result } fn load-file filename: (addr array byte) -> out/esi: (addr buffered-file) { var result: (handle buffered-file) { var tmp1/eax: (addr handle buffered-file) <- address result open filename, 0, tmp1 } var tmp2/eax: (addr buffered-file) <- lookup result out <- copy tmp2 } fn dump in: (addr buffered-file) { var c/eax: byte <- read-byte-buffered in compare c, 0xffffffff # EOF marker break-if-= print-byte-to-screen c loop }