-
Notifications
You must be signed in to change notification settings - Fork 23
/
util.c
114 lines (105 loc) · 4.1 KB
/
util.c
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* The util library comes from libsl which contains some functionality that is common for several
* suckless project, e.g. dmenu and dwm.
*
* @see https://git.suckless.org/libsl/files.html
*/
#include "util.h"
/* Helper function that prints an error before exiting the process.
*
* @called_from ecalloc in case of error
* @called_from sigchld in case SIGCHLD handler could not be installed
* @called_from main in the event of unexpected arguments
* @called_from xerrorstart in case another window manager is running
* @calls va_start
* @calls vfprintf
* @calls va_end
* @calls strlen to get the length of the error string
* @calls strerror to look up the description of the error that occurred
* @calls fputc to write a character to standard err
* @calls exit to stop the process
* @see https://www.tutorialspoint.com/c_standard_library/c_macro_va_start.htm
*
* Internal call stack:
* main -> setup -> drw_fontset_create -> xfont_create
* main -> setup -> drw_scm_create -> drw_clr_create -> die
* main -> setup -> ecalloc -> die
* main -> setup -> updategeom -> ecalloc -> die
* main -> setup -> updategeom -> createmon -> ecalloc -> die
* main -> setup -> sigchld -> die
* main -> die
* run -> buttonpress -> drw_fontset_getwidth -> drw_text -> die
* run -> buttonpress -> spawn -> die
* run -> configurenotify -> updategeom -> ecalloc -> die
* run -> configurenotify -> updategeom -> createmon -> ecalloc -> die
* run -> keypress -> spawn -> die
* run -> maprequest -> manage -> ecalloc -> die
* run -> scan -> manage -> ecalloc -> die
* xerrorstart -> die
* ~ -> drawbar -> drw_text -> die
* ~ -> drawbar -> drw_fontset_getwidth -> drw_text -> die
*/
void
die(const char *fmt, ...)
{
va_list ap;
int saved_errno;
saved_errno = errno;
/* Note how the function ends with , ... - this means that the function takes variable
* arguments. Have a look at the tutorial on these macros for more information, but the gist
* of it is that it allows for calls to die on this form:
*
* die("error, cannot allocate color '%s'", clrname);
*
* where the %s is substituted for the value of the clrname variable.
*/
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
/* If the error string ends with a colon then print the error that happened as well. */
if (fmt[0] && fmt[strlen(fmt)-1] == ':')
fprintf(stderr, " %s", strerror(saved_errno));
fputc('\n', stderr);
/* Stop the process passing 1 to exit to signify failure. */
exit(1);
}
/* Memory allocation wrapper around calloc that calls die in the event that memory could not be
* allocated.
*
* @called_from drw_cur_create to allocate memory for a cursor
* @called_from drw_scm_create to allocate memory for the colour scheme
* @called_from drw_create to allocate memory for the drawable
* @called_from setup to allocate memory for colour schemes
* @called_from updategeom to allocate memory to hold unique screen info
* @called_from createmon to allocate memory for new Monitor structures
* @called_from manage to allocate memory for new Client structures
* @calls calloc to allocate memory
* @calls die in the event that memory could not be allocated
*
* Internal call stack:
* main -> setup -> drw_cur_create -> ecalloc
* main -> setup -> drw_fontset_create -> xfont_create -> ecalloc
* main -> setup -> drw_scm_create -> ecalloc
* main -> setup -> drw_create -> ecalloc
* main -> setup -> ecalloc
* main -> setup -> updategeom -> ecalloc
* main -> setup -> updategeom -> createmon -> ecalloc
* run -> configurenotify -> updategeom -> ecalloc
* run -> configurenotify -> updategeom -> createmon -> ecalloc
* run -> maprequest -> manage -> ecalloc
* run -> scan -> manage -> ecalloc
*/
void *
ecalloc(size_t nmemb, size_t size)
{
void *p;
/* If memory could not be allocated then call die to exit the window manager. */
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}