1 /**
2  * Generate the tcod.functions module from a flat list of functions,
3  * given on stdin. Output to stdout.
4  *
5  * This is not particularly general purpose; it makes a lot of
6  * assumptions about the function list that it will be given.
7  */
8 module genfunctionsmod;
9 
10 import std.algorithm : sort;
11 import std.conv : to;
12 import std.stdio;
13 import std.ascii : isWhite;
14 import std.string;
15 
16 
17 void main()
18 {
19     string[string] functions;
20 
21 	foreach (line; stdin.byLine) {
22         if (line.emptyOrWhitespace()) continue;
23 
24         string[] functionParts = split(to!string(line), " ");
25         string functionDefinition = functionParts[0 .. $ - 1].join(" ");
26 		string functionName = chop(functionParts[$ - 1]);
27         if (functionName.length == 0) {
28 			throw new Exception("Malformed function line.");
29 		}
30 
31         functions[functionName] = functionDefinition;
32     }
33 
34     stdout.write(`/// This module has been automatically generated.
35 
36 module tcod.c.functions;
37 
38 import core.runtime : Runtime;
39 import std.algorithm.iteration : map;
40 import std.path : dirName, dirSeparator;
41 import std.range : array;
42 import std.string: join, toStringz;
43 
44 import derelict.util.loader;
45 import derelict.util.system;
46 
47 import tcod.c.all;
48 import tcod.c.types;
49 
50 extern(C) @nogc nothrow {
51 `);
52 
53     // Okay, first declare the function variables.
54     foreach (func; sort(functions.keys)) {
55         stdout.writeln("    alias da_", func, " = ", functions[func], ";");
56     }
57 
58     stdout.write(`}
59 
60 __gshared {
61 `);
62 
63     foreach (functionName; sort(functions.keys)) {
64         stdout.writeln("    da_", functionName, " ", functionName, ";");
65     }
66 
67     stdout.write(`}
68 
69 class DerelictTCODLoader : SharedLibLoader {
70     this(string libNames) {
71         super(libNames);
72     }
73 
74     ~this() {
75         unload();
76     }
77 
78     override void loadSymbols()
79     {
80 `);
81 
82     // Now load the functions from the shared object, asserting each time.
83     foreach (functionName; sort(functions.keys)) {
84         stdout.writeln("        bindFunc(cast(void**)&", functionName, ", \"", functionName, "\");");
85     }
86 
87 stdout.write(`    }
88 }
89 
90 __gshared DerelictTCODLoader DerelictTCOD;
91 
92 shared static this()
93 {
94     string[] libNames;
95     if(Derelict_OS_Windows) {
96         libNames = ["libtcod_debug.dll", "libtcod.dll"];
97     } else if(Derelict_OS_Linux) {
98         libNames = ["libtcod_debug.so", "libtcod.so"];
99 
100         // prepend executable path to library names
101         string path = dirName(Runtime.args[0]);
102         libNames = array(map!(e => path ~ dirSeparator ~ e)(libNames));
103     } else
104     assert(0, "libtcod-d is not supported on this operating system.");
105 
106     DerelictTCOD = new DerelictTCODLoader(join(libNames, ','));
107     DerelictTCOD.load();
108 }
109 `);
110 }
111 
112 /**
113  * Returns: true if string `s` is comprised entirely of whitespace
114  *          or is completely empty.
115  */
116 bool emptyOrWhitespace(T)(T s)
117 {
118     bool emptyOrWhite = true;
119     foreach (c; s) {
120         if (!isWhite(c)) {
121             emptyOrWhite = false;
122             break;
123         }
124     }
125 
126     return emptyOrWhite;
127 }
128 
129 unittest
130 {
131     assert(emptyOrWhitespace(""));
132     assert(emptyOrWhitespace("   \t\n   \t \n"));
133     assert(!emptyOrWhitespace("  a "));
134 }