mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Added path::home_directory, path::documents_directory, path::videos_directory, path::pictures_directory, path::desktop_directory, path::screenshots_directory,
`path::public_share_directory`, `path::templates_directory`, `path::saved_games_directory`, `path::music_directory`, `path::downloads_directory`. Fix codegen bug in expressions like `foo(x()) ?? io::EOF?` causing irregular crashes.
This commit is contained in:
committed by
Christoffer Lerno
parent
cbd415881b
commit
69b3263a00
@@ -35,6 +35,7 @@ faultdef
|
||||
NO_PERMISSION,
|
||||
OUT_OF_SPACE,
|
||||
OVERFLOW,
|
||||
PATH_COULD_NOT_BE_FOUND,
|
||||
READ_ONLY,
|
||||
SYMLINK_FAILED,
|
||||
TOO_MANY_DESCRIPTORS,
|
||||
|
||||
@@ -1,5 +1,112 @@
|
||||
module std::io::os;
|
||||
|
||||
enum NativeSystemDir
|
||||
{
|
||||
DESKTOP,
|
||||
DOCUMENTS,
|
||||
VIDEOS,
|
||||
MUSIC,
|
||||
DOWNLOADS,
|
||||
PICTURES,
|
||||
TEMPLATES,
|
||||
PUBLIC_SHARE,
|
||||
SAVED_GAMES,
|
||||
SCREENSHOTS
|
||||
}
|
||||
|
||||
module std::io::os @if(env::LIBC);
|
||||
import std::io::path, std::os;
|
||||
import std::io, std::os;
|
||||
|
||||
fn String? win32_get_known_folder_temp(Win32_REFKNOWNFOLDERID rfid) @private @if(env::WIN32)
|
||||
{
|
||||
Win32_PWSTR path;
|
||||
Win32_HRESULT res = win32::shGetKnownFolderPath(rfid, 0x00008000 /* KF_FLAG_CREATE */, null, &path);
|
||||
if (res) return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
return string::from_wstring(tmem, (WString)path);
|
||||
}
|
||||
|
||||
fn Path? native_home_directory(Allocator allocator) => @pool()
|
||||
{
|
||||
$switch env::OS_TYPE:
|
||||
$case IOS:
|
||||
$case MACOS:
|
||||
$case TVOS:
|
||||
$case WATCHOS:
|
||||
$case FREEBSD:
|
||||
$case KFREEBSD:
|
||||
$case LINUX:
|
||||
$case NETBSD:
|
||||
$case OPENBSD:
|
||||
$case HAIKU:
|
||||
return path::new(allocator, env::tget_var("HOME")) ?? io::PATH_COULD_NOT_BE_FOUND?;
|
||||
$case WIN32:
|
||||
return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_PROFILE));
|
||||
$default:
|
||||
return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
$endswitch
|
||||
}
|
||||
|
||||
fn Path? native_user_directory(Allocator allocator, NativeSystemDir dir) => @pool()
|
||||
{
|
||||
$switch env::OS_TYPE:
|
||||
$case FREEBSD:
|
||||
$case KFREEBSD:
|
||||
$case LINUX:
|
||||
$case NETBSD:
|
||||
$case OPENBSD:
|
||||
$case HAIKU:
|
||||
switch (dir)
|
||||
{
|
||||
case DESKTOP: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "DESKTOP"));
|
||||
case DOWNLOADS: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "DOWNLOAD"));
|
||||
case DOCUMENTS: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "DOCUMENTS"));
|
||||
case MUSIC: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "MUSIC"));
|
||||
case VIDEOS: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "VIDEOS"));
|
||||
case PICTURES: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "PICTURES"));
|
||||
case PUBLIC_SHARE: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "PUBLICSHARE"));
|
||||
case TEMPLATES: return path::new(allocator, posix::xdg_user_dir_lookup(tmem, "TEMPLATES"));
|
||||
case SAVED_GAMES:
|
||||
case SCREENSHOTS: nextcase;
|
||||
default: return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
}
|
||||
$case IOS:
|
||||
$case MACOS:
|
||||
$case WATCHOS:
|
||||
$case TVOS:
|
||||
switch (dir)
|
||||
{
|
||||
case DESKTOP: return path::new(allocator, darwin::find_first_directory_temp(DESKTOP, USER));
|
||||
case DOWNLOADS: return path::new(allocator, darwin::find_first_directory_temp(DOWNLOADS, USER));
|
||||
case DOCUMENTS: return path::new(allocator, darwin::find_first_directory_temp(DOCUMENT, USER));
|
||||
case MUSIC: return path::new(allocator, darwin::find_first_directory_temp(MUSIC, USER));
|
||||
case VIDEOS: return path::new(allocator, darwin::find_first_directory_temp(MOVIES, USER));
|
||||
case PICTURES: return path::new(allocator, darwin::find_first_directory_temp(PICTURES, USER));
|
||||
case PUBLIC_SHARE: return path::new(allocator, darwin::find_first_directory_temp(SHARED_PUBLIC, USER));
|
||||
case SAVED_GAMES:
|
||||
case SCREENSHOTS:
|
||||
case TEMPLATES: nextcase;
|
||||
default: return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
}
|
||||
$case WIN32:
|
||||
switch (dir)
|
||||
{
|
||||
case DOWNLOADS: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_DOWNLOADS));
|
||||
case DOCUMENTS: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_DOCUMENTS));
|
||||
case DESKTOP: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_DESKTOP));
|
||||
case MUSIC: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_MUSIC));
|
||||
case VIDEOS: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_VIDEOS));
|
||||
case PICTURES: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_PICTURES));
|
||||
case SAVED_GAMES: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_SAVED_GAMES));
|
||||
case SCREENSHOTS: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_SCREENSHOTS));
|
||||
case TEMPLATES: return path::new(allocator, win32_get_known_folder_temp(&win32::FOLDERID_TEMPLATES));
|
||||
case PUBLIC_SHARE: nextcase;
|
||||
default: return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
}
|
||||
$default:
|
||||
return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
$endswitch
|
||||
}
|
||||
|
||||
|
||||
fn Path? native_temp_directory(Allocator allocator) @if(!env::WIN32)
|
||||
{
|
||||
@@ -23,7 +130,6 @@ fn Path? native_temp_directory(Allocator allocator) @if(env::WIN32) => @pool()
|
||||
module std::io::os @if(env::NO_LIBC);
|
||||
import std::io::path;
|
||||
|
||||
macro Path? native_temp_directory(Allocator allocator)
|
||||
{
|
||||
return io::UNSUPPORTED_OPERATION?;
|
||||
}
|
||||
macro Path? native_home_directory(Allocator allocator) => io::PATH_COULD_NOT_BE_FOUND?;
|
||||
macro Path? native_temp_directory(Allocator allocator) => io::PATH_COULD_NOT_BE_FOUND?;
|
||||
fn Path? native_user_directory(Allocator allocator, NativeSystemDir dir) => io::PATH_COULD_NOT_BE_FOUND?;
|
||||
|
||||
@@ -57,6 +57,18 @@ macro void? chdir(path)
|
||||
|
||||
fn Path? temp_directory(Allocator allocator) => os::native_temp_directory(allocator);
|
||||
|
||||
fn Path? home_directory(Allocator allocator) => os::native_home_directory(allocator);
|
||||
fn Path? desktop_directory(Allocator allocator) => os::native_user_directory(allocator, DESKTOP);
|
||||
fn Path? videos_directory(Allocator allocator) => os::native_user_directory(allocator, VIDEOS);
|
||||
fn Path? music_directory(Allocator allocator) => os::native_user_directory(allocator, MUSIC);
|
||||
fn Path? documents_directory(Allocator allocator) => os::native_user_directory(allocator, DOCUMENTS);
|
||||
fn Path? screenshots_directory(Allocator allocator) => os::native_user_directory(allocator, SCREENSHOTS);
|
||||
fn Path? saved_games_directory(Allocator allocator) => os::native_user_directory(allocator, SAVED_GAMES);
|
||||
fn Path? downloads_directory(Allocator allocator) => os::native_user_directory(allocator, DOWNLOADS);
|
||||
fn Path? pictures_directory(Allocator allocator) => os::native_user_directory(allocator, PICTURES);
|
||||
fn Path? templates_directory(Allocator allocator) => os::native_user_directory(allocator, TEMPLATES);
|
||||
fn Path? public_share_directory(Allocator allocator) => os::native_user_directory(allocator, PUBLIC_SHARE);
|
||||
|
||||
fn void? delete(Path path) => os::native_remove(path.str_view()) @inline;
|
||||
|
||||
macro bool @is_pathlike(#path) @const => $typeof(#path) == String ||| $typeof(#path) == Path;
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
module std::os::macos::cf @if(env::DARWIN) @link(env::DARWIN, "CoreFoundation.framework");
|
||||
|
||||
typedef CFArrayRef = void*;
|
||||
typedef CFArray = inline CFType;
|
||||
alias CFArrayRef = CFArray*;
|
||||
typedef CFArrayCallBacksRef = void*;
|
||||
typedef CFMutableArrayRef = void*;
|
||||
typedef CFMutableArray = inline CFArray;
|
||||
typedef CFMutableArrayRef = CFMutableArray*;
|
||||
|
||||
extern fn CFIndex CFArray.getCount(&self) @extern("CFArrayGetCount");
|
||||
extern fn void* CFArray.getValueAtIndex(&self, CFIndex i) @extern("CFArrayGetValueAtIndex");
|
||||
|
||||
extern fn CFArrayRef macos_CFArrayCreate(CFAllocatorRef allocator, void** values, CFIndex num_values, CFArrayCallBacksRef callBacks) @extern("CFArrayCreate") @builtin;
|
||||
extern fn CFArrayRef macos_CFArrayCopy(CFAllocatorRef allocator, CFArrayRef array) @extern("CFArrayCopy") @builtin;
|
||||
extern fn CFIndex macos_CFArrayGetCount(CFArrayRef array) @extern("CFArrayGetCount") @builtin;
|
||||
extern fn void macos_CFArrayAppendArray(CFMutableArrayRef theArray, CFArrayRef otherArray, CFRange otherRange) @extern("CFArrayAppendArray") @builtin;
|
||||
extern fn void CFMutableArray.appendArray(&self, CFArrayRef otherArray, CFRange otherRange) @extern("CFArrayAppendArray");
|
||||
extern fn void CFMutableArray.appendValue(&self, void *value) @extern("CFArrayAppendValue");
|
||||
|
||||
extern fn CFMutableArrayRef macos_CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, CFArrayCallBacksRef callBacks) @extern("CFArrayCreateMutable") @builtin;
|
||||
extern fn void macos_CFArrayAppendValue(CFMutableArrayRef theArray, void *value) @extern("CFArrayAppendValue") @builtin;
|
||||
|
||||
|
||||
@@ -1,13 +1,42 @@
|
||||
module std::os::macos::cf @if(env::DARWIN) @link(env::DARWIN, "CoreFoundation.framework");
|
||||
|
||||
typedef CFTypeRef = void*;
|
||||
typedef CFType = void;
|
||||
typedef CFTypeRef = CFType*;
|
||||
alias CFIndex = isz;
|
||||
|
||||
typedef CFString = inline CFType;
|
||||
alias CFStringRef = CFString*;
|
||||
|
||||
struct CFRange
|
||||
{
|
||||
CFIndex location;
|
||||
CFIndex length;
|
||||
}
|
||||
|
||||
extern fn CFTypeRef macos_CFRetain(CFTypeRef cf) @extern("CFRetain") @builtin;
|
||||
extern fn void macos_CFRelease(CFTypeRef cf) @extern("CFRelease") @builtin;
|
||||
extern fn ZString CFString.getCStringPtr(&self, CFStringEncoding encoding) @extern("CFStringGetCStringPtr");
|
||||
extern fn ZString CFString.getCString(&self, char* buffer, usz len, CFStringEncoding encoding) @extern("CFStringGetCString");
|
||||
|
||||
extern fn CFTypeRef CFType.retain(&self) @extern("CFRetain");
|
||||
extern fn void CFType.release(&self) @extern("CFRelease");
|
||||
extern fn CFIndex CFType.getRetainCount(&self) @extern("CFGetRetainCount");
|
||||
|
||||
enum CFStringEncoding : const uint
|
||||
{
|
||||
INVALID_ID = 0xffffffffU,
|
||||
MAC_ROMAN = 0,
|
||||
WINDOWS_LATIN_1 = 0x0500,
|
||||
ISO_LATIM_1 = 0x0201,
|
||||
NEXT_STEP_LATIN = 0x0B01,
|
||||
ASCII = 0x0600,
|
||||
UNICODE = 0x0100,
|
||||
UTF8 = 0x08000100,
|
||||
NON_LOSSY_ASCII = 0x0BFF,
|
||||
|
||||
UTF16 = 0x0100,
|
||||
UTF16BE = 0x10000100,
|
||||
UTF16LE = 0x14000100,
|
||||
|
||||
UTF32 = 0x0c000100,
|
||||
UTF32BE = 0x18000100,
|
||||
UTF32LE = 0x1c000100
|
||||
}
|
||||
|
||||
@@ -1,2 +1,60 @@
|
||||
module std::os::darwin @if(env::DARWIN);
|
||||
module std::os::darwin @if(env::DARWIN) @link("Foundation.framework");
|
||||
import std::os::macos::cf, std::os::macos::objc, std::io;
|
||||
|
||||
enum NSSearchPathDomainMask : const NSUInteger
|
||||
{
|
||||
USER = 1,
|
||||
LOCAL = 2,
|
||||
NETWORK = 4,
|
||||
SYSTEM = 8,
|
||||
ALL = 0x0ffff
|
||||
}
|
||||
|
||||
enum NSSearchPathDirectory : const NSUInteger
|
||||
{
|
||||
APPLICATION = 1,
|
||||
DEMO_APPLICATION,
|
||||
DEVELOPER_APPLICATION,
|
||||
ADMIN_APPLICATION,
|
||||
LIBRARY,
|
||||
DEVELOPER,
|
||||
USER,
|
||||
DOCUMENTATION,
|
||||
DOCUMENT,
|
||||
CORE_SERVICE,
|
||||
AUTOSAVED_INFORMATION,
|
||||
DESKTOP = 12,
|
||||
CACHES = 13,
|
||||
APPLICATION_SUPPORT = 14,
|
||||
DOWNLOADS = 15,
|
||||
INPUT_METHODS = 16,
|
||||
MOVIES = 17,
|
||||
MUSIC = 18,
|
||||
PICTURES = 19,
|
||||
PRINTER_DESCRIPTION = 20,
|
||||
SHARED_PUBLIC = 21,
|
||||
PREFERENCE_PANES = 22,
|
||||
APPLICATION_SCRIPTS = 23,
|
||||
ITEM_REPLACEMENT = 99,
|
||||
ALL_APPLICATIONS = 100,
|
||||
ALL_LIBRARIES = 101,
|
||||
TRASH = 102,
|
||||
}
|
||||
|
||||
// real signature in Foundation
|
||||
extern fn CFArrayRef nsSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, bool expandTilde) @extern("NSSearchPathForDirectoriesInDomains");
|
||||
|
||||
|
||||
|
||||
fn String? find_first_directory_temp(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask)
|
||||
{
|
||||
objc::@autoreleasepool()
|
||||
{
|
||||
CFArrayRef arr = nsSearchPathForDirectoriesInDomains(directory, domainMask, true);
|
||||
if (!arr.getCount()) return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
CFStringRef str = (CFStringRef)arr.getValueAtIndex(0);
|
||||
char* buffer = tmalloc(2048);
|
||||
if (!str.getCString(buffer, 2048, UTF8)) return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
return ((ZString)buffer).str_view();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ macro bool ObjcClass.equals(ObjcClass a, ObjcClass b) => a == b;
|
||||
fn ObjcId alloc(ObjcClass cls) => objc::msg_send(cls, SendVoid, "alloc");
|
||||
fn void release(ObjcId id) => objc::msg_send(id, SendVoid, "release");
|
||||
|
||||
alias NSUInteger = $typefrom(env::ARCH_64_BIT ??? ulong : uint);
|
||||
alias NSInteger = $typefrom(env::ARCH_64_BIT ??? long : int);
|
||||
|
||||
macro ObjcClass? class_by_name(ZString c)
|
||||
{
|
||||
ObjcClass cls = objc::lookUpClass(c);
|
||||
@@ -43,6 +46,15 @@ macro msg_send(id, $FunctionType, ZString $selector, ...)
|
||||
return (($FunctionType)&msgSend)((ObjcId)id, sel_getUid($selector), $vasplat);
|
||||
}
|
||||
|
||||
macro void @autoreleasepool(;@body())
|
||||
{
|
||||
void* ctx = objc_autoreleasePoolPush();
|
||||
defer objc_autoreleasePoolPop(ctx);
|
||||
@body();
|
||||
}
|
||||
|
||||
extern fn void* objc_autoreleasePoolPush();
|
||||
extern fn void objc_autoreleasePoolPop(void* context);
|
||||
extern fn ObjcClass getClass(ZString name) @extern("objc_getClass");
|
||||
extern fn int getClassList(ObjcClass* buffer, int buffer_count) @extern("objc_getClassList");
|
||||
extern fn ObjcClass lookUpClass(ZString name) @extern("objc_lookUpClass") @builtin;
|
||||
|
||||
16
lib/std/os/win32/shell32.c3
Normal file
16
lib/std/os/win32/shell32.c3
Normal file
@@ -0,0 +1,16 @@
|
||||
module std::os::win32 @if(env::WIN32) @link("shell32");
|
||||
|
||||
typedef Win32_REFKNOWNFOLDERID = Win32_KNOWNFOLDERID*;
|
||||
typedef Win32_KNOWNFOLDERID = Win32_GUID;
|
||||
extern fn Win32_HRESULT shGetKnownFolderPath(Win32_REFKNOWNFOLDERID rfid, Win32_DWORD dwFlags, Win32_HANDLE hToken, Win32_PWSTR* ppszPath) @extern("SHGetKnownFolderPath");
|
||||
|
||||
const Win32_KNOWNFOLDERID FOLDERID_PROFILE = { 0x5E6C858F, 0x0E22, 0x4760, x"9AFEEA3317B67173" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_DESKTOP = { 0xB4BFCC3A, 0xDB2C, 0x424C, x"B0297FE99A87C641" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_DOCUMENTS = { 0xFDD39AD0, 0x238F, 0x46AF, x"ADB46C85480369C7" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_DOWNLOADS = { 0x374de290, 0x123f, 0x4565, x"916439c4925e467b" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_MUSIC = { 0x4BD8D571, 0x6D19, 0x48D3, x"BE97422220080E43" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_PICTURES = { 0x33E28130, 0x4E1E, 0x4676, x"835A98395C3BC3BB" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_SAVED_GAMES = { 0x4c5c32ff, 0xbb9d, 0x43b0, x"b5b42d72e54eaaa4" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_SCREENSHOTS = { 0xb7bede81, 0xdf94, 0x4682, x"a7d857a52620b86f" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_TEMPLATES = { 0xA63293E8, 0x664E, 0x48DB, x"A079DF759E0509F7" };
|
||||
const Win32_KNOWNFOLDERID FOLDERID_VIDEOS = { 0x18989B1D, 0x99B5, 0x455B, x"841CAB7C74E4DDFC" };
|
||||
53
lib/std/os/xdg.c3
Normal file
53
lib/std/os/xdg.c3
Normal file
@@ -0,0 +1,53 @@
|
||||
module std::os::posix @if(env::POSIX);
|
||||
import std::io, std::os::env;
|
||||
|
||||
fn String? xdg_user_dir_lookup(Allocator allocator, String type) => @pool()
|
||||
{
|
||||
String home = env::tget_var("HOME")!;
|
||||
String config_file @noinit;
|
||||
if (try String config_home = env::tget_var("XDG_CONFIG_HOME") && config_home.len)
|
||||
{
|
||||
config_file = config_home.tconcat("/user-dirs.dirs");
|
||||
}
|
||||
else
|
||||
{
|
||||
config_file = home.tconcat("/.config/user-dirs.dirs");
|
||||
}
|
||||
File f = file::open(config_file, "r")!;
|
||||
defer (void)f.close();
|
||||
while (try line = io::treadline(&f))
|
||||
{
|
||||
line = line.trim();
|
||||
if (!line.starts_with("XDG_")) continue;
|
||||
line = line[4..];
|
||||
if (!line.starts_with(type)) continue;
|
||||
line = line[type.len ..];
|
||||
if (!line.starts_with("_DIR")) continue;
|
||||
line = line[4..];
|
||||
line = line.trim();
|
||||
if (!line.starts_with("=")) continue;
|
||||
line = line[1..].trim();
|
||||
if (!line.starts_with("\"")) continue;
|
||||
line = line[1..];
|
||||
bool relative = false;
|
||||
if (line.starts_with("$HOME/"))
|
||||
{
|
||||
relative = true;
|
||||
line = line[6..];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!line.starts_with("/")) continue;
|
||||
if (line.len < 2) continue;
|
||||
line = line[1..];
|
||||
}
|
||||
if (line.len < 1 || line[^1] != '"') continue;
|
||||
line = line[:^1];
|
||||
if (relative)
|
||||
{
|
||||
return string::format(allocator, "%s/%s", home, line);
|
||||
}
|
||||
return line.copy(allocator);
|
||||
}
|
||||
return io::PATH_COULD_NOT_BE_FOUND?;
|
||||
}
|
||||
Reference in New Issue
Block a user