23 # include "TargetConditionals.h"
25 # include <mach-o/dyld.h>
26 # elif TARGET_OS_IPHONE
27 # elif TARGET_IPHONE_SIMULATOR
30 #elif defined _WIN32 || defined _WIN64
34 #define PATH_BUFFER_SIZE 4096
36 void perr(
const char* str) {
40 int qsort_int_cmp(
const void* a,
const void* b) {
41 return *((
int*)a) - *((
int*)b);
44 char* mstrcpy(
const char* str) {
45 char* strbuf = (
char*)malloc(
sizeof(
char) * (strlen(str) + 1));
51 char* mstrncpy(
const char* str,
size_t n) {
52 char* strbuf = (
char*)malloc(
sizeof(
char) * (n + 1));
54 strncpy(strbuf, str, n);
59 void skip_utf8_bom(FILE* fp) {
74 for (n = 0; n <= 2 && (bom[n] = getc(fp)) != EOF; n++) {}
78 if ((n < 3) || (bom[0] != 0xEF) || (bom[1] != 0xBB) || (bom[2] != 0xBF)) {
79 for (n--; n >= 0; n--) {
87 const char* executable_path(
void) {
88 static char path_buffer[PATH_BUFFER_SIZE];
89 static int calculated = 0;
93 ssize_t res = readlink(
"/proc/self/exe", path_buffer,
sizeof(path_buffer));
96 uint32_t size =
sizeof(path_buffer);
97 int res = _NSGetExecutablePath(path_buffer, &size);
99 #elif _WIN32 || _WIN64
108 char* last_sep = strrchr(path_buffer,
'/');
109 assert(last_sep != NULL);
116 char* try_open_file(
const char* path) {
118 FILE* fp = fopen(path,
"r");
122 return mstrcpy(path);
126 if (is_absolute_path(path)) {
131 const char* exe_dir = executable_path();
133 (
char*)malloc(
sizeof(
char) * (strlen(path) + strlen(exe_dir) + 2));
134 sprintf(filename,
"%s/%s", exe_dir, path);
135 fp = fopen(filename,
"r");
145 (
char*)malloc(
sizeof(
char) * (strlen(path) + strlen(PKGDATADIR) + 2));
146 sprintf(filename,
"%s/%s", PKGDATADIR, path);
147 fp = fopen(filename,
"r");
157 char* get_file_path(
const char* filename) {
158 const char* last_sep = strrchr(filename,
'/');
160 if (last_sep == NULL) {
163 char* path = mstrncpy(filename, last_sep - filename);
167 int is_absolute_path(
const char* path) {
168 if (path[0] ==
'/') {
172 if (path[1] ==
':') {