Thanks to Jacob Carlborg's suggestion
(news://new.digitalmars.com:119/k6d9se$i46$1...@digitalmars.com), I decided
to create my own little installer for MAC OSX. Albeit a very naive
implementation, it does what I ask it to do... (D2 only). Along the way,
I picked up a little understanding about I/O, so I decided to try my
hand at it. There are a whole lot of things my eyes doesn't yet see and
my brain doesn't yet grasp so I wanted to ask the community's making
this a better product.
The focus is on the I/O piece vice what's implemented in main().
Also, does D allow function scope extern(C) declarations? If so, what is
the proper way to do it? If not, why not? What would be the harm in
doing so?
I would like to make this completely unicode aware but had a little
trouble because I don't fully understand what I am doing.
Any suggestion would be greatly appreciated.
Andrew
----------
module io;
import std.process:system;
import core.sys.posix.sys.types;
import core.sys.posix.fcntl;
private static char[] rbuffer;
static this() {
rbuffer.length = 1024;
}
enum nl = "\n";
enum stdin = 0;
enum stdout = 1;
enum stderr = 2;
private extern (C) {
size_t write(int fd, const void* buf, size_t nbytes);
int open(in char* path, int oflags);
int open(in char* path, int oflags, mode_t mode);
int read(int fildes, void* buf, size_t nbytes);
int close(int filedes);
}
void emit(Args...)(const auto ref Args args) {
string buffer;
import std.traits:isPointer;
import std.string:xformat;
foreach (element; args) {
static if(isPointer!(typeof(element))) {
buffer ~= xformat("%s", *element);
} else {
buffer ~= xformat("%s", element);
}
}
write(stdout, buffer.ptr, buffer.length);
}
void emitln(Args...)(Args args)
{
emit(args, nl);
}
void save(Args...)(int fd, Args args)
{
import std.string:format;
string buffer = format("%s", args);
write(fd, buffer.ptr, buffer.length);
}
int scan(A)(ref A data)
{
import std.traits:isPointer, isNumeric, isSomeChar;
import std.algorithm:findAmong, stride;
import std.ascii:whitespace;
import std.conv:to;
auto len = read(stdin, rbuffer.ptr, rbuffer.length);
auto white = findAmong(rbuffer[0 .. len-1], whitespace);
static if(isPointer!(typeof(data))) {
if(isNumeric!(typeof(*data)) && white.length) return -1;
if (len > 1) {
if (isSomeChar!(typeof(*data))) {
foreach (c; stride(rbuffer, 1)) {
*data = to!(typeof(*data))(c);
break;
}
}
else {
*data = (to!(typeof(*data))(rbuffer[0 ..
len-1]));
}
} else {
len = -1;
}
} else {
if(isNumeric!(typeof(data)) && white.length) return -1;
if (len > 1) {
if (isSomeChar!(typeof(data))) {
data = to!(typeof(data))(rbuffer[0]);
}
else {
data = (to!(typeof(data))(rbuffer[0 .. len-1]));
}
} else {
len = -1;
}
}
return len;
}
void main(string[] args)
{
emit("DMD version to be downloaded: ");
string v;
scan(v);
string link =
"https://github.com/downloads/D-Programming-Language/dmd/";
string dmd = "dmd." ~ v ~ ".zip";
string curl = "curl -L -o '" ~ dmd ~ "' '" ~ link ~ dmd ~ "'";
//curl.writeln;
emitln("Downloading... ", dmd);
system(curl);
emitln("Preparing installation! ", );
system("unzip " ~ dmd);
system("rm -r dmd2/freebsd");
system("rm -r dmd2/linux");
system("rm -r dmd2/windows");
system("mv dmd2/osx/bin dmd2/");
system("mv dmd2/osx/lib dmd2/");
system("rm -r dmd2/osx");
system("rm dmd2/bin/dmd.conf");
system("rm " ~ dmd);
int fd = open("dmd2/bin/dmd.conf",
O_WRONLY | O_APPEND | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
scope(exit) assert(close(fd) >= 0);
if (fd >= 0) {
save(fd, "[Environment]", nl, nl);
save(fd, "DFLAGS=-I%@P%/../src/phobos -I%@P%/../src/druntime/import
-L-L%@P%/../lib", nl);
} else {
emit("Error opening file.");
}
system("sudo rm -r /usr/share/dmd2");
system("sudo mv dmd2 /usr/share/");
}