aboutsummaryrefslogtreecommitdiff
path: root/snag/src/util.c
blob: ab0b7e6309577694009df17e07daff4a25ad50e6 (plain)
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include "util.h"

#if !DEBUG
void die(const char* format, ...) {
#else
void _die(const char* file, int line, const char* format, ...) {
	fprintf(stderr, "%s:%d: error: ", file, line);
#endif
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
	fprintf(stderr, "\n");
    exit(1);
}

#if !DEBUG
void* emalloc(size_t size, char* alloc_reason) {
	void* d = malloc(size);
	if (d == NULL) die("failed to allocate '%s': %s", alloc_reason, strerror(errno));
	return d;
}
#else
void* _emalloc(const char* file, int line, size_t size, char* alloc_reason) {
	void* d = malloc(size);
	if (d == NULL) _die(file, line, "failed to allocate '%s': %s", alloc_reason, strerror(errno));
	return d;
}
#endif

#if DEBUG
void _failassert(const char* file, int line, char* contents) {
	fprintf(stderr, "%s:%d: assertion failed: '%s'", file, line, contents);
	exit(1);
}
#endif

void printout(const char* format, ...) {
    va_list args;
    va_start(args, format);
    vfprintf(stdout, format, args);
    va_end(args);
}

void print(const char* format, ...) {
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
}

char* vastrcat_(int dummy, ...) {

    va_list args;
    va_list args2;
    va_start(args, dummy);
	va_copy(args2, args);

	// get len of output string
	size_t len = 0;
    char* arg = NULL;
    while ((arg = va_arg(args, char*))) {
		len += strlen(arg);
    }
    va_end(args);

	// allocate and build output
	char* output = malloc(len + 1);
    if (!output) return NULL;
	char* p = output;
    while ((arg = va_arg(args2, char*))) {
		size_t alen = strlen(arg);
		memcpy(p, arg, alen);
		p += alen;
    }
	output[len] = '\0';
    va_end(args2);

	return output;
}

char* join_path_(int dummy, ...) {

    va_list args;
    va_list args2;
    va_start(args, dummy);
	va_copy(args2, args);

	// note(jqj): some path joining libraries reset if they encounter an
	//            absolute path, we could implement that easily, but I'm not
	//            sure about it

	// get len of output path
	size_t len = 0;
    char* arg = NULL;
	int i = 0;
    while ((arg = va_arg(args, char*))) {
		if (i > 0) len += 1;
		len += strlen(arg);
		++i;
    }
    va_end(args);

	// allocate output string
	char* output = malloc(len + 1);
    if (!output) {
        va_end(args2);
        return NULL;
    }

    // build output string
	char* p = output;
    while ((arg = va_arg(args2, char*))) {
		if (p != output) {
			// add slash before every part except the first
			*p = '/';
			++p;
		}
		size_t alen = strlen(arg);
		memcpy(p, arg, alen);
		p += alen;
    }
	output[len] = '\0';
    va_end(args2);

	return output;
}