foundation-module: Replace spaces in file names to underscores.

This commit is contained in:
AwesomeAdam54321 2024-03-07 15:48:31 +08:00
parent 7c2efe9851
commit 4b2c8bd3ff
42 changed files with 100 additions and 82 deletions

View file

@ -18,10 +18,7 @@ operating system, and the other one on Windows.
@ Some basics that apply to all POSIX-supporting systems. @ Some basics that apply to all POSIX-supporting systems.
@d FOLDER_SEPARATOR '/' <<*>>=
@d SHELL_QUOTE_CHARACTER '\''
= (very early code)
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
@ -30,80 +27,92 @@ operating system, and the other one on Windows.
#include <limits.h> #include <limits.h>
#include <unistd.h> #include <unistd.h>
@h Mac OS X. ^"ifdef-PLATFORM_MACOS" #define FOLDER_SEPARATOR '/'
#define SHELL_QUOTE_CHARACTER '\''
@d PLATFORM_STRING "macos" @ \section{Mac OS X.}
@d SHELL_QUOTE_CHARACTER '\'' <<*>>=
@d INFORM_FOLDER_RELATIVE_TO_HOME "Library" #ifdef PLATFORM_MACOS
@h Generic Unix. ^"ifdef-PLATFORM_UNIX" #define PLATFORM_STRING "macos"
#define SHELL_QUOTE_CHARACTER '\''
#define INFORM_FOLDER_RELATIVE_TO_HOME "Library"
@ \section{Generic Unix.}
<<*>>=
#ifdef PLATFORM_UNIX
@ These settings are used both for the Linux versions (both command-line, by
Adam Thornton, and for Ubuntu, Fedora, Debian and so forth, by Philip
Chimento) and also for Solaris variants: they can probably be used for any
Unix-based system.
#define PLATFORM_STRING "unix"
#define INFORM_FOLDER_RELATIVE_TO_HOME ""
<<*>>=
#include <strings.h>
@ \section{Linux.}
These settings are used both for the Linux versions (both command-line, by These settings are used both for the Linux versions (both command-line, by
Adam Thornton, and for Ubuntu, Fedora, Debian and so forth, by Philip Adam Thornton, and for Ubuntu, Fedora, Debian and so forth, by Philip
Chimento) and also for Solaris variants: they can probably be used for any Chimento) and also for Solaris variants: they can probably be used for any
Unix-based system. Unix-based system.
@d PLATFORM_STRING "unix" <<*>>=
@d INFORM_FOLDER_RELATIVE_TO_HOME "" #ifdef PLATFORM_LINUX
#define PLATFORM_STRING "linux"
#define INFORM_FOLDER_RELATIVE_TO_HOME ""
= (very early code) <<*>>=
#include <strings.h> #include <strings.h>
@h Linux. ^"ifdef-PLATFORM_LINUX" @ \section{Android.}
These settings are used both for the Linux versions (both command-line, by
Adam Thornton, and for Ubuntu, Fedora, Debian and so forth, by Philip
Chimento) and also for Solaris variants: they can probably be used for any
Unix-based system.
@d PLATFORM_STRING "linux"
@d INFORM_FOLDER_RELATIVE_TO_HOME ""
= (very early code)
#include <strings.h>
@h Android. ^"ifdef-PLATFORM_ANDROID"
These settings are used for Nathan Summers's Android versions. These settings are used for Nathan Summers's Android versions.
@d PLATFORM_STRING "android" <<*>>=
@d SUPPRESS_MAIN #ifdef PLATFORM_ANDROID
@d INFORM_FOLDER_RELATIVE_TO_HOME "" #define PLATFORM_STRING "android"
#define SUPPRESS_MAIN
#define INFORM_FOLDER_RELATIVE_TO_HOME ""
= (very early code) <<*>>=
#include <strings.h> #include <strings.h>
@h Folder separator. @ \section{Folder separator.}
When using a Unix-like system such as Cygwin on Windows, it's inevitable that When using a Unix-like system such as Cygwin on Windows, it's inevitable that
paths will sometimes contain backslashes and sometimes forward slashes, meaning paths will sometimes contain backslashes and sometimes forward slashes, meaning
a folder (i.e. directory) divide in either case. So: a folder (i.e. directory) divide in either case. So:
(a) When writing such a divider, always write |FOLDER_SEPARATOR|, a backslash; (a) When writing such a divider, always write |FOLDER_SEPARATOR|, a backslash;
(b) When testing for such a divider, call the following. (b) When testing for such a divider, call the following.
= <<*>>=
int Platform::is_folder_separator(wchar_t c) { int Platform::is_folder_separator(wchar_t c) {
return (c == FOLDER_SEPARATOR); return (c == FOLDER_SEPARATOR);
} }
@h Locale. @ \section{Locale.}
The following definition handles possible differences of text encoding The following definition handles possible differences of text encoding
in filenames, which depend on the current "locale". Locale is an odd piece in filenames, which depend on the current "locale". Locale is an odd piece
of old Unix terminology, but one thing it includes is how the textual names of old Unix terminology, but one thing it includes is how the textual names
of files are encoded (as ASCII, as ISO Latin-1, as UTF-8, etc.). The default of files are encoded (as ASCII, as ISO Latin-1, as UTF-8, etc.). The default
here is UTF-8 since OS X and Linux both adopt this. here is UTF-8 since OS X and Linux both adopt this.
= <<*>>=
#ifndef LOCALE_IS_ISO #ifndef LOCALE_IS_ISO
#ifndef LOCALE_IS_UTF8 #ifndef LOCALE_IS_UTF8
#define LOCALE_IS_UTF8 1 #define LOCALE_IS_UTF8 1
#endif #endif
#endif #endif
@h Environment variables. @ \section{Environment variables.}
= <<*>>=
char *Platform::getenv(const char *name) { char *Platform::getenv(const char *name) {
return getenv(name); return getenv(name);
} }
@h Executable location. ^"ifdef-PLATFORM_LINUX" @ \section{Executable location.}
Fill the wide-char buffer |p| with the path to the current executable, up to Fill the wide-char buffer |p| with the path to the current executable, up to
length |length|. This function is guaranteed to be called from only one length |length|. This function is guaranteed to be called from only one
thread. Should the information be unavailable, or fail to fit into |p|, thread. Should the information be unavailable, or fail to fit into |p|,
@ -111,7 +120,8 @@ truncate |p| to zero length. (On some platforms, the information will
always be unavailable: that doesn't mean we can't run on those platforms, always be unavailable: that doesn't mean we can't run on those platforms,
just that installation and use of Foundation-built tools is less convenient.) just that installation and use of Foundation-built tools is less convenient.)
= <<*>>=
ifdef PLATFORM_LINUX
void Platform::where_am_i(wchar_t *p, size_t length) { void Platform::where_am_i(wchar_t *p, size_t length) {
char buffer[PATH_MAX + 1]; char buffer[PATH_MAX + 1];
@<Follow the proc filesystem symlink to the real filesystem's file@>; @<Follow the proc filesystem symlink to the real filesystem's file@>;
@ -123,7 +133,7 @@ Follow that link to find the path. Normally when reading a symlink, one uses
|lstat()| to find the path length instead of guessing |PATH_MAX|, but the |lstat()| to find the path length instead of guessing |PATH_MAX|, but the
symlinks in |/proc| are special and don't provide a length to |lstat()|. symlinks in |/proc| are special and don't provide a length to |lstat()|.
@<Follow the proc filesystem symlink to the real filesystem's file@> = <<Follow the proc filesystem symlink to the real filesystem's file>>=
ssize_t link_len = readlink("/proc/self/exe", buffer, PATH_MAX); ssize_t link_len = readlink("/proc/self/exe", buffer, PATH_MAX);
if (link_len < 0) @<Fail@>; // unable to find if (link_len < 0) @<Fail@>; // unable to find
buffer[link_len] = '\0'; buffer[link_len] = '\0';
@ -132,13 +142,14 @@ symlinks in |/proc| are special and don't provide a length to |lstat()|.
encoding, and possibly in a multibyte encoding such as UTF-8) to a wide-char encoding, and possibly in a multibyte encoding such as UTF-8) to a wide-char
string. string.
@<Transcode buffer, which is locale-encoded, into the wide-char buffer@> = <<Transcode buffer, which is locale-encoded, into the wide-char buffer>>=
size_t convert_len = mbstowcs(p, buffer, length); size_t convert_len = mbstowcs(p, buffer, length);
if (convert_len == (size_t)-1) @<Fail@>; // wouldn't fit if (convert_len == (size_t)-1) @<Fail@>; // wouldn't fit
@ And now the Mac version: ^"ifdef-PLATFORM_MACOS" @ And now the Mac version:
= (very early code) <<*>>=
#ifdef PLATFORM_MACOS
int _NSGetExecutablePath(char* buf, uint32_t* bufsize); int _NSGetExecutablePath(char* buf, uint32_t* bufsize);
void Platform::where_am_i(wchar_t *p, size_t length) { void Platform::where_am_i(wchar_t *p, size_t length) {
@ -160,34 +171,35 @@ void Platform::where_am_i(wchar_t *p, size_t length) {
if (convert_len == (size_t)-1) @<Fail@>; if (convert_len == (size_t)-1) @<Fail@>;
} }
@ For Unix, there's nothing we can generically do. ^"ifdef-PLATFORM_UNIX" @ For Unix, there's nothing we can generically do. #ifdef PLATFORM_UNIX"
= <<*>>=
void Platform::where_am_i(wchar_t *p, size_t length) { void Platform::where_am_i(wchar_t *p, size_t length) {
@<Fail@>; @<Fail@>;
} }
@ On Android, there's no real need for this. ^"ifdef-PLATFORM_ANDROID" @ On Android, there's no real need for this. #ifdef PLATFORM_ANDROID"
= <<*>>=
void Platform::where_am_i(wchar_t *p, size_t length) { void Platform::where_am_i(wchar_t *p, size_t length) {
@<Fail@>; @<Fail@>;
} }
@ All of the above make use of: @ All of the above make use of:
@<Fail@> = <<Fail>>=
p[0] = '\0'; p[0] = '\0';
return; return;
@h Shell commands. ^"ifndef-PLATFORM_MACOS" @ \section{Shell commands.}
= <<*>>=
#ifndef PLATFORM_MACOS
int Platform::system(const char *cmd) { int Platform::system(const char *cmd) {
return system(cmd); return system(cmd);
} }
@ ^"ifdef-PLATFORM_MACOS" @
In MacOS 10.5, a new implementation of the C standard library In MacOS 10.5, a new implementation of the C standard library
crippled performance of |system()| by placing it behind a global mutex, so crippled performance of |system()| by placing it behind a global mutex, so
that it was impossible for two cores to be calling the function at the same that it was impossible for two cores to be calling the function at the same
@ -207,7 +219,8 @@ about signal-handling -- led to obscure and unrepeatable memory corruption
bugs in Intest, with the worker threads apparently writing on each other's bugs in Intest, with the worker threads apparently writing on each other's
memory space. Using |posix_spawn()| instead appears to work better. memory space. Using |posix_spawn()| instead appears to work better.
= <<*>>=
#ifdef PLATFORM_MACOS
#include <spawn.h> #include <spawn.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -227,9 +240,9 @@ int Platform::system(const char *cmd) {
return -1; return -1;
} }
@h Directory handling. @ \section{ Directory handling.}
= <<*>>=
int Platform::mkdir(char *transcoded_pathname) { int Platform::mkdir(char *transcoded_pathname) {
errno = 0; errno = 0;
int rv = mkdir(transcoded_pathname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); int rv = mkdir(transcoded_pathname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
@ -263,14 +276,14 @@ void Platform::closedir(void *D) {
closedir(dirp); closedir(dirp);
} }
@h Timestamp and file size. @ \section{ Timestamp and file size.
There are implementations of the C standard library where |time_t| has There are implementations of the C standard library where |time_t| has
super-weird behaviour, but on almost all POSIX systems, time 0 corresponds to super-weird behaviour, but on almost all POSIX systems, time 0 corresponds to
midnight on 1 January 1970. All we really need is that the "never" value midnight on 1 January 1970. All we really need is that the "never" value
is one which is earlier than any possible timestamp on the files we'll is one which is earlier than any possible timestamp on the files we'll
be dealing with. be dealing with.
= <<*>>=
time_t Platform::never_time(void) { time_t Platform::never_time(void) {
return (time_t) 0; return (time_t) 0;
} }
@ -287,14 +300,14 @@ off_t Platform::size(char *transcoded_filename) {
return (off_t) 0; return (off_t) 0;
} }
@h Sync. @ \section{Sync.}
Both names here are of directories which do exist. The function makes Both names here are of directories which do exist. The function makes
the |dest| tree an exact copy of the |source| tree (and therefore deletes the |dest| tree an exact copy of the |source| tree (and therefore deletes
anything different which was originally in |dest|). anything different which was originally in |dest|).
In POSIX world, we can fairly well depend on |rsync| being around: In POSIX world, we can fairly well depend on |rsync| being around:
= <<*>>=
void Platform::rsync(char *transcoded_source, char *transcoded_dest) { void Platform::rsync(char *transcoded_source, char *transcoded_dest) {
char rsync_command[10*MAX_FILENAME_LENGTH]; char rsync_command[10*MAX_FILENAME_LENGTH];
sprintf(rsync_command, "rsync -a --delete "); sprintf(rsync_command, "rsync -a --delete ");
@ -317,14 +330,14 @@ void Platform::quote_text(char *quoted, char *raw, int terminate) {
quoted[qp++] = 0; quoted[qp++] = 0;
} }
@h Sleep. @ \section{Sleep.}
= <<*>>=
void Platform::sleep(int seconds) { void Platform::sleep(int seconds) {
sleep((unsigned int) seconds); sleep((unsigned int) seconds);
} }
@h Notifications. ^"ifdef-PLATFORM_MACOS" @ \section{Notifications.}
The "submarine" sound is a gloomy thunk; the "bell" is the three-tone rising The "submarine" sound is a gloomy thunk; the "bell" is the three-tone rising
alert noise which iPhones make when they receive texts, but which hackers of a alert noise which iPhones make when they receive texts, but which hackers of a
certain age will remember as the "I have ripped your music CD now" alert from certain age will remember as the "I have ripped your music CD now" alert from
@ -335,7 +348,8 @@ It is anybody's guess how long Apple will permit the shell command |osascript|
to survive, given the MacOS team's current hostility to scripting; we're to survive, given the MacOS team's current hostility to scripting; we're
actually running a one-line AppleScript here. actually running a one-line AppleScript here.
= <<*>>=
#ifdef-PLATFORM_MACOS
void Platform::notification(text_stream *text, int happy) { void Platform::notification(text_stream *text, int happy) {
char *sound_name = "Bell.aiff"; char *sound_name = "Bell.aiff";
if (happy == FALSE) sound_name = "Submarine.aiff"; if (happy == FALSE) sound_name = "Submarine.aiff";
@ -346,13 +360,14 @@ void Platform::notification(text_stream *text, int happy) {
DISCARD_TEXT(TEMP) DISCARD_TEXT(TEMP)
} }
@ ^"ifndef-PLATFORM_MACOS" @
= <<*>>=
#ifndef PLATFORM_MACOS
void Platform::notification(text_stream *text, int happy) { void Platform::notification(text_stream *text, int happy) {
} }
@h Terminal setup. @ \section{Terminal setup.}
The idea of this function is that if anything needs to be done to enable the The idea of this function is that if anything needs to be done to enable the
output of ANSI-standard coloured terminal output, then this function has the output of ANSI-standard coloured terminal output, then this function has the
chance to do it; similarly, it may need to configure itself to receive console chance to do it; similarly, it may need to configure itself to receive console
@ -361,19 +376,21 @@ find this).
On POSIX platforms, so far as we know, nothing need be done. On POSIX platforms, so far as we know, nothing need be done.
= <<*>>=
void Platform::configure_terminal(void) { void Platform::configure_terminal(void) {
} }
@h Concurrency. @ \section{Concurrency.}
The following abstracts the pthread library, so that it can all be done The following abstracts the pthread library, so that it can all be done
differently on Windows. differently on Windows.
= (very early code) <<*>>=
typedef pthread_t foundation_thread; typedef pthread_t foundation_thread;
typedef pthread_attr_t foundation_thread_attributes; typedef pthread_attr_t foundation_thread_attributes;
@ = @
<<*>>=
int Platform::create_thread(foundation_thread *pt, int Platform::create_thread(foundation_thread *pt,
const foundation_thread_attributes *pa, void *(*fn)(void *), void *arg) { const foundation_thread_attributes *pa, void *(*fn)(void *), void *arg) {
return pthread_create(pt, pa, fn, arg); return pthread_create(pt, pa, fn, arg);
@ -394,35 +411,36 @@ size_t Platform::get_thread_stack_size(foundation_thread_attributes *pa) {
return mystacksize; return mystacksize;
} }
@ ^"ifdef-PLATFORM_LINUX" @
This function returns the number of logical cores in the host computer -- This function returns the number of logical cores in the host computer --
i.e., twice the number of physical cores if there's hyperthreading. The i.e., twice the number of physical cores if there's hyperthreading. The
result is used as a guess for an appropriate number of simultaneous threads result is used as a guess for an appropriate number of simultaneous threads
to launch. to launch.
It's not easy to find a function which reliably does this on all POSIX platforms. It's not easy to find a function which reliably does this on all POSIX platforms.
On Linux we can use |sys/sysinfo.h|, but this header is a POSIX extension which On Linux we can use |sys/sysinfo.h|, but this section is a POSIX extension which
MacOS does not support. MacOS does not support.
= (very early code) <<*>>=
#ifdef PLATFORM_LINUX
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
@ ^"ifdef-PLATFORM_LINUX" @ #ifdef PLATFORM_LINUX"
= <<*>>=
int Platform::get_core_count(void) { int Platform::get_core_count(void) {
int N = get_nprocs(); int N = get_nprocs();
if (N < 1) return 1; if (N < 1) return 1;
return N; return N;
} }
@ ^"ifdef-PLATFORM_MACOS" @ #ifdef PLATFORM_MACOS"
While MacOS lacks |sysinfo.h|, it does have |sysctl.h|: While MacOS lacks |sysinfo.h|, it does have |sysctl.h|:
= (very early code) <<*>>=
#include <sys/sysctl.h> #include <sys/sysctl.h>
@ ^"ifdef-PLATFORM_MACOS" @ #ifdef PLATFORM_MACOS"
= <<*>>=
int Platform::get_core_count(void) { int Platform::get_core_count(void) {
int N; int N;
size_t N_size = sizeof(int); size_t N_size = sizeof(int);
@ -431,17 +449,17 @@ int Platform::get_core_count(void) {
return N; return N;
} }
@ ^"ifdef-PLATFORM_ANDROID" @ #ifdef PLATFORM_ANDROID"
For Android it seems prudent simply to ignore multithreading: For Android it seems prudent simply to ignore multithreading:
= <<*>>=
int Platform::get_core_count(void) { int Platform::get_core_count(void) {
return 1; return 1;
} }
@h Mutexes. @ \section{Mutexes.}
@d CREATE_MUTEX(name) #define CREATE_MUTEX(name)
static pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER;
@d LOCK_MUTEX(name) pthread_mutex_lock(&name); #define LOCK_MUTEX(name) pthread_mutex_lock(&name);
@d UNLOCK_MUTEX(name) pthread_mutex_unlock(&name); #define UNLOCK_MUTEX(name) pthread_mutex_unlock(&name);