Skip to content

Commit a9579b2

Browse files
committed
Move get_program_file and get_sys_name into a C library until cosmocc fixes windowesque
jart/cosmopolitan#1380
1 parent 48aad7b commit a9579b2

File tree

5 files changed

+183
-99
lines changed

5 files changed

+183
-99
lines changed

.github/workflows/build.yml

+1-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@ on:
99

1010
jobs:
1111
build:
12-
strategy:
13-
matrix:
14-
os: [ubuntu-latest]
15-
arch: [x86_64]
16-
runs-on: ${{ matrix.os }}
12+
runs-on: ubuntu-latest
1713

1814
steps:
1915
- uses: actions/checkout@v4

src/main.cpp

+10-93
Original file line numberDiff line numberDiff line change
@@ -3,105 +3,22 @@
33
#include <string>
44

55
#include "tbox/tbox.h"
6+
#include "utils.h"
67

78
namespace fs = std::filesystem;
89

9-
#ifndef TB_CONFIG_OS_WINDOWS
10-
#include <unistd.h>
11-
#endif
12-
13-
14-
#if defined(TB_CONFIG_OS_WINDOWS)
15-
#include <windows.h>
16-
#elif defined(__COSMOPOLITAN__)
17-
#include <windowsesque.h>
18-
#include <sys/utsname.h>
19-
#endif
20-
21-
// proc/self
22-
#if defined(TB_CONFIG_OS_LINUX)
23-
# define XM_PROC_SELF_FILE "/proc/self/exe"
24-
#elif defined(TB_CONFIG_OS_BSD) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
25-
# if defined(__NetBSD__)
26-
# define XM_PROC_SELF_FILE "/proc/curproc/exe"
27-
# else
28-
# define XM_PROC_SELF_FILE "/proc/curproc/file"
29-
# endif
30-
#endif
31-
32-
std::string get_sys_name()
33-
{
34-
tb_char_t const* name = tb_null;
35-
#if defined(__COSMOPOLITAN__)
36-
struct utsname buffer;
37-
if (uname(&buffer) == 0)
38-
{
39-
if (tb_strstr(buffer.sysname, "Darwin"))
40-
name = "macosx";
41-
else if (tb_strstr(buffer.sysname, "Linux"))
42-
name = "linux";
43-
else if (tb_strstr(buffer.sysname, "Windows"))
44-
name = "windows";
45-
}
46-
#elif defined(TB_CONFIG_OS_WINDOWS)
47-
name = "windows";
48-
#elif defined(TB_CONFIG_OS_MACOSX)
49-
name = "macosx";
50-
#elif defined(TB_CONFIG_OS_LINUX)
51-
name = "linux";
52-
#endif
53-
return std::string(name);
10+
std::string get_sys_name() {
11+
std::string s(10, '\0');
12+
_get_sys_name(s.data());
13+
s.shrink_to_fit();
14+
return s;
5415
}
5516

5617
std::string get_program_file() {
57-
58-
std::string sysname = std::string(get_sys_name());
59-
std::string path = std::string(TB_PATH_MAXN, '\0');
60-
tb_size_t maxn = TB_PATH_MAXN;
61-
tb_bool_t ok = tb_false;
62-
63-
if(sysname == "windows") {
64-
#if defined(TB_CONFIG_OS_WINDOWS) || defined(__COSMOPOLITAN__)
65-
// get the executale file path as program directory
66-
tb_wchar_t buf[TB_PATH_MAXN] = {0};
67-
tb_size_t size = (tb_size_t)GetModuleFileNameW(tb_null, buf, (DWORD)TB_PATH_MAXN);
68-
// tb_assert_and_check_break(size < TB_PATH_MAXN);
69-
// end
70-
buf[size] = L'\0';
71-
size = tb_wcstombs(path.data(), buf, maxn);
72-
// tb_assert_and_check_break(size < maxn);
73-
path[size] = '\0';
74-
return path;
75-
#endif
76-
}
77-
else if(sysname == "linux") {
78-
#if defined(TB_CONFIG_OS_LINUX)
79-
// get the executale file path as program directory
80-
ssize_t size = readlink(XM_PROC_SELF_FILE, path.data(), (size_t)maxn);
81-
if (size > 0 && size < maxn)
82-
{
83-
path[size] = '\0';
84-
ok = tb_true;
85-
}
86-
#endif
87-
} else if(sysname == "macosx") {
88-
#if defined(TB_CONFIG_OS_MACOSX)
89-
/*
90-
* _NSGetExecutablePath() copies the path of the main executable into the buffer. The bufsize parameter
91-
* should initially be the size of the buffer. The function returns 0 if the path was successfully copied,
92-
* and *bufsize is left unchanged. It returns -1 if the buffer is not large enough, and *bufsize is set
93-
* to the size required.
94-
*
95-
* Note that _NSGetExecutablePath will return "a path" to the executable not a "real path" to the executable.
96-
* That is the path may be a symbolic link and not the real file. With deep directories the total bufsize
97-
* needed could be more than MAXPATHLEN.
98-
*/
99-
tb_uint32_t bufsize = (tb_uint32_t)maxn;
100-
if (!_NSGetExecutablePath(path.data(), &bufsize))
101-
ok = tb_true;
102-
#endif
103-
}
104-
return path;
18+
std::string s(TB_PATH_MAXN, '\0');
19+
_get_program_file(s.data());
20+
s.shrink_to_fit();
21+
return s;
10522
}
10623

10724
tb_int_t main(tb_int_t argc, tb_char_t** argv) {

src/utils.c

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#include <stdio.h>
2+
#include <uchar.h>
3+
#include "utils.h"
4+
5+
#ifndef TB_CONFIG_OS_WINDOWS
6+
#include <unistd.h>
7+
#endif
8+
9+
#if defined(TB_CONFIG_OS_WINDOWS)
10+
#include <windows.h>
11+
#elif defined(__COSMOPOLITAN__)
12+
#include <windowsesque.h>
13+
#include <sys/utsname.h>
14+
#define GetModuleFileNameW GetModuleFileName
15+
#endif
16+
17+
// proc/self
18+
#if defined(TB_CONFIG_OS_LINUX)
19+
# define XM_PROC_SELF_FILE "/proc/self/exe"
20+
#elif defined(TB_CONFIG_OS_BSD) && !defined(__OpenBSD__) && !defined(__FreeBSD__)
21+
# if defined(__NetBSD__)
22+
# define XM_PROC_SELF_FILE "/proc/curproc/exe"
23+
# else
24+
# define XM_PROC_SELF_FILE "/proc/curproc/file"
25+
# endif
26+
#endif
27+
28+
tb_size_t char16_wcslen(char16_t const* s)
29+
{
30+
tb_assert_and_check_return_val(s, 0);
31+
32+
__tb_register__ char16_t const* p = s;
33+
34+
#ifdef __tb_small__
35+
while (*p) p++;
36+
return (p - s);
37+
#else
38+
while (1)
39+
{
40+
if (!p[0]) return (p - s + 0);
41+
if (!p[1]) return (p - s + 1);
42+
if (!p[2]) return (p - s + 2);
43+
if (!p[3]) return (p - s + 3);
44+
p += 4;
45+
}
46+
return 0;
47+
#endif
48+
}
49+
50+
inline static tb_size_t char16_wcstombs_charset(tb_char_t* s1, char16_t const* s2, tb_size_t n)
51+
{
52+
// check
53+
tb_assert_and_check_return_val(s1 && s2, 0);
54+
55+
// init
56+
tb_long_t r = 0;
57+
tb_size_t l = char16_wcslen(s2);
58+
59+
// atow
60+
if (l)
61+
{
62+
tb_size_t e = (sizeof(char16_t) == 4) ? TB_CHARSET_TYPE_UTF32 : TB_CHARSET_TYPE_UTF16;
63+
r = tb_charset_conv_data(e | TB_CHARSET_TYPE_LE, TB_CHARSET_TYPE_UTF8, (tb_byte_t const*)s2, l * sizeof(char16_t), (tb_byte_t*)s1, n);
64+
}
65+
66+
// strip
67+
if (r >= 0) s1[r] = '\0';
68+
69+
// ok?
70+
return r > 0 ? r : -1;
71+
}
72+
73+
74+
void _get_sys_name(tb_char_t* name) {
75+
#if defined(__COSMOPOLITAN__)
76+
struct utsname buffer;
77+
if (uname(&buffer) == 0) {
78+
if (tb_strstr(buffer.sysname, "Darwin"))
79+
tb_strcpy(name, "macosx");
80+
else if (tb_strstr(buffer.sysname, "Linux"))
81+
tb_strcpy(name, "linux");
82+
else if (tb_strstr(buffer.sysname, "Windows"))
83+
tb_strcpy(name, "windows");
84+
}
85+
#elif defined(TB_CONFIG_OS_WINDOWS)
86+
tb_strcpy(name, "windows");
87+
#elif defined(TB_CONFIG_OS_MACOSX)
88+
tb_strcpy(name, "macosx");
89+
#elif defined(TB_CONFIG_OS_LINUX)
90+
tb_strcpy(name, "linux");
91+
#endif
92+
}
93+
94+
void _get_program_file(tb_char_t* path) {
95+
96+
tb_char_t sysname[16];
97+
_get_sys_name(sysname);
98+
tb_size_t maxn = TB_PATH_MAXN;
99+
tb_bool_t ok = tb_false;
100+
101+
if(tb_strstr(sysname, "windows")) {
102+
#if defined(TB_CONFIG_OS_WINDOWS) || defined(__COSMOPOLITAN__)
103+
// get the executale file path as program directory
104+
printf("%lld\n", sizeof(tb_wchar_t));
105+
#ifdef __COSMOPOLITAN__
106+
char16_t buf[TB_PATH_MAXN] = { 0 };
107+
tb_size_t size = (tb_size_t)GetModuleFileNameW((int64_t)tb_null, (char16_t*)buf, (DWORD)TB_PATH_MAXN);
108+
char16_wcstombs_charset(path, buf, maxn);
109+
#else
110+
tb_wchar_t buf[TB_PATH_MAXN] = { 0 };
111+
tb_size_t size = (tb_size_t)GetModuleFileNameW(tb_null, buf, TB_PATH_MAXN);
112+
buf[size] = L'\0';
113+
size = tb_wcstombs(path, buf, maxn);
114+
#endif
115+
path[size] = '\0';
116+
#endif
117+
}
118+
else if(tb_strstr(sysname, "linux")) {
119+
#if defined(TB_CONFIG_OS_LINUX)
120+
// get the executale file path as program directory
121+
ssize_t size = readlink(XM_PROC_SELF_FILE, path, (size_t)maxn);
122+
if (size > 0 && size < maxn)
123+
{
124+
path[size] = '\0';
125+
ok = tb_true;
126+
}
127+
#endif
128+
} else if(tb_strstr(sysname, "macosx")) {
129+
#if defined(TB_CONFIG_OS_MACOSX)
130+
/*
131+
* _NSGetExecutablePath() copies the path of the main executable into the buffer. The bufsize parameter
132+
* should initially be the size of the buffer. The function returns 0 if the path was successfully copied,
133+
* and *bufsize is left unchanged. It returns -1 if the buffer is not large enough, and *bufsize is set
134+
* to the size required.
135+
*
136+
* Note that _NSGetExecutablePath will return "a path" to the executable not a "real path" to the executable.
137+
* That is the path may be a symbolic link and not the real file. With deep directories the total bufsize
138+
* needed could be more than MAXPATHLEN.
139+
*/
140+
tb_uint32_t bufsize = (tb_uint32_t)maxn;
141+
if (!_NSGetExecutablePath(path, &bufsize))
142+
ok = tb_true;
143+
#endif
144+
}
145+
}

src/utils.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef UTILS_H
2+
#define UTILS_H
3+
#include "tbox/tbox.h"
4+
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
void _get_program_file(tb_char_t* path);
10+
void _get_sys_name(tb_char_t* path);
11+
12+
#ifdef __cplusplus
13+
}
14+
#endif
15+
16+
#endif

xmake.lua

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
add_rules("mode.debug", "mode.release")
22
set_languages("cxx17")
33

4-
add_requires("tbox")
4+
add_requires("tbox", {configs = {charset = true}})
55
add_requires("doctest")
66

77
target("gitignore_parser")
88
set_kind("static")
99
add_files("src/gitignore_parser.cpp")
1010
add_headerfiles("src/gitignore_parser.hpp")
1111

12+
target("utils")
13+
set_kind("static")
14+
add_files("src/utils.c")
15+
add_headerfiles("src/utils.h")
16+
add_packages("tbox")
17+
1218
target("synctignore")
1319
add_files("src/main.cpp")
1420
add_packages("tbox")
21+
add_deps("utils")
1522

1623
-- used for win32 api (also compospolitan)
1724
add_defines("UNICODE", "_UNICODE")
25+
-- if is_plat("windows") then
26+
-- add_ldflags("/LTCG")
27+
-- end
1828

1929
target("tests")
2030
set_default(false)

0 commit comments

Comments
 (0)