www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Request some guidance regarding I/O

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