5
* These utility functions and macros can requiers nob.h
7
* You may use them as you see fit.
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.
19
#include <linux/limits.h>
30
#if defined(__unix__) || defined(__linux__)
34
#include <mach-o/dyld.h>
39
#define IN /*Does nothing, just a mark.*/
40
#define OUT /*Does nothing, just a mark.*/
41
#define INOUT /*Does nothing, just a mark.*/
43
typedef struct da_strings_t DaStrings;
45
typedef enum NobberError {
47
NOBBER_RETURN_UNUSED0,
48
NOBBER_RETURN_UNUSED1,
49
NOBBER_RETURN_UNUSED2,
50
NOBBER_RETURN_UNUSED3,
51
NOBBER_RETURN_UNKNOWN_COMMAND,
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);
68
//#define free0(ptr) \
72
memset ((void *)ptr, 0, sizeof ((void *) ptr)); \
83
* free the items in a list propperly!
84
* TODO: Need a version that takes a FreeFunc.
86
#define da_free_items(Type, da) { \
87
for (Type *it = (da)->items; it < (da)->items + (da)->capacity; it++) { \
88
if (*it == NULL) break;\
94
#ifdef NOBBER_UTILS_IMPLEMENTAITON
96
/* ----------------- */
98
void * malloc0 (size_t size) {
99
void * out_val = malloc (size);
100
memset (out_val, 0, size);
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);
111
while (end > out_str && *end != '.' && *end != '\\' && *end != '/') {
115
if ((end > out_str && *end == '.') &&
116
(*(end - 1) != '\\' && *(end - 1) != '/')) {
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);
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++) {
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);
145
char * s = malloc0 (strlen (tmp_str) + 1);
147
nob_da_append (object_files, s);
149
nob_cmd_run (cmd, .async = procs);
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);
165
void clean_files (IN char * source_files[], size_t len, char * exec_name, INOUT Nob_Cmd * cmd) {
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);
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;
182
nob_cmd_append (cmd, exec_name);
184
da_free_items (char *, &tmp_strings);
187
char * construct_string (IN char * str, ...) {
188
char * retval = NULL;
190
Nob_String_Builder sb = {0};
191
nob_sb_append_cstr (&sb, str);
192
va_start (list, str);
194
nob_sb_append_cstr (&sb, str);
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);
203
NobberError run_excutable (INOUT Nob_Cmd * cmd, IN char * executable) {
204
// We assume we are only running from the current directory.
206
NobberError ret_val = NOBBER_RETURN_NORMAL;
208
strcat (cwd, executable);
212
char * get_path_of_current_executalbe () {
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__)
221
if (readlink (PROC_EXE_PATH, buf, PATH_MAX) < 0) {
222
fprintf (stderr, "[ERROR] Could not readlink /proc/self/exe: %s", strerror (errno));
225
#elif defined(__FreeBSD__)
229
mib[2] = KERN_PROC_PATHNAME;
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.");
237
if (!GetModuleFileNameA (NULL, buf, MAX_PATH)) {
238
fprintf (stderr, "[ERROR] Could not readlink /proc/self/exe: %s", strerror (errno));
242
static_assert (false, "get_path_of_current_executalbe () is not implemented for this platform.");
244
char * ret = malloc (strlen (buf));
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;
255
// Count the nuber of tokens
257
if (*ptr == deliminator) {
262
if (*(--ptr) != deliminator) {
265
no_of_tokens++; // add empty space.
267
char ** result = malloc0 (sizeof (char *) * no_of_tokens);
270
char * tok_ptr = str_cpy;
272
char * token = strtok (tok_ptr, delim);
274
result[idx] = strndup (token, strlen (token));
275
token = strtok (NULL, delim);
280
*out_size = no_of_tokens - 1;
286
#endif // NOBBER_UTILS_IMPLEMENTATION