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/");
}

Reply via email to