https://github.com/JuliaLang/julia
Raw File
Tip revision: f07dea91e2bd598afff47bba1f90022e6c55adaa authored by Shuhei Kadowaki on 01 April 2022, 09:57:03 UTC
effects: define `Core.Compiler.infer_effects`
Tip revision: f07dea9
loader_win_utils.c
// This file is a part of Julia. License is MIT: https://julialang.org/license

// Workarounds for compiling via mingw without using libgcc_s
typedef struct {
    HANDLE fd;
    BOOL isconsole;
} FILE;

static FILE _stdout = { INVALID_HANDLE_VALUE };
static FILE _stderr = { INVALID_HANDLE_VALUE };

FILE *stdout = &_stdout;
FILE *stderr = &_stderr;

int loader_fwrite(const WCHAR *str, size_t nchars, FILE *out) {
    DWORD written;
    if (out->isconsole) {
        if (WriteConsole(out->fd, str, nchars, &written, NULL))
            return written;
    } else {
        if (WriteFile(out->fd, str, sizeof(WCHAR) * nchars, &written, NULL))
            return written;
    }
    return -1;
}

int loader_fputs(const char *str, FILE *out) {
    wchar_t wstr[1024];
    utf8_to_wchar(str, wstr, 1024);
    return fwrite(wstr, wcslen(wstr), out);
}

void * loader_malloc(const size_t size) {
    return HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, size);
}

void * loader_realloc(void * mem, const size_t size) {
    return HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, mem, size);
}

LPWSTR *CommandLineToArgv(LPWSTR lpCmdLine, int *pNumArgs) {
    LPWSTR out = lpCmdLine;
    LPWSTR cmd = out;
    unsigned MaxEntries = 4;
    unsigned backslashes = 0;
    int in_quotes = 0;
    int empty = 1;
    LPWSTR *cmds;
    *pNumArgs = 0;
    cmds = (LPWSTR*)malloc(sizeof(LPWSTR) * MaxEntries);
    while (1) {
        WCHAR c = *lpCmdLine++;
        switch (c) {
        case 0:
            if (!empty) {
                *out++ = '\0';
                cmds[(*pNumArgs)++] = cmd;
            }
            cmds[*pNumArgs] = NULL;
            return cmds;
        default:
            *out++ = c;
            empty = 0;
            break;
        case '"':
            out -= backslashes / 2; // remove half of the backslashes
            if (backslashes % 2)
                *(out - 1) = '"'; // replace \ with "
            else
                in_quotes = !in_quotes; // treat as quote delimater
            empty = 0;
            break;
        case '\t':
        case ' ':
            if (in_quotes) {
                *out++ = c;
            } else if (!empty) {
                *out++ = '\0';
                cmds[(*pNumArgs)++] = cmd;
                cmd = out;
                empty = 1;
                if (*pNumArgs >= MaxEntries - 1) {
                    MaxEntries *= 2;
                    cmds = (LPWSTR*)realloc(cmds, sizeof(LPWSTR) * MaxEntries);
                }
            }
        }
        if (c == '\\')
            backslashes++;
        else
            backslashes = 0;
    }
}

void setup_stdio() {
    DWORD mode = 0;
    _stdout.fd = GetStdHandle(STD_OUTPUT_HANDLE);
    _stdout.isconsole = GetConsoleMode(_stdout.fd, &mode);
    _stderr.fd = GetStdHandle(STD_ERROR_HANDLE);
    _stderr.isconsole = GetConsoleMode(_stderr.fd, &mode);
}

void loader_exit(int code) {
    ExitProcess(code);
}


/* Utilities to convert from Windows' wchar_t stuff to UTF-8 */
int wchar_to_utf8(const wchar_t * wstr, char *str, size_t maxlen) {
    /* Fast-path empty strings, as WideCharToMultiByte() returns zero for them. */
    if (wstr[0] == L'\0') {
        str[0] = '\0';
        return 1;
    }
    size_t len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
    if (!len)
        return 0;
    if (len > maxlen)
        return 0;
    if (!WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL))
        return 0;
    return 1;
}

int utf8_to_wchar(const char * str, wchar_t * wstr, size_t maxlen) {
    /* Fast-path empty strings, as WideCharToMultiByte() returns zero for them. */
    if (str[0] == '\0') {
        wstr[0] = L'\0';
        return 1;
    }
    size_t len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    if (!len)
        return 0;
    if (len > maxlen)
        return 0;
    if (!MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len))
        return 0;
    return 1;
}

size_t loader_strlen(const char * x) {
    int idx = 0;
    while (x[idx] != 0)
        idx++;
    return idx;
}

size_t loader_wcslen(const wchar_t * x) {
    int idx = 0;
    while (x[idx] != 0)
        idx++;
    return idx;
}

char * loader_strncat(char * base, const char * tail, size_t maxlen) {
    int base_len = strlen(base);
    int tail_len = strlen(tail);
    for (int idx=base_len; idx<min(maxlen, base_len + tail_len); ++idx) {
        base[idx] = tail[idx - base_len];
    }
    return base;
}

void * loader_memcpy(void * dest, const void * src, size_t len) {
    for (int idx=0; idx<len; ++idx) {
        ((char *)dest)[idx] = ((const char *)src)[idx];
    }
    return dest;
}

char * loader_dirname(char * x) {
    int idx = strlen(x);
    while (idx > 0 && x[idx] != PATHSEPSTRING[0]) {
        idx -= 1;
    }
    if (x[idx] == PATHSEPSTRING[0]) {
        // Special-case x == "/"
        if (idx == 0) {
            x[1] = '\0';
            return x;
        } else {
            x[idx] = '\0';
            return x;
        }
    }
    x[0] = '.';
    x[1] = '\0';
    return x;
}

char * loader_strchr(const char * haystack, int needle) {
    int idx=0;
    while (haystack[idx] != needle) {
        if (haystack[idx] == 0) {
            return NULL;
        }
        idx++;
    }
    return (char *)haystack + idx;
}
back to top