: ((Last) ? ((Last)->Next = (Nodeptr), (Last) = (Nodeptr)) \
: ((Head)->Next = (Last) = (Nodeptr))))
-struct cb_path_list {
+struct CB_PathList {
char **values;
size_t count;
size_t capacity;
};
-typedef struct cb_path_list cb_cmd;
+typedef struct CB_PathList CB_Cmd;
-struct cb_run_args {
+struct CB_RunArgs {
bool async;
bool reset;
# define CB_DYN_DEFAULT_CAPACITY 8
#endif
+#ifndef CB_RECOMPILE_OPTIONS
+# define CB_RECOMPILE_OPTIONS
+#endif
+
#if OS_WINDOWS
-# define CB_CMD_REBUILD_SELF(Exe_name, Builder_src) "cl.exe", "/Fe:", (Exe_name), (Builder_src)
+# define CB_CMD_REBUILD_SELF(Exe_name, Builder_src) "cl.exe", "/Fe:", (Exe_name), \
+ (Builder_src), CB_RECOMPILE_OPTIONS
#else
-# define CB_CMD_REBUILD_SELF(Exe_name, Builder_src) "cc", "-o", (Exe_name), (Builder_src)
+# define CB_CMD_REBUILD_SELF(Exe_name, Builder_src) "cc", "-o", (Exe_name), (Builder_src), \
+ CB_RECOMPILE_OPTIONS
#endif
#define cb_dyn_reserve(Dynarr, HowMany) cb_dyn_reserve_custom((Dynarr), (HowMany), values, count, capacity)
#define cb_cmd_append(Dynarr, ...) cb_dyn_append((Dynarr), \
((char*[]){__VA_ARGS__}), \
(sizeof((char*[]){__VA_ARGS__}) / sizeof(char*)))
+#define cb_println(Level, Fmt, ...) cb_print((Level), Fmt "\n", ##__VA_ARGS__)
#define cb_rebuild_self(argc, argv) _cb_rebuild(argc, argv, __FILE__, 0)
#define cb_rebuild_self_with(argc, argv, ...) _cb_rebuild(argc, argv, __FILE__, __VA_ARGS__, 0)
-#define cb_run(Cmd, ...) _cb_run((Cmd), (struct cb_run_args) { \
- .async = false, \
- .reset = true, \
- __VA_ARGS__ \
+#define cb_run(Cmd, ...) _cb_run((Cmd), (struct CB_RunArgs) { \
+ .async = false, \
+ .reset = true, \
+ __VA_ARGS__ \
})
#define cb_proclist_push(Dynarr, Value) cb_dyn_push(Dynarr, Value)
(Dynarr)->Count += (Size); \
} while(0)
+#define cb_handle_write(Handle, Content) _is_literal(Content) ? _cb_handle_write_lit(Handle, Content) : _cb_handle_write_dyn(Handle, Content)
+#define _cb_handle_write_lit(Handle, Content) \
+ _cb_handle_write((Handle), (Content), (sizeof((Content)) / sizeof(*(Content))))
+#define _cb_handle_write_dyn(Handle, Content) \
+ _cb_handle_write((Handle), (Content), strlen((Content)))
+#define _is_literal(x) _is_literal_(x)
+#define _is_literal_(x) _is_literal_f(#x, sizeof(#x) - 1)
+
static char* cb_format(const char *format, ...);
static void cb_print(CB_LogLevel level, const char *fmt, ...);
static char* cb_getenv(char *varname);
static CB_Handle cb_handle_open(char *path, CB_AccessFlag permission);
static void cb_handle_close(CB_Handle fd);
static char* cb_handle_read(CB_Handle fd);
-static void cb_handle_write(CB_Handle fd, char *buffer, size_t buffsize);
static bool cb_dir_create(char *path);
static void cb_dir_delete(char *path);
static void cb_file_delete(char *path);
static bool cb_file_rename(char *path, char *to);
+internal void _cb_handle_write(CB_Handle fd, char *buffer, size_t buffsize);
internal char* _cb_format(const char *format, va_list args);
-internal bool _cb_need_rebuild(char *output_path, struct cb_path_list sources);
+internal bool _cb_need_rebuild(char *output_path, struct CB_PathList sources);
internal void _cb_rebuild(int argc, char **argv, char *cb_src, ...);
-internal CB_Process _cb_run(cb_cmd *cmd, struct cb_run_args args);
+internal CB_Process _cb_run(CB_Cmd *cmd, struct CB_RunArgs args);
internal size_t _last_occurance_of(char *string, char ch);
+internal bool _is_literal_f(char *str, size_t l);
// ==============================================================================
print_str: ;
va_start(args, fmt);
- printf("%s\n", _cb_format(fmt, args));
+ printf("%s", _cb_format(fmt, args));
va_end(args);
#undef ANSI_COLOR_RED
#undef ANSI_COLOR_GREEN
static void cb_process_wait(CB_Process *proc) {
if (proc->handle == CB_PROC_INVALID) {
- cb_print(CB_LogLevel_Warn, "Waiting on invalid process handle");
+ cb_println(CB_LogLevel_Warn, "Waiting on invalid process handle");
return;
}
static void cb_handle_close(CB_Handle fd) {
if (fd == CB_HANDLE_INVALID) {
- cb_print(CB_LogLevel_Warn, "Closing invalid handle");
+ cb_println(CB_LogLevel_Warn, "Closing invalid handle");
return;
}
static char* cb_handle_read(CB_Handle fd) {
if (fd == CB_HANDLE_INVALID) {
- cb_print(CB_LogLevel_Warn, "Reading from invalid handle");
+ cb_println(CB_LogLevel_Warn, "Reading from invalid handle");
return 0;
}
#endif
}
-static void cb_handle_write(CB_Handle fd, char *buffer, size_t buffsize) {
+static void _cb_handle_write(CB_Handle fd, char *buffer, size_t buffsize) {
if (fd == CB_HANDLE_INVALID) {
- cb_print(CB_LogLevel_Warn, "Writing to invalid handle");
+ cb_println(CB_LogLevel_Warn, "Writing to invalid handle");
return;
}
+ while (!buffer[buffsize - 1]) { buffsize -= 1; }
#if OS_WINDOWS
uint64_t to_write = buffsize;
uint64_t total_write = 0;
return res;
}
-internal CB_Process _cb_run(cb_cmd *cmd, struct cb_run_args args) {
+internal CB_Process _cb_run(CB_Cmd *cmd, struct CB_RunArgs args) {
CB_Process res = {};
#if OS_WINDOWS
FORMAT_MESSAGE_IGNORE_INSERTS,
0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, 0);
- cb_print(CB_LogLevel_Error, "Child process creation failed with error %u: %s",
- error, lpMsgBuf);
+ cb_println(CB_LogLevel_Error, "Child process creation failed with error %u: %s",
+ error, lpMsgBuf);
exit(-1);
}
#else
res.handle = fork();
if (res.handle < 0) {
- cb_print(CB_LogLevel_Error, "Child process creation failed with error %d: %s\n",
- errno, strerror(errno));
+ cb_println(CB_LogLevel_Error, "Child process creation failed with error %d: %s\n",
+ errno, strerror(errno));
exit(-1);
} else if (!res.handle) {
if (args.stdout) { dup2(args.stdout, STDOUT_FILENO); }
dup2(args.stdin, STDIN_FILENO);
}
- cb_cmd _cmd = {};
+ CB_Cmd _cmd = {};
cb_cmd_append_dyn(&_cmd, cmd->values, cmd->count);
cb_cmd_push(&_cmd, 0);
if (execvp(_cmd.values[0], _cmd.values) < 0) {
- cb_print(CB_LogLevel_Error, "Child process creation failed with error %d: %s\n",
- errno, strerror(errno));
+ cb_println(CB_LogLevel_Error, "Child process creation failed with error %d: %s\n",
+ errno, strerror(errno));
exit(-1);
}
// NOTE(lb): unreachable, execvp only returns on error.
Assert(argc >= 1);
char *exe_name = argv[0];
- struct cb_path_list sources = {};
+ struct CB_PathList sources = {};
cb_dyn_push(&sources, builder_src);
-
va_list args;
va_start(args, builder_src);
for (;;) {
cb_dyn_free(&sources);
return;
}
+ cb_println(CB_LogLevel_Info, "rebuilding %s", exe_name);
#if OS_WINDOWS
char *exe_name_old = cb_format("%s.old", exe_name);
if (!cb_file_rename(exe_name, exe_name_old)) {
- cb_print(CB_LogLevel_Error, "File rename failed: %s -> %s",
- exe_name, exe_name_old);
+ cb_println(CB_LogLevel_Info, "File rename failed: %s -> %s",
+ exe_name, exe_name_old);
exit(-1);
}
#endif
- cb_cmd cmd = {};
+ CB_Cmd cmd = {};
cb_cmd_append(&cmd, CB_CMD_REBUILD_SELF(exe_name, builder_src));
+ cb_print(CB_LogLevel_Info, "running: `");
+ for (int32_t i = 0; i < cmd.count; ++i) {
+ printf("%s ", cmd.values[i]);
+ }
+ printf("\b`\n");
CB_Process recompiler = cb_run(&cmd);
if (recompiler.status_code) {
#if OS_WINDOWS
exit(0);
}
-internal bool _cb_need_rebuild(char *output_path, struct cb_path_list sources) {
+internal bool _cb_need_rebuild(char *output_path, struct CB_PathList sources) {
#if OS_WINDOWS
FILETIME output_mtime_large = {};
HANDLE output_handle = CreateFileA(output_path, GENERIC_READ, FILE_SHARE_READ,
}
return false;
#else
- // NOTE(lb): on `fstat` failure assume needed rebuild
struct stat output_stat = {};
- if (stat(output_path, &output_stat) < 0) { return true; }
+ if (stat(output_path, &output_stat) < 0) { goto rebuild_failure; }
for (size_t i = 0; i < sources.count; ++i) {
struct stat source_stat = {};
- if (stat(sources.values[i], &source_stat) < 0 ||
- output_stat.st_mtime < source_stat.st_mtime) { return true; }
+ if (stat(sources.values[i], &source_stat) < 0) {
+ rebuild_failure:
+ cb_println(CB_LogLevel_Error,
+ "`%s` modification time unreadable. Is the file path correct?",
+ sources.values[i]);
+ exit(-1);
+ }
+ if (output_stat.st_mtime < source_stat.st_mtime) { return true; }
}
return false;
#endif
return res - string;
}
+internal bool _is_literal_f(char *str, size_t l) {
+ const char *e = str + l;
+ if (str[0] == 'L') str++;
+ if (str[0] != '"') return false;
+ for (; str != e; str = strchr(str + 1, '"')) {
+ if (!str) { return false; }
+ for (str++;
+ *str == '\f' || *str == '\n' || *str == '\r' ||
+ *str == '\t' || *str == '\v';
+ ++str);
+ if (*str != '"') { return false; }
+ }
+ return true;
+}
+
#endif
--- /dev/null
+#ifndef GEN_TRAJECTORY_H
+#define GEN_TRAJECTORY_H
+#define N_POINTS 150
+typedef struct { float x, y; } Points;
+static Points waypoints[N_POINTS] = {{-0.000039,0.000000},{28.846359,0.462402},{57.663120,1.849121},{86.420731,4.158813},{115.089432,7.388977},{143.639877,11.536377},{172.042725,16.596741},{200.268768,22.564880},{228.289062,29.434631},{256.074829,37.198914},{283.597382,45.849854},{310.828522,55.378418},{337.740234,65.774902},{364.304962,77.028564},{390.495392,89.128052},{416.284485,102.060608},{441.645782,115.813171},{466.553253,130.371521},{490.981415,145.720703},{514.904968,161.844971},{538.299500,178.727783},{561.140808,196.351624},{583.405518,214.698608},{605.070801,233.749817},{626.114258,253.485596},{646.514404,273.885681},{666.250122,294.929138},{685.301331,316.594360},{703.648376,338.859192},{721.272217,361.700500},{738.155029,385.094971},{754.279297,409.018585},{769.628479,433.446686},{784.186829,458.354187},{797.939453,483.715607},{810.872009,509.504669},{822.971375,535.695007},{834.225098,562.259705},{844.621582,589.171448},{854.150146,616.402588},{862.801086,643.925232},{870.565369,671.710938},{877.435120,699.731201},{883.403259,727.957275},{888.463623,756.360107},{892.611023,784.910522},{895.841187,813.579346},{898.150818,842.336853},{899.537598,871.153625},{900.000000,900.000000},{900.000000,899.999939},{900.462402,928.846313},{901.849121,957.663086},{904.158752,986.420593},{907.388977,1015.089294},{911.536316,1043.639771},{916.596741,1072.042725},{922.564880,1100.268799},{929.434631,1128.289062},{937.198914,1156.074829},{945.849792,1183.597290},{955.378418,1210.828491},{965.774902,1237.740234},{977.028564,1264.304932},{989.127991,1290.495239},{1002.060547,1316.284302},{1015.813049,1341.645630},{1030.371582,1366.553345},{1045.720703,1390.981445},{1061.844971,1414.905029},{1078.727783,1438.299438},{1096.351562,1461.140747},{1114.698608,1483.405518},{1133.749756,1505.070801},{1153.485474,1526.114258},{1173.885620,1546.514404},{1194.929077,1566.250122},{1216.594238,1585.301270},{1238.859131,1603.648438},{1261.700562,1621.272217},{1285.094971,1638.155029},{1309.018555,1654.279297},{1333.446655,1669.628418},{1358.354126,1684.186768},{1383.715454,1697.939331},{1409.504761,1710.872070},{1435.695068,1722.971436},{1462.259644,1734.225098},{1489.171387,1744.621582},{1516.402588,1754.150146},{1543.925171,1762.801025},{1571.710938,1770.565430},{1599.731201,1777.435059},{1627.957153,1783.403320},{1656.359985,1788.463623},{1684.910522,1792.611084},{1713.579346,1795.841187},{1742.336792,1798.150879},{1771.153564,1799.537598},{1800.000000,1800.000000},{1800.000000,1800.000000},{1818.000000,1800.000000},{1836.000000,1800.000000},{1854.000000,1800.000000},{1872.000000,1800.000000},{1890.000000,1800.000000},{1908.000000,1800.000000},{1926.000000,1800.000000},{1944.000000,1800.000000},{1962.000000,1800.000000},{1980.000000,1800.000000},{1998.000000,1800.000000},{2016.000000,1800.000000},{2034.000000,1800.000000},{2052.000000,1800.000000},{2070.000000,1800.000000},{2088.000000,1800.000000},{2106.000000,1800.000000},{2124.000000,1800.000000},{2142.000000,1800.000000},{2160.000000,1800.000000},{2178.000000,1800.000000},{2196.000000,1800.000000},{2214.000000,1800.000000},{2232.000000,1800.000000},{2250.000000,1800.000000},{2268.000000,1800.000000},{2286.000000,1800.000000},{2304.000000,1800.000000},{2322.000000,1800.000000},{2340.000000,1800.000000},{2358.000000,1800.000000},{2376.000000,1800.000000},{2394.000000,1800.000000},{2412.000000,1800.000000},{2430.000000,1800.000000},{2448.000000,1800.000000},{2466.000000,1800.000000},{2484.000000,1800.000000},{2502.000000,1800.000000},{2520.000000,1800.000000},{2538.000000,1800.000000},{2556.000000,1800.000000},{2574.000000,1800.000000},{2592.000000,1800.000000},{2610.000000,1800.000000},{2628.000000,1800.000000},{2646.000000,1800.000000},{2664.000000,1800.000000},{2682.000000,1800.000000}};
+#endif