ProcessEnvironment.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Исходный код среды исполнения ПВТ-ОО.

    Этот исходный код является частью проекта ПВТ-ОО.

    Copyright © 2021 Малик Разработчик

    Это свободная программа: вы можете перераспространять её и/или
    изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она может быть полезна,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <http://www.gnu.org/licenses/>.
*/

package platform.dependent;

import avt.io.*;

public final class ProcessEnvironment(Object)
{
    public static final ProcessEnvironment instance;

    public static { instance = new ProcessEnvironment(); }


    private final Object fldCurrentDirectoryMonitor;
    private final ByteWriter fldStandardOutput;
    private final ByteWriter fldStandardError;
    private final ByteReader fldStandardInput;

    private () {
        fldCurrentDirectoryMonitor = new Object();
        fldStandardOutput = new MSWindowsFileSystemOutputStream(Kernel32.getStdHandle(Kernel32.STD_OUTPUT));
        fldStandardError = new MSWindowsFileSystemOutputStream(Kernel32.getStdHandle(Kernel32.STD_ERROR));
        fldStandardInput = new MSWindowsFileSystemInputStream(Kernel32.getStdHandle(Kernel32.STD_INPUT));
    }

    public String[] getArguments() throws Exception {
        long2 cmdlineDescriptor = Kernel32.getCommandLine();
        char[] cmdline = (char[]) char[].class.newArrayAt(cmdlineDescriptor[0], (int) cmdlineDescriptor[1]);
        int length = cmdline.length;
        int count = length > 0 && cmdline[length - 1] > ' ' ? 1 : 0;
        for(boolean quote = false, int i = 0; i < length; i++)
        {
            if(cmdline[i] == '\"') quote = !quote;
            if(!quote && i > 0 && cmdline[i - 1] > ' ' && cmdline[i] == ' ') count++;
        }
        String[] result = new String[count];
        for(boolean quote = false, int b = count = 0, int i = 0; i < length; i++)
        {
            if(!quote && cmdline[i] > ' ' && (i > 0 && cmdline[i - 1] == ' ' || i == 0)) b = i;
            if(cmdline[i] == '\"') quote = !quote;
            if(!quote && cmdline[i] > ' ' && (i < length - 1 && cmdline[i + 1] == ' ' || i == length - 1))
            {
                result[count++] = cmdline[i] == '\"' ? new String(cmdline, b + 1, i - b - 1) : new String(cmdline, b, i - b + 1);
            }
        }
        if(count > 0)
        {
            char[] exepath = new char[Platform.instance.localFileSystem.getObjectNameMaximumLength() + 2];
            length = Kernel32.getModuleFileName(0L, exepath.getPointer() + 2L, exepath.length - 1) + 1;
            for(exepath[0] = '/', int i = 1; i < length; i++) if(exepath[i] == '\\') exepath[i] = '/';
            result[0] = new String(exepath, 0, length);
        }
        return result;
    }

    public ByteWriter standardOutput { read = fldStandardOutput }

    public ByteWriter standardError { read = fldStandardError }

    public ByteReader standardInput { read = fldStandardInput }

    public String currentDirectory { read = getCurrentDirectory, write = setCurrentDirectory }

    private void setCurrentDirectory(String newCurrentDirectory) {
        if(newCurrentDirectory == null)
        {
            throw new NullPointerException("аргумент newCurrentDirectory равен нулевой ссылке");
        }
        StringBuilder path = new StringBuilder(newCurrentDirectory.length + 1) + newCurrentDirectory;
        if(!newCurrentDirectory.endsWith("/")) path + '/';
        int length = path.length;
        if(length < 4 || length - 1 > Platform.instance.localFileSystem.getObjectNameMaximumLength() || path[0] != '/' || !MSWindowsFileSystem.isDriveLetter(path[1]) || path[2] != ':' || path[3] != '/' || newCurrentDirectory.indexOf('\\') >= 0 || newCurrentDirectory.indexOf(0) >= 0)
        {
            throw new IllegalArgumentException("аргумент newCurrentDirectory имеет недопустимое значение");
        }
        for(int i = length = path.delete(0).length; i-- > 0; ) if(path[i] == '/') path[i] = '\\';
        char[] pathName = new char[length + 1];
        path.getChars(0, length, pathName, 0);
        int result;
        synchronized(fldCurrentDirectoryMonitor)
        {
            result = Kernel32.setCurrentDirectory(pathName.getPointer());
        }
        if(result == 0)
        {
            throw new IllegalArgumentException("аргумент newCurrentDirectory не удалось установить как текущую папку");
        }
    }

    private String getCurrentDirectory() {
        int length;
        char[] pathName;
        synchronized(fldCurrentDirectoryMonitor)
        {
            pathName = new char[length = Kernel32.getCurrentDirectory(0, 0L)];
            Kernel32.getCurrentDirectory(length, pathName.getPointer());
        }
        StringBuilder path = (new StringBuilder(length-- + 1)).append('/').append(pathName, 0, length);
        if(path[length] != '\\') path + '/';
        for(int i = path.length; i-- > 0; ) if(path[i] == '\\') path[i] = '/';
        return path.toString();
    }
}