bzr branch
http://gegoxaren.bato24.eu/bzr/nobber/trunk
|
4
by Stream
* Moved functions to utils.h |
1 |
#pragma once
|
2 |
||
3 |
/*******
|
|
4 |
* utils.h
|
|
5 |
* These utility functions and macros can requiers nob.h
|
|
6 |
*
|
|
7 |
* You may use them as you see fit.
|
|
8 |
*
|
|
9 |
* This header file uses the standard STB-style inclue stuff:
|
|
10 |
* define NOBBER_UTILS_IMPREMENTATION
|
|
11 |
* to in one file, so they get built.
|
|
12 |
******/
|
|
13 |
||
14 |
#include <stdlib.h> |
|
15 |
#include <stdio.h> |
|
16 |
||
17 |
#include <alloca.h> |
|
18 |
#include <errno.h> |
|
19 |
#include <linux/limits.h> |
|
20 |
#include <stdlib.h> |
|
21 |
#include <stddef.h> |
|
22 |
#include <stdio.h> |
|
23 |
#include <stdlib.h> |
|
24 |
#include <string.h> |
|
25 |
#include <stdbool.h> |
|
26 |
#include <stdint.h> |
|
27 |
#include <inttypes.h> |
|
28 |
#include <unistd.h> |
|
29 |
#include <assert.h> |
|
30 |
#if defined(__unix__) || defined(__linux__)
|
|
31 |
#include <unistd.h> |
|
32 |
#endif
|
|
33 |
#ifdef __darwin__
|
|
34 |
#include <mach-o/dyld.h> |
|
35 |
#endif
|
|
36 |
||
37 |
#include "nob.h" |
|
38 |
||
39 |
#define IN /*Does nothing, just a mark.*/ |
|
40 |
#define OUT /*Does nothing, just a mark.*/ |
|
41 |
#define INOUT /*Does nothing, just a mark.*/ |
|
42 |
||
43 |
typedef struct da_strings_t DaStrings; |
|
44 |
||
45 |
typedef enum NobberError { |
|
46 |
NOBBER_RETURN_NORMAL, |
|
47 |
NOBBER_RETURN_UNUSED0, |
|
48 |
NOBBER_RETURN_UNUSED1, |
|
49 |
NOBBER_RETURN_UNUSED2, |
|
50 |
NOBBER_RETURN_UNUSED3, |
|
51 |
NOBBER_RETURN_UNKNOWN_COMMAND, |
|
52 |
NOBBER_RETURN_EXEC, |
|
53 |
NOBBER_RETURN_COUNT |
|
54 |
} NobberError; |
|
55 |
||
56 |
void * malloc0 (size_t size); |
|
57 |
char * strip_extention (IN char * file_name); |
|
58 |
char * c_to_o_ext (IN char * str); |
|
59 |
DaStrings * compile_files (IN char * source_files[], size_t source_files_len, IN char * build_flags[], size_t build_flags_len, INOUT Nob_Cmd * cmd, INOUT Nob_Procs * procs); |
|
60 |
void link_files (IN DaStrings * object_files, IN char * exec_name, IN char * link_flags[], size_t link_flags_len, INOUT Nob_Cmd * cmd); |
|
61 |
void clean_files (IN char * source_files[], size_t len, char * exec_name, INOUT Nob_Cmd * cmd); |
|
62 |
char * construct_string (IN char * str, ...); |
|
63 |
NobberError run_excutable (INOUT Nob_Cmd * cmd, IN char * executable); |
|
64 |
char * get_path_of_current_executalbe (); |
|
65 |
char ** split_string (IN char * str, char delimeter, OUT size_t * out_size); |
|
66 |
||
67 |
||
68 |
//#define free0(ptr) \
|
|
69 |
// free (ptr); \
|
|
70 |
// ptr = NULL;
|
|
71 |
#define free0(ptr) \
|
|
72 |
memset ((void *)ptr, 0, sizeof ((void *) ptr)); \
|
|
73 |
free (ptr);
|
|
74 |
||
75 |
struct da_strings_t { |
|
76 |
char ** items; |
|
77 |
size_t count; |
|
78 |
size_t capacity; |
|
79 |
};
|
|
80 |
||
81 |
||
82 |
/**
|
|
83 |
* free the items in a list propperly!
|
|
84 |
* TODO: Need a version that takes a FreeFunc.
|
|
85 |
**/
|
|
86 |
#define da_free_items(Type, da) { \
|
|
87 |
for (Type *it = (da)->items; it < (da)->items + (da)->capacity; it++) { \
|
|
88 |
if (*it == NULL) break;\
|
|
89 |
free (*it);\
|
|
90 |
}\
|
|
91 |
free ((da)->items);\
|
|
92 |
}
|
|
93 |
||
94 |
#ifdef NOBBER_UTILS_IMPLEMENTAITON
|
|
95 |
||
96 |
/* ----------------- */
|
|
97 |
||
98 |
void * malloc0 (size_t size) { |
|
99 |
void * out_val = malloc (size); |
|
100 |
memset (out_val, 0, size); |
|
101 |
return out_val; |
|
102 |
}
|
|
103 |
||
104 |
||
105 |
// https://stackoverflow.com/questions/43163677/how-do-i-strip-a-file-extension-from-a-string-in-c
|
|
106 |
char * strip_extention (IN char * file_name) { |
|
107 |
char * out_str = malloc(strlen(file_name) + 1); |
|
108 |
strcpy (out_str, file_name); |
|
109 |
char *end = out_str + strlen(out_str); |
|
110 |
||
111 |
while (end > out_str && *end != '.' && *end != '\\' && *end != '/') { |
|
112 |
--end; |
|
113 |
} |
|
114 |
||
115 |
if ((end > out_str && *end == '.') && |
|
116 |
(*(end - 1) != '\\' && *(end - 1) != '/')) { |
|
117 |
*end = '\0'; |
|
118 |
} |
|
119 |
||
120 |
return out_str; |
|
121 |
}
|
|
122 |
||
123 |
char * c_to_o_ext (IN char * str) { |
|
124 |
char * out_str = malloc (strlen(str) + 1); |
|
125 |
char * tmp_str = strip_extention (str); |
|
126 |
sprintf (out_str, "%s.o", tmp_str); |
|
127 |
free (tmp_str); |
|
128 |
return out_str; |
|
129 |
}
|
|
130 |
||
131 |
DaStrings * compile_files (IN char * source_files[], size_t source_files_len, |
|
132 |
IN char * build_flags[], size_t build_flags_len, |
|
133 |
INOUT Nob_Cmd * cmd, INOUT Nob_Procs * procs) { |
|
134 |
DaStrings * object_files = malloc0 (sizeof (DaStrings)); |
|
135 |
for (size_t i = 0; i < source_files_len; i++) { |
|
136 |
cmd->count = 0; |
|
137 |
if (source_files[i] == NULL) break; |
|
138 |
nob_cmd_append (cmd, "cc"); |
|
139 |
nob_cmd_append (cmd, source_files[i]); |
|
140 |
nob_da_append_many (cmd, build_flags, build_flags_len); |
|
141 |
nob_cmd_append (cmd, "-c"); |
|
142 |
char * tmp_str = c_to_o_ext (source_files[i]); |
|
143 |
nob_cmd_append (cmd, "-o", tmp_str); |
|
144 |
||
145 |
char * s = malloc0 (strlen (tmp_str) + 1); |
|
146 |
strcpy (s, tmp_str); |
|
147 |
nob_da_append (object_files, s); |
|
148 |
||
149 |
nob_cmd_run (cmd, .async = procs); |
|
150 |
free0 (tmp_str); |
|
151 |
} |
|
152 |
return object_files; |
|
153 |
}
|
|
154 |
||
155 |
void link_files (IN DaStrings * object_files, IN char * exec_name, |
|
156 |
IN char * link_flags[], size_t link_flags_len, |
|
157 |
INOUT Nob_Cmd * cmd) { |
|
158 |
nob_cmd_append (cmd, "cc"); |
|
159 |
nob_cmd_append (cmd, "-o", exec_name); |
|
160 |
nob_da_append_many (cmd, (char**) object_files->items, object_files->count); |
|
161 |
nob_da_append_many (cmd, (char**) link_flags, link_flags_len); |
|
162 |
nob_cmd_run (cmd); |
|
163 |
}
|
|
164 |
||
165 |
void clean_files (IN char * source_files[], size_t len, char * exec_name, INOUT Nob_Cmd * cmd) { |
|
166 |
cmd->count = 0; |
|
167 |
DaStrings tmp_strings = {0}; |
|
168 |
for (size_t i = 0; i < len; i++) { |
|
169 |
if (source_files[i] == NULL) break; |
|
170 |
char * tmp_file = strip_extention ((char *)source_files[i]); |
|
171 |
char * tmp_obj_file = c_to_o_ext (tmp_file); |
|
172 |
nob_da_append (&tmp_strings, tmp_obj_file); |
|
173 |
tmp_file = c_to_o_ext (tmp_file); |
|
174 |
free0 (tmp_file); |
|
175 |
} |
|
176 |
nob_cmd_append (cmd, "rm"); |
|
177 |
nob_da_append_many (cmd, tmp_strings.items, tmp_strings.count); |
|
178 |
for (size_t i = 0; i < tmp_strings.count; i++) { |
|
179 |
char * s = tmp_strings.items[i]; |
|
180 |
if (s == NULL) break; |
|
181 |
} |
|
182 |
nob_cmd_append (cmd, exec_name); |
|
183 |
nob_cmd_run (cmd); |
|
184 |
da_free_items (char *, &tmp_strings); |
|
185 |
}
|
|
186 |
||
187 |
char * construct_string (IN char * str, ...) { |
|
188 |
char * retval = NULL; |
|
189 |
va_list list = {0}; |
|
190 |
Nob_String_Builder sb = {0}; |
|
191 |
nob_sb_append_cstr (&sb, str); |
|
192 |
va_start (list, str); |
|
193 |
while (*str++) { |
|
194 |
nob_sb_append_cstr (&sb, str); |
|
195 |
} |
|
196 |
va_end (list); |
|
197 |
Nob_String_View sv = nob_sv_from_parts (sb.items, sb.count); |
|
198 |
retval = malloc0 (strlen (sv.data) + 1); |
|
199 |
strcpy (retval, sv.data); |
|
200 |
return retval; |
|
201 |
}
|
|
202 |
||
203 |
NobberError run_excutable (INOUT Nob_Cmd * cmd, IN char * executable) { |
|
204 |
// We assume we are only running from the current directory. |
|
205 |
char * cwd; |
|
206 |
NobberError ret_val = NOBBER_RETURN_NORMAL; |
|
207 |
strcat (cwd, "/"); |
|
208 |
strcat (cwd, executable); |
|
209 |
return ret_val; |
|
210 |
}
|
|
211 |
||
212 |
char * get_path_of_current_executalbe () { |
|
213 |
char buf[PATH_MAX]; |
|
214 |
#if defined(__DragonFly__) || defined(__NetBSD__) || defined(__linux__)
|
|
215 |
#if defined(__linux__) |
|
216 |
#define PROC_EXE_PATH "/proc/self/exe" |
|
217 |
#elif defined(__NetBSD__) |
|
218 |
#define PROC_EXE_PATH "/proc/curproc/exe" |
|
219 |
#elif defined(__DragonFly__) |
|
220 |
#endif |
|
221 |
if (readlink (PROC_EXE_PATH, buf, PATH_MAX) < 0) { |
|
222 |
fprintf (stderr, "[ERROR] Could not readlink /proc/self/exe: %s", strerror (errno)); |
|
223 |
return NULL; |
|
224 |
} |
|
225 |
#elif defined(__FreeBSD__)
|
|
226 |
int mib[4]; |
|
227 |
mib[0] = CTL_KERN; |
|
228 |
mib[1] = KERN_PROC; |
|
229 |
mib[2] = KERN_PROC_PATHNAME; |
|
230 |
mib[3] = -1; |
|
231 |
sysctl(mib, 4, buf, PATH_MAX, NULL, 0); |
|
232 |
#elif defined(__darwin__)
|
|
233 |
if (_NSGetExecutablePath(buf, PATH_MAX) < 0) { |
|
234 |
fprintf (stderr, "[ERROR] Could not get executable path."); |
|
235 |
} |
|
236 |
#elif defined(WIN32)
|
|
237 |
if (!GetModuleFileNameA (NULL, buf, MAX_PATH)) { |
|
238 |
fprintf (stderr, "[ERROR] Could not readlink /proc/self/exe: %s", strerror (errno)); |
|
239 |
return NULL; |
|
240 |
} |
|
241 |
#else
|
|
242 |
static_assert (false, "get_path_of_current_executalbe () is not implemented for this platform."); |
|
243 |
#endif
|
|
244 |
char * ret = malloc (strlen (buf)); |
|
245 |
strcpy(ret, buf); |
|
246 |
return ret; |
|
247 |
}
|
|
248 |
||
249 |
char ** split_string (IN char * str, char deliminator, OUT size_t * out_size) { |
|
250 |
char * str_cpy = strndup (str, strlen (str)); |
|
251 |
char * ptr = str_cpy; |
|
252 |
char delim[2] = {deliminator, 0}; |
|
253 |
size_t no_of_tokens = 0; |
|
254 |
||
255 |
// Count the nuber of tokens |
|
256 |
while (*ptr) { |
|
257 |
if (*ptr == deliminator) { |
|
258 |
no_of_tokens++; |
|
259 |
} |
|
260 |
ptr++; |
|
261 |
} |
|
262 |
if (*(--ptr) != deliminator) { |
|
263 |
no_of_tokens++; |
|
264 |
} |
|
265 |
no_of_tokens++; // add empty space. |
|
266 |
|
|
267 |
char ** result = malloc0 (sizeof (char *) * no_of_tokens); |
|
268 |
if (result) { |
|
269 |
size_t idx = 0; |
|
270 |
char * tok_ptr = str_cpy; |
|
271 |
|
|
272 |
char * token = strtok (tok_ptr, delim); |
|
273 |
while (token) { |
|
274 |
result[idx] = strndup (token, strlen (token)); |
|
275 |
token = strtok (NULL, delim); |
|
276 |
idx++; |
|
277 |
} |
|
278 |
result[idx] = 0; |
|
279 |
} |
|
280 |
*out_size = no_of_tokens - 1; |
|
281 |
free (str_cpy); |
|
282 |
return result; |
|
283 |
}
|
|
284 |
||
285 |
||
286 |
#endif // NOBBER_UTILS_IMPLEMENTATION |