Changeset 885

Show
Ignore:
Timestamp:
12/18/08 13:57:46 (3 years ago)
Author:
andrei
Message:

Fix for bug #2523.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/tools/rdmd.d

    r808 r885  
    3232int main(string[] args) 
    3333{ 
    34     // Parse the command line; first get rdmd's own arguments 
    35  
     34    //writeln("Invoked with: ", map!(q{a ~ ", "})(args)); 
     35     
     36    // Parse the #! line of the root module 
     37    // Not used yet; not sure whether it's a good idea 
     38    // completeFlagsFromShebang(root, args); 
     39 
     40    // Continue parsing the command line; now get rdmd's own arguments 
    3641    // parse the -o option 
    3742    void dashOh(string key, string value) 
     
    4954            assert(exe.endsWith(std.path.sep)); 
    5055        } 
     56        else if (value[0] == '-') 
     57        { 
     58            // -o- passed 
     59            enforce(false, "Option -o- currently not supported by rdmd"); 
     60        } 
    5161        else 
    5262        { 
     
    5565    } 
    5666     
    57     // set by functions called in getopt if program should exit 
    58     bool bailout; 
    59  
    6067    // start the web browser on documentation page 
    61     void man(string) 
    62     { 
    63         bailout = true; 
    64         auto browser = std.process.getenv("BROWSER"); 
    65         foreach (b; [ browser, "firefox", 
     68    void man() 
     69    { 
     70        foreach (b; [ std.process.getenv("BROWSER"), "firefox", 
    6671                        "sensible-browser", "x-www-browser" ]) { 
    6772            if (!b.length) continue; 
     
    7176    } 
    7277 
     78    // set by functions called in getopt if program should exit 
     79    bool bailout; 
    7380    getopt(args, 
    7481            std.getopt.config.caseSensitive, 
     
    8087            "force", &force, 
    8188            "help", (string) { writeln(helpString); bailout = true; }, 
    82             "man", &man
     89            "man", (string) { man; bailout = true; }
    8390            "o", &dashOh, 
    8491            "compiler", &compiler); 
     
    8693    if (dryRun) chatty = true; // dry-run implies chatty 
    8794 
    88     // Continue parsing the program line - find the program to run 
     95    // Parse the program line - first find the program to run 
    8996    invariant programPos = find!("a.length && a[0] != '-'")(args[1 .. $]) 
    9097        - begin(args); 
     
    97104        root = /*rel2abs*/(chomp(args[programPos], ".d") ~ ".d"), 
    98105        exeBasename = basename(root, ".d"), 
    99         programArgs = args[programPos + 1 .. $], 
    100         compilerFlags = args[1 .. programPos]; 
    101    
     106        programArgs = args[programPos + 1 .. $]; 
     107    args = args[0 .. programPos]; 
     108    const compilerFlags = args[1 .. programPos]; 
     109 
    102110    // Compute the object directory and ensure it exists 
    103111    invariant objDir = getObjPath(root, compilerFlags); 
     
    143151{ 
    144152    // Heuristics: if source starts with "std.", it's in a library 
    145     return startsWith(source, "std.") 
     153    return startsWith(source, "std.") || startsWith(source, "core.") 
    146154        || source == "object" || source == "gcstats"; 
    147155    // another crude heuristic: if a module's path is absolute, it's 
     
    188196private string getObjPath(in string root, in string[] compilerFlags) 
    189197{ 
    190     auto tmpRoot = tmpDir; 
     198    const tmpRoot = tmpDir; 
    191199    return std.path.join(tmpRoot, 
    192200            "rdmd-" ~ basename(root) ~ '-' ~ hash(root, compilerFlags)); 
     
    219227} 
    220228 
     229void 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 --stuff 
     239    // or 
     240    // #!/usr/bin/env rdmd --stuff 
     241    // or 
     242    // #!/bin/env rdmd --stuff 
     243    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" thing 
     248        cmd = cmd[1 .. $]; 
     249    } 
     250    // Ok, found a command with maybe some parms. Put those in front so 
     251    // they are overridden by the true command-line arguments 
     252    args = args[0] ~ cmd[1 .. $] ~ args[1 .. $]; 
     253} 
     254 
    221255// Run a program optionally writing the command line first 
    222256 
     
    242276    // myModules maps module source paths to corresponding .o names 
    243277    string[string] myModules;// = [ rootModule : d2obj(rootModule) ]; 
    244     FILE* depsReader; 
    245278    // Must collect dependencies 
    246279    invariant depsGetter = compiler~" "~join(compilerFlags, " ") 
    247280        ~" -v -o- "~shellQuote(rootModule); 
    248281    if (chatty) writeln(depsGetter); 
    249     depsReader = enforce(popen(depsGetter), "Error getting dependencies"); 
    250     scope(exit) fclose(depsReader); 
     282    File depsReader; 
     283    depsReader.popen(depsGetter); 
     284    scope(exit) collectException(depsReader.close); // we don't care for errors 
    251285 
    252286    // Fetch all dependent modules and append them to myModules 
     
    257291        invariant moduleName = pattern[1], moduleSrc = pattern[2]; 
    258292        if (inALibrary(moduleName, moduleSrc)) continue; 
    259         auto moduleObj = d2obj(moduleSrc); 
     293        invariant moduleObj = d2obj(moduleSrc); 
    260294        myModules[/*rel2abs*/(moduleSrc)] = moduleObj; 
    261295    }