/*
Исходный код среды исполнения ПВТ-ОО.
Этот исходный код является частью проекта ПВТ-ОО.
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();
}
}