Changeset 936
- Timestamp:
- 02/23/09 12:39:02 (3 years ago)
- Files:
-
- trunk/tools/rdmd.d (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/tools/rdmd.d
r885 r936 30 30 private string exe, compiler = "dmd"; 31 31 32 // For --eval 33 immutable string importWorld = " 34 import std.stdio, std.algorithm, std.array, std.atomics, std.base64, 35 std.bigint, std.bind, /*std.bitarray,*/ std.bitmanip, std.boxer, 36 std.compiler, std.complex, std.contracts, std.conv, std.cpuid, std.cstream, 37 std.ctype, std.date, std.dateparse, std.demangle, std.encoding, std.file, 38 std.format, std.functional, std.getopt, std.intrinsic, std.iterator, 39 /*std.loader,*/ std.math, std.md5, std.metastrings, std.mmfile, 40 std.numeric, std.openrj, std.outbuffer, std.path, std.perf, std.process, 41 std.random, std.range, std.regex, std.regexp, std.signals, std.socket, 42 std.socketstream, std.stdint, std.stdio, std.stdiobase, std.stream, 43 std.string, std.syserror, std.system, std.traits, std.typecons, 44 std.typetuple, std.uni, std.uri, std.utf, std.variant, std.xml, std.zip, 45 std.zlib;"; 46 32 47 int main(string[] args) 33 48 { 34 49 //writeln("Invoked with: ", map!(q{a ~ ", "})(args)); 50 if (args.length > 1 && std.string.startsWith(args[1], "--shebang ")) 51 { 52 // multiple options wrapped in one 53 auto a = args[1]["--shebang ".length .. $]; 54 args = args[0 .. 1] ~ split(a) ~ args[2 .. $]; 55 } 35 56 36 // Parse the #! line of the root module37 // Not used yet; not sure whether it's a good idea38 // completeFlagsFromShebang(root, args);39 40 57 // Continue parsing the command line; now get rdmd's own arguments 41 58 // parse the -o option … … 52 69 // add a trailing path separator to clarify it's a dir 53 70 exe = std.path.join(value[1 .. $], ""); 54 assert( exe.endsWith(std.path.sep));71 assert(std.string.endsWith(exe, std.path.sep)); 55 72 } 56 73 else if (value[0] == '-') … … 77 94 78 95 // set by functions called in getopt if program should exit 79 bool bailout; 96 bool bailout, loop; 97 string eval; 80 98 getopt(args, 81 99 std.getopt.config.caseSensitive, … … 88 106 "help", (string) { writeln(helpString); bailout = true; }, 89 107 "man", (string) { man; bailout = true; }, 108 "eval", &eval, 109 "loop", &loop, 90 110 "o", &dashOh, 91 111 "compiler", &compiler); … … 93 113 if (dryRun) chatty = true; // dry-run implies chatty 94 114 115 if (eval) 116 { 117 // Just evaluate this program! 118 if (loop) 119 { 120 return .eval(importWorld ~ "void main(string[] args) { " 121 ~ "foreach (line; stdin.byLine()) { " ~ eval ~ "; } }"); 122 } 123 else 124 { 125 return .eval(importWorld ~ "void main(string[] args) { " 126 ~ eval ~ "; }"); 127 } 128 } 129 95 130 // Parse the program line - first find the program to run 96 invariant programPos = find!("a.length && a[0] != '-'")(args[1 .. $]) 97 - begin(args); 98 if (programPos == args.length) 99 { 100 write(helpString); 101 return 1; 131 uint programPos = 1; 132 for (;; ++programPos) 133 { 134 if (programPos == args.length) 135 { 136 write(helpString); 137 return 1; 138 } 139 if (args[programPos].length && args[programPos][0] != '-') break; 102 140 } 103 141 const … … 125 163 { 126 164 // user-specified exe name 127 if ( endsWith(exe, std.path.sep))165 if (std.string.endsWith(exe, std.path.sep)) 128 166 { 129 167 // user specified a directory, complete it to a file … … 151 189 { 152 190 // Heuristics: if source starts with "std.", it's in a library 153 return startsWith(source, "std.") || startsWith(source, "core.") 191 return std.string.startsWith(source, "std.") 192 || std.string.startsWith(source, "core.") 154 193 || source == "object" || source == "gcstats"; 155 194 // another crude heuristic: if a module's path is absolute, it's … … 209 248 in string[] compilerFlags) 210 249 { 211 invarianttodo = compiler~" "~join(compilerFlags, " ")250 auto todo = compiler~" "~join(compilerFlags, " ") 212 251 ~" -of"~shellQuote(fullExe) 213 252 ~" -od"~shellQuote(objDir) 214 ~" "~shellQuote(root)~" " 215 ~join(map!(shellQuote)(myModules.keys), " "); 253 ~" "~shellQuote(root)~" "; 254 foreach (k; map!(shellQuote)(myModules.keys)) { 255 todo ~= k ~ " "; 256 } 216 257 invariant result = run(todo); 217 258 if (result) … … 225 266 rmdirRecurse(objDir); 226 267 return 0; 227 }228 229 void completeFlagsFromShebang(string root, ref string[] args)230 {231 auto f = File(root);232 auto sheBang = f.readln;233 auto cmd = std.regexp.split(strip(sheBang), r"\s+");234 if (cmd.length <= 1 || !cmd[0].startsWith("#!")) return;235 invariant prog = cmd[0][2 .. $];236 237 // Allowed shebangs:238 // #!/path/to/rdmd --stuff239 // or240 // #!/usr/bin/env rdmd --stuff241 // or242 // #!/bin/env rdmd --stuff243 if (basename(prog) != "rdmd")244 {245 if (prog != "/bin/env" && prog != "/usr/bin/env" || cmd[1] != "rdmd")246 return;247 // Discard the "[/usr]/bin/env" thing248 cmd = cmd[1 .. $];249 }250 // Ok, found a command with maybe some parms. Put those in front so251 // they are overridden by the true command-line arguments252 args = args[0] ~ cmd[1 .. $] ~ args[1 .. $];253 268 } 254 269 … … 326 341 (implies --chatty) 327 342 --force force a rebuild even if apparently not necessary 343 --eval=code evaluate program a la perl -e 344 --loop assume \"foreach (line; stdin.byLine()) { ... }\" for eval 328 345 --help this message 329 346 --man open web browser on manual page 347 --shebang rdmd is in a shebang line (put as first argument) 330 348 "; 331 349 } 350 351 int eval(string todo) 352 { 353 auto progname = tmpDir~"/eval.d"; 354 std.file.write(progname, todo); 355 scope(exit) std.file.remove(progname); 356 run("dmd -run " ~ progname); 357 return 0; 358 }
