Changeset 1156

Show
Ignore:
Timestamp:
05/05/08 06:59:49 (2 months ago)
Author:
fraserofthenight
Message:

Re-assembled flute in a compiling and questionably working state.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/descent.unittest/flute/src/org/dsource/descent/flute/flute.d

    r1113 r1156  
    276276 */ 
    277277 
    278  
    279 // Functions this program uses in a tango/phobos independent manner 
    280  
    281 /** 
    282  * Initializes input/output. Should be called before any IO operations are 
    283  * performed. 
    284  */ 
    285 //private void initIO(); 
    286  
    287 /** 
    288  * Closes input/output. Should be called before program termination and after 
    289  * initIO(). 
    290  */ 
    291 //private void closeIO(); 
    292  
    293 /** 
    294  * Flushes the output stream. Should be called before waiting for user input and 
    295  * before possibly lengthy operations to alert users. 
    296  */ 
    297 //private void flush(); 
    298  
    299 /** 
    300  * Prints the given string to the output (either a socket or stdout). 
    301  *  
    302  * Params: 
    303  *     str = The string to print 
    304  */ 
    305 //private void write(char[] str); 
    306  
    307 /** 
    308  * Reads a line (terminated by a system-specific line specifier for stdout, or a 
    309  * CRLF for socket input), and returns the line. 
    310  *  
    311  * Returns: The next line from the input stream 
    312  */ 
    313 //private char[] readln(); 
    314  
    315 /** 
    316  * Initalize libraries needed to lookup file/line information in exception stack 
    317  * traces.  
    318  */ 
    319 //private void initDebugInfo(); 
    320  
    321 /** 
    322  * Close librries needed to lookup file/line information in exception stack traces. 
    323  */ 
    324 //private void closeDebugInfo(); 
    325  
    326 /** 
    327  * Attempts to look up the file/line in the debug info given an execution 
    328  * address. 
    329  *  
    330  * Params: 
    331  *     addr = the execution address to look up 
    332  *     line = the line thatn was executing 
    333  *     file = the file that was executing, as reported by the debug info 
    334  * Returns: true if and only if the lookup was succesful, false otherwise. 
    335  */ 
    336 //private static bool getDebugInfo(void* addr, out int line, out char[] file) 
    337  
    338278import cn.kuehne.flectioned; 
    339  
    340 /** 
    341  * Port to listen on (this should be configurable somehow)... 
    342  */ 
    343 private const ushort PORT = 30587; 
    344  
    345 static if(is(typeof((new object.Object()).toUtf8()) == char[])) 
     279import org.dsource.descent.flute.io; 
     280 
     281// Import and define functions for library-independent use 
     282version(Tango) 
    346283{ 
    347284    version = inTango; 
     
    353290    import tango.stdc.ctype : isdigit; 
    354291     
    355     version(FluteCommandLine) 
    356     { 
    357         import tango.io.Stdout : Cin, Cout; 
    358     } 
    359     else 
    360     { 
    361         import tango.net.ServerSocket; 
    362         import tango.net.InternetAddress; 
    363         import tango.net.SocketConduit; 
    364          
    365         import tango.io.model.IConduit; 
    366         import tango.io.model.IBuffer; 
    367         import tango.io.protocol.model.IWriter; 
    368          
    369         import tango.io.Buffer; 
    370         import tango.io.protocol.Writer; 
    371     } 
    372      
    373292    static import tango.text.convert.Integer; 
    374293    static if(is(typeof(tango.text.convert.Integer.toString))) 
     
    376295    else 
    377296        alias tango.text.convert.Integer.toUtf8 itoa; 
    378      
    379     version(FluteCommandLine) {} else 
    380     { 
    381         private ServerSocket serv; 
    382         private IConduit socket; 
    383         private IBuffer buf; 
    384         private IWriter writer; 
    385     } 
    386      
    387     private void initIO() 
    388     { 
    389         version(FluteCommandLine) 
    390             { } // Nothing to do 
    391         else 
    392         { 
    393             serv = new ServerSocket(new InternetAddress("127.0.0.1", PORT)); 
    394             socket = serv.accept(); 
    395             buf = new Buffer(socket); 
    396             writer = new Writer(buf); 
    397         } 
    398     } 
    399      
    400     private void closeIO() 
    401     { 
    402         version(FluteCommandLine) 
    403             { } // Nothing to do 
    404         else 
    405         { 
    406             socket.detach(); 
    407             serv.socket.detach(); 
    408         } 
    409     } 
    410      
    411     private void flush() 
    412     { 
    413         version(FluteCommandLine) 
    414             Cout.flush(); 
    415         else 
    416             writer.flush(); 
    417     } 
    418      
    419     private void write(char[] str) 
    420     { 
    421         version(FluteCommandLine) 
    422             Cout(str); 
    423         else 
    424             writer.put(str); 
    425     } 
    426      
    427     private char[] readln() 
    428     { 
    429         version(FluteCommandLine) 
    430         { 
    431             return Cin.copyln(); 
    432         } 
    433         else 
    434         { 
    435             char[] content; 
    436              
    437             uint line (void[] input) 
    438             { 
    439                 char[] text = cast(char[]) input; 
    440                 foreach (i, c; text) 
    441                 { 
    442                     if (c == '\n') 
    443                     { 
    444                         uint j = i; 
    445                         if (j && (text[j - 1] == '\r')) 
    446                             --j; 
    447                         content = text [0 .. j]; 
    448                         return i + 1; 
    449                     } 
    450                 } 
    451                 return IConduit.Eof; 
    452             } 
    453  
    454             bool read = buf.next(&line) || (content = cast(char[])  
    455                     buf.slice(buf.readable), false); 
    456             return read ? content.dup : null; 
    457         } 
    458     } 
    459      
     297 
    460298    private int find(char[] haystack, char[] needle) 
    461299    {  
     
    474312    import std.asserterror : AssertError; 
    475313     
    476     version(FluteCommandLine) 
    477     { 
    478         import std.stdio: writef, fflush, stdout; 
    479         import std.stdio : cinReadln = readln; 
    480     } 
    481     else 
    482     { 
    483         import std.socket : Socket, TcpSocket, AddressFamily, InternetAddress, 
    484             SocketShutdown, SocketException; 
    485         import std.socketstream : SocketStream; 
    486         import std.stream : Stream; 
    487     } 
    488      
    489     version(FluteCommandLine) { } else 
    490     { 
    491         Socket serv; 
    492         Stream stream; 
    493     } 
    494      
    495     private void initIO() 
    496     { 
    497         version(FluteCommandLine) 
    498             { } // Nothing to do 
    499         else 
    500         { 
    501             try 
    502             { 
    503                 serv = new TcpSocket(AddressFamily.INET); 
    504                 serv.bind(new InternetAddress("127.0.0.1", PORT)); 
    505                 serv.listen(0); 
    506                 Socket conn = serv.accept(); 
    507                 stream = new SocketStream(conn); 
    508             } 
    509             catch(SocketException se) 
    510             { 
    511                 std.stdio.writefln("Couldn't create socket; error code " ~ 
    512                     itoa(se.errorCode)); 
    513                 exit(se.errorCode); 
    514             } 
    515         } 
    516     } 
    517      
    518     private void closeIO() 
    519     { 
    520         version(FluteCommandLine) 
    521             { } // Nothing to do 
    522         else 
    523         { 
    524             stream.close(); 
    525             serv.shutdown(SocketShutdown.BOTH); 
    526             serv.close(); 
    527         } 
    528     } 
    529      
    530     private void flush() 
    531     { 
    532         version(FluteCommandLine) 
    533             fflush(stdout); 
    534         else 
    535             stream.flush(); 
    536     } 
    537      
    538     private void write(char[] str) 
    539     { 
    540         version(FluteCommandLine) 
    541             writef(str); 
    542         else 
    543             stream.writeString(str); 
    544     } 
    545      
    546     private char[] readln() 
    547     { 
    548         version(FluteCommandLine) 
    549             return cinReadln(); 
    550         else 
    551             return stream.readLine(); 
    552     } 
    553      
    554314    private char[] itoa(int i) 
    555315    { 
    556316        return format("%d", i); 
    557317    } 
    558 } 
    559  
    560 version(Windows) 
    561 { 
    562     /// Can we lookup debug info? 
    563     private bool debugInfo = false; 
    564      
    565     import std.c.windows.windows; 
    566      
    567     private enum 
    568     { 
    569         MAX_MODULE_NAME32 = 255, 
    570         TH32CS_SNAPMODULE = 0x00000008, 
    571         SYMOPT_LOAD_LINES = 0x10, 
    572     } 
    573      
    574     private extern(Windows) struct MODULEENTRY32 
    575     { 
    576         DWORD  dwSize; 
    577         DWORD  th32ModuleID; 
    578         DWORD  th32ProcessID; 
    579         DWORD  GlblcntUsage; 
    580         DWORD  ProccntUsage; 
    581         BYTE  *modBaseAddr; 
    582         DWORD  modBaseSize; 
    583         HMODULE hModule; 
    584         char   szModule[MAX_MODULE_NAME32 + 1]; 
    585         char   szExePath[MAX_PATH]; 
    586     } 
    587      
    588     private extern(Windows) struct IMAGEHLP_LINE 
    589     { 
    590         DWORD SizeOfStruct; 
    591         PVOID Key;  
    592         DWORD LineNumber;  
    593         PTSTR FileName;  
    594         DWORD Address; 
    595     } 
    596     alias IMAGEHLP_LINE* PIMAGEHLP_LINE; 
    597      
    598     private extern(Windows) BOOL Module32First(HANDLE, MODULEENTRY32*); 
    599     private extern(Windows) BOOL Module32Next(HANDLE, MODULEENTRY32*); 
    600     private extern(Windows) HANDLE CreateToolhelp32Snapshot(DWORD,DWORD); 
    601      
    602     private HMODULE imagehlp; 
    603     private HANDLE proc; 
    604     private extern(Windows) DWORD function(DWORD) SymSetOptions; 
    605     private extern(Windows) BOOL function(HANDLE, PCSTR, BOOL) SymInitialize; 
    606     private extern(Windows) BOOL function(HANDLE) SymCleanup; 
    607     private extern(Windows) DWORD function(HANDLE, HANDLE, PCSTR, PCSTR, DWORD, DWORD) SymLoadModule; 
    608     private extern(Windows) BOOL function(HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE) SymGetLineFromAddr; 
    609          
    610     private void initDebugInfo() 
    611     { 
    612         MODULEENTRY32 moduleEntry; 
    613         moduleEntry.dwSize = moduleEntry.sizeof; 
    614         char buffer[4096]; 
    615          
    616         try 
    617         { 
    618             scope(failure) 
    619             { 
    620                 if(imagehlp) 
    621                     FreeLibrary(imagehlp); 
    622                  
    623                 SymSetOptions = null; 
    624                 SymInitialize = null; 
    625                 SymCleanup = null; 
    626                 SymLoadModule = null; 
    627                 SymGetLineFromAddr = null; 
    628             } 
    629              
    630             proc = GetCurrentProcess(); 
    631             if(!proc) 
    632                 throw new Exception("GetCurrentProcess() returned null"); 
    633              
    634             HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); 
    635             if(!snapshot) 
    636                 throw new Exception("CreateToolHelp32Snapshot failed"); 
    637              
    638             imagehlp = LoadLibraryA("imagehlp.dll"); 
    639             if(!imagehlp) 
    640                 throw new Exception("Failed to load imagehlp.dll"); 
    641              
    642             SymSetOptions = cast(typeof(SymSetOptions)) GetProcAddress(imagehlp, "SymSetOptions"); 
    643             if(!SymSetOptions) 
    644                 throw new Exception("Failed to load SymSetOptions"); 
    645              
    646             SymInitialize = cast(typeof(SymInitialize)) GetProcAddress(imagehlp, "SymInitialize"); 
    647             if(!SymInitialize) 
    648                 throw new Exception("Failed to load SymInitialize"); 
    649              
    650             SymCleanup = cast(typeof(SymCleanup)) GetProcAddress(imagehlp, "SymCleanup"); 
    651             if(!SymCleanup) 
    652                 throw new Exception("Failed to load SymCleanup"); 
    653              
    654             SymLoadModule = cast(typeof(SymLoadModule)) GetProcAddress(imagehlp, "SymLoadModule"); 
    655             if(!SymLoadModule) 
    656                 throw new Exception("Failed to load SymLoadModule"); 
    657              
    658             SymGetLineFromAddr = cast(typeof(SymGetLineFromAddr)) GetProcAddress(imagehlp, "SymGetLineFromAddr"); 
    659             if(!SymGetLineFromAddr) 
    660                 throw new Exception("Failed to load SymGetLineFromAddr"); 
    661              
    662             // Since Flectioned doesn't load the line inforamtion when loading 
    663             // symbols, we have little choice but to load all the symbols again, this 
    664             // time with SYMOPT_LOAD_LINES on. 
    665             if(!SymCleanup(proc)) 
    666                 throw new Exception("SymCleanup failed"); 
    667             SymSetOptions(SYMOPT_LOAD_LINES); 
    668             if(!SymInitialize(proc, null, FALSE)) 
    669                 throw new Exception("SymInitialize failed"); 
    670              
    671             // We have to enumerate through the modules individually so that each 
    672             // module finds its search path 
    673             if(!Module32First(snapshot, &moduleEntry)) 
    674                 throw new Exception("Module32First Failed"); 
    675             do 
    676             { 
    677                 if(GetModuleFileNameA(moduleEntry.hModule, buffer.ptr, buffer.length)) 
    678                     SymLoadModule(proc, HANDLE.init, buffer.ptr, null, 0, 0); 
    679             } 
    680             while(Module32Next(snapshot, &moduleEntry)); 
    681              
    682             debugInfo = true; 
    683         } 
    684         catch(Exception e) 
    685         { 
    686             //write(e.toString() ~ "\n"); 
    687         } 
    688     } 
    689          
    690     private void closeDebugInfo() 
    691     { 
    692         if(debugInfo) 
    693         { 
    694             SymCleanup(proc); 
    695             FreeLibrary(imagehlp); 
    696              
    697             SymSetOptions = null; 
    698             SymInitialize = null; 
    699             SymCleanup = null; 
    700             SymLoadModule = null; 
    701             SymGetLineFromAddr = null; 
    702         } 
    703     } 
    704      
    705     private bool getDebugInfo(void* addr, out int line, out char[] file) 
    706     {    
    707         if(!debugInfo || !addr) 
    708             goto Lunknown; 
    709          
    710         IMAGEHLP_LINE lineInfo; 
    711         DWORD displacement; 
    712         lineInfo.SizeOfStruct = lineInfo.sizeof; 
    713          
    714         if(!SymGetLineFromAddr(proc, cast(DWORD) addr, &displacement, &lineInfo)) 
    715             goto Lunknown; 
    716          
    717         line = lineInfo.LineNumber; 
    718         file = lineInfo.FileName[0 .. strlen(lineInfo.FileName)]; 
    719         return true; 
    720          
    721         Lunknown: 
    722             return false; 
    723     } 
    724 } 
    725 else 
    726 { 
    727     // TODO 
    728318} 
    729319 
     
    813403        { 
    814404            case ResultType.PASSED: 
    815                 write("PASSED\r\n"); 
     405                io.write("PASSED\r\n"); 
    816406                return; 
    817407             
    818408            case ResultType.FAILED: 
    819                 write("FAILED\r\n"); 
     409                io.write("FAILED\r\n"); 
    820410                version(inTango) 
    821411                { 
     
    823413                    AssertException ae = cast(AssertException) e; 
    824414                    assert(ae !is null); 
    825                     write("Assertion failed in " ~ ae.file ~ " at line " ~ 
     415                    io.write("Assertion failed in " ~ ae.file ~ " at line " ~ 
    826416                        itoa(ae.line)); 
    827417                    if(ae.msg && ae.msg.length > 0) 
    828                         write(": " ~ ae.msg); 
    829                     write("\r\n"); 
     418                        io.write(": " ~ ae.msg); 
     419                    io.write("\r\n"); 
    830420                } 
    831421                else 
     
    843433                    AssertError ae = cast(AssertError) e; 
    844434                    assert(ae !is null); 
    845                     write("Assertion failed in " ~ ae.filename ~ " at line " ~ 
     435                    io.write("Assertion failed in " ~ ae.filename ~ " at line " ~ 
    846436                        itoa(ae.linnum)); 
    847437                    char[] msg = extractMessage(ae.msg); 
    848438                    if(msg) 
    849                         write(": " ~ msg); 
    850                     write("\r\n"); 
     439                        io.write(": " ~ msg); 
     440                    io.write("\r\n"); 
    851441                } 
    852442                goto LprintStackTrace; 
     
    855445            // and tango, i.e. filename/line, etc. 
    856446            case ResultType.ERROR: 
    857                 write("ERROR\r\n"); 
     447                io.write("ERROR\r\n"); 
    858448                static if(is(typeof((new Object).toString))) 
    859                     write("Exception " ~ e.classinfo.name ~ ": " ~ e.toString() 
     449                    io.write("Exception " ~ e.classinfo.name ~ ": " ~ e.toString() 
    860450                        ~ "\r\n"); 
    861451                else 
    862                     write("Exception " ~ e.classinfo.name ~ ": " ~ e.toUtf8() 
     452                    io.write("Exception " ~ e.classinfo.name ~ ": " ~ e.toUtf8() 
    863453                        ~ "\r\n"); 
    864454                goto LprintStackTrace; 
     
    906496                int line; 
    907497                char[] file; 
    908                 if(getDebugInfo(ste.code, line, file)) 
     498                if(getLineFromAddr(ste.code, line, file)) 
    909499                { 
    910500                    buf ~= file ~ ":" ~ itoa(line); 
     
    915505                } 
    916506                buf ~= ")\r\n"; 
    917                 write(buf); 
     507                io.write(buf); 
    918508            } 
    919509    } 
     
    1242832        { 
    1243833            case SearchResult.TestFound.NOT_FOUND: 
    1244                 write("Test " ~ spec ~ "not found\r\n"); 
     834                io.write("Test " ~ spec ~ "not found\r\n"); 
    1245835                return null; 
    1246836            case SearchResult.TestFound.AMBIGUOUS: 
    1247                 write("Simple name " ~ spec[1 .. $] ~ " is ambigous, could refer" 
     837                io.write("Simple name " ~ spec[1 .. $] ~ " is ambigous, could refer" 
    1248838                      " to either " ~ found.ambig.fqns[0] ~ " or " ~ 
    1249839                      found.ambig.fqns[1]); 
     
    1291881        foreach(spec; testNames.sort) 
    1292882        { 
    1293             write(spec ~ "\r\n"); 
     883            io.write(spec ~ "\r\n"); 
    1294884            TestResult result = runTest(spec); 
    1295885            if(result) 
     
    1308898                } 
    1309899            } 
    1310             write("\r\n"); 
    1311             flush(); 
     900            io.write("\r\n"); 
     901            io.flush(); 
    1312902        } 
    1313903         
    1314904        uint total = passed + failed + error; 
    1315         write("   PASSED: " ~ itoa(passed) ~ "/" ~ itoa(total) ~ "\r\n"); 
    1316         write("   FAILED: " ~ itoa(failed) ~ "/" ~ itoa(total) ~ "\r\n"); 
    1317         write("   ERROR: "  ~ itoa(error)  ~ "/" ~ itoa(total) ~ "\r\n"); 
     905        io.write("   PASSED: " ~ itoa(passed) ~ "/" ~ itoa(total) ~ "\r\n"); 
     906        io.write("   FAILED: " ~ itoa(failed) ~ "/" ~ itoa(total) ~ "\r\n"); 
     907        io.write("   ERROR: "  ~ itoa(error)  ~ "/" ~ itoa(total) ~ "\r\n"); 
    1318908    } 
    1319909} 
     
    1321911/// The registry of all the tests in the pplication 
    1322912private TestRegistry registry; 
     913 
     914/// The I/O provider used for all operations 
     915private IOProvider io; 
    1323916 
    1324917/** 
     
    1329922{ 
    1330923    TracedException.traceAllExceptions(); 
    1331     initIO(); 
    1332     initDebugInfo(); 
    1333     write(VERSION_STRING ~ "\r\n"); 
     924    io = getIOProvider(); 
     925    io.write(VERSION_STRING ~ "\r\n"); 
    1334926    initRegistry(); 
    1335927    if(!commandLoop()) 
     
    1343935private void fluteExit() 
    1344936{ 
    1345     flush(); 
    1346     closeDebugInfo(); 
    1347     closeIO(); 
     937    io.flush(); 
     938    delete io; 
    1348939    _moduleDtor(); 
    1349940    gc_term(); 
     
    1367958{ 
    1368959    LnextCommand: 
    1369     write("(flute)\r\n"); 
    1370     flush(); 
    1371     char[] line = trim(readln()); 
     960    io.write("(flute)\r\n"); 
     961    io.flush(); 
     962    char[] line = trim(io.readln()); 
    1372963    if(line.length < 1) 
    1373964        goto LnextCommand; 
     
    1391982            goto default; 
    1392983        foreach(spec; registry.getTestNames()) 
    1393             write(spec ~ "\r\n"); 
     984            io.write(spec ~ "\r\n"); 
    1394985        goto LnextCommand; 
    1395986     
     
    14111002    // It's an unknown command -- say so & try again 
    14121003    default: 
    1413         write("Unrecognized command " ~ line ~ "\r\n"); 
     1004        io.write("Unrecognized command " ~ line ~ "\r\n"); 
    14141005        goto LnextCommand; 
    14151006    } 
     
    14901081            version(Flute_NoWarnings) {} 
    14911082            else 
    1492                 write("Warning: Test " ~ test.getSignature() ~  
     1083                io.write("Warning: Test " ~ test.getSignature() ~  
    14931084                    " given multiple names, only " ~ test.getSimpleName()~ 
    14941085                    " used\r\n"); 
  • trunk/descent.unittest/flute/src/org/dsource/descent/flute/io.d

    r1150 r1156  
     1/** 
     2 * Provides a set of (simple) library-independent I/O operations depending on 
     3 * what version is specified. If FluteCommandLine is specified, will provide 
     4 * console stdio, which is useful mainly for testing purposes. Otherwise, will 
     5 * provide socket I/O. 
     6 *  
     7 * The socket will always bind to the localhost, and will opn a port determined 
     8 * by the contents of the ".fluteio" file (without the quotes) in the current 
     9 * working directory. This file's sole contents should be an ASCII-encoded 
     10 * decimal integer between 1024 and 65535m representing the port flute should 
     11 * open on. If this file does not exist or is in the wrong format, an error will 
     12 * be printed to stdout and the application will exit. 
     13 */ 
    114module org.dsource.descent.flute.io; 
    215 
     
    720else 
    821{ 
    9     import std.file : exists, read; 
    10     import std.stdio: writef, fflush, stdout; 
     22    version(FluteCommandLine) 
     23    { 
     24        import std.stdio : writef, fflush, stdout, cinReadln = readln; 
     25    } 
     26    else 
     27    { 
     28        import std.c.stdlib : exit, EXIT_SUCCESS, EXIT_FAILURE; 
     29        import std.ctype : isdigit; 
     30        import std.file : exists, read; 
     31        import std.socket : Socket, TcpSocket, AddressFamily, InternetAddress, 
     32            SocketShutdown, SocketException; 
     33        import std.socketstream : SocketStream; 
     34        import std.stdio: writef; 
     35        import std.stream : Stream; 
     36        import std.string : atoi; 
     37    } 
    1138} 
    1239 
    13 private IOProvider ioProvider; 
    14  
     40/** 
     41 * Gets a new instance of IO provider. This instance should be explicitly 
     42 * deleted when done. This should only be called once (since trying to open a 
     43 * socket on the same port more than once will obviously not work too well). 
     44 */ 
    1545public IOProvider getIOProvider() 
    1646{ 
    17     if(null is ioProvider) 
    18     { 
    19         ioProvider = new PhobosStdioProvider(); 
    20     } 
    21      
    22     return ioProvider; 
     47    return new IOProviderImpl(); 
    2348} 
    2449 
    25 public interface IOProvider 
     50/** 
     51 * The interface for issuing I/O commands. This is an abstract class instead of 
     52 * an interface to get around the limitation in D that interfaces can't be 
     53 * deleted. 
     54 */ 
     55public abstract class IOProvider 
    2656{ 
    2757    /** 
     
    3161     *     str = The string to print 
    3262     */ 
    33     public void write(string str); 
     63    public abstract void write(string str); 
    3464     
    3565    /** 
    36      * Flushes the output stream. Should be called before waiting for user input and 
    37      * before possibly lengthy operations to alert users. 
     66     * Flushes the output stream. Should be called before waiting for user input 
     67     * and before possibly lengthy operations to alert users. 
    3868     */ 
    39     public void flush(); 
     69    public abstract void flush(); 
    4070 
    4171    /** 
     
    4474     * Returns: The next line from the input stream 
    4575     */ 
    46     public string readln(); 
    47      
    48     /** 
    49      * Provides a library-independent interface for accessing a file. 
    50      * It is assumed the file is a smallish UTF-8 text file. 
    51      *  
    52      * Returns: a new handle to the file or null if the file could not be 
    53      *          found 
    54      */ 
    55     protected FileHandle getFileHandle(string filename); 
    56 
    57  
    58 /** 
    59  * Provides a library-independent interface for reading from a smallish UTF-8 
    60  * text file in a line-by-line manner. 
    61  */ 
    62 private interface FileHandle 
    63 
    64     /** 
    65      * Iterates over the contents of a file line-by line. 
    66      */ 
    67     public int opApply(int delegate(ref string) dg); 
     76    public abstract string readln(); 
    6877} 
    6978 
     
    7483else 
    7584{ 
    76     private abstract class PhobosIOProvider : IOProvider 
     85    version(FluteCommandLine) 
    7786    { 
    78         protected final FileHandle getFileHandle(string filename) 
    79         { 
    80             if(exists(filename)
     87        private final class IOProviderImpl : IOProvider 
     88        {   
     89            public void write(string str
    8190            { 
    82                 return new class(filename) FileHandle 
    83                 { 
    84                     private string filename; 
    85                      
    86                     public this(string filename) 
    87                     { 
    88                         this.filename = filename; 
    89                     } 
    90                      
    91                     public int opApply(int delegate(ref string) dg) 
    92                     { 
    93                         // Read the file 
    94                         char[] text = cast(char[]) read(filename); 
    95                          
    96                         // Iterate through the lines 
    97                         uint lineStart = 0; 
    98                         uint i = 0; 
    99                         for(; i < test.length; i++) 
    100                         { 
    101                             char c = text[i]; 
    102                             if (c == '\n') 
    103                             { 
    104                                 uint lineEnd = i; 
    105                                  
    106                                 // Handle a \r\n 
    107                                 if(lineEnd && (text[lineEnd - 1] == '\r')) 
    108                                     lineEnd--; 
    109                                  
    110                                 char[] line = text[lineStart .. lineEnd]; 
    111                                 lineStart = i + 1; 
    112                                  
    113                                 int result = dg(line); 
    114                                 if(result) 
    115                                     return result; 
    116                             } 
    117                         } 
    118                          
    119                         // Slurp up the remainder of the text as the final line 
    120                         if(lineStart < text.length) 
    121                         { 
    122                             char[] line = text[lineStart .. i]; 
    123                             int result = dg(line); 
    124                             if(result) 
    125                                 return result; 
    126                         } 
    127                          
    128                         return 0; 
    129                     } 
    130                 }; 
     91                writef(str); 
    13192            } 
    132             else 
     93             
     94            public void flush() 
    13395            { 
    134                 return null; 
     96                fflush(stdout); 
     97            } 
     98     
     99            public string readln() 
     100            { 
     101                return cinReadln(); 
    135102            } 
    136103        } 
    137104    } 
    138      
    139     private final class PhobosStdioProvider : PhobosIOProvider 
    140     {    
    141         public void write(string str) 
     105    else 
     106    { 
     107        private final class IOProviderImpl : IOProvider 
    142108        { 
    143             writef(str); 
    144         } 
    145          
    146         public void flush() 
    147         { 
    148             fflush(stdout); 
    149         } 
    150  
    151         public string readln() 
    152         { 
    153             return cinReadln(); 
     109            Socket serv; 
     110            Stream stream; 
     111             
     112            public this() 
     113            { 
     114                writef("Port %s\n", getPort()); 
     115                exit(EXIT_SUCCESS); 
     116                 
     117                try 
     118                { 
     119                    serv = new TcpSocket(AddressFamily.INET); 
     120                    serv.bind(new InternetAddress("127.0.0.1", getPort())); 
     121                    serv.listen(0); 
     122                    Socket conn = serv.accept(); 
     123                    stream = new SocketStream(conn); 
     124                } 
     125                catch(SocketException se) 
     126                { 
     127                    writef("Couldn't create socket; error code %d\n", 
     128                        se.errorCode); 
     129                    exit(se.errorCode); 
     130                } 
     131            } 
     132             
     133            public ~this() 
     134            { 
     135                try 
     136                { 
     137                    stream.close(); 
     138                    serv.shutdown(SocketShutdown.BOTH); 
     139                    serv.close(); 
     140                } 
     141                catch(Exception e) 
     142                { 
     143                    // Ignore 
     144                } 
     145            } 
     146             
     147            public void write(string str) 
     148            { 
     149                stream.writeString(str); 
     150            } 
     151             
     152            public void flush() 
     153            { 
     154                stream.flush(); 
     155            } 
     156             
     157            public string readln() 
     158            { 
     159                return stream.readLine(); 
     160            } 
     161             
     162            private const string CONFIG_FILE_NAME = ".fluteport"; 
     163             
     164            private uint getPort() 
     165            { 
     166                if(!exists(CONFIG_FILE_NAME)) 
     167                { 
     168                    writef("Couldn't open config file %s\n", CONFIG_FILE_NAME); 
     169                    exit(EXIT_FAILURE); 
     170                } 
     171                 
     172                string contents = cast(string) read(CONFIG_FILE_NAME); 
     173                 
     174                uint i = 0; 
     175                while(i < contents.length && isdigit(contents[i])) 
     176                    i++; 
     177                 
     178                if(0 == i) 
     179                { 
     180                    writef("Invalid flute config file %s\n", CONFIG_FILE_NAME); 
     181                    exit(EXIT_FAILURE); 
     182                } 
     183                 
     184                string portStr = contents[0 .. i]; 
     185                int portNum = atoi(portStr); 
     186                 
     187                if(portNum < 1024 || portNum > 65535) 
     188                { 
     189                    writef("Invalid port %d - Must be in the range 1024 .. 65535\n", 
     190                        portNum); 
     191                    exit(EXIT_FAILURE); 
     192                } 
     193                 
     194                return portNum; 
     195            } 
    154196        } 
    155197    } 
  • trunk/descent.unittest/src/descent/internal/unittest/ui/OpenModuleAction.java

    r1150 r1156  
    1111import descent.core.IJavaModel; 
    1212import descent.core.IJavaProject; 
     13import descent.core.IPackageFragment; 
     14import descent.core.IPackageFragmentRoot; 
    1315import descent.core.JavaModelException; 
    1416import descent.internal.compiler.parser.ISignatureConstants; 
     
    5052 
    5153    private static ICompilationUnit findModule(IJavaProject project, 
    52             String moduleSignature, Set<IJavaProject> visitedProjects) 
    53             throws JavaModelException 
     54            String moduleSignature, 
     55            Set<IJavaProject> visitedProjects) 
     56        throws JavaModelException 
    5457    { 
    5558        if (visitedProjects.contains(project)) 
    5659            return null; 
    5760         
    58         ICompilationUnit module; 
    59         // TODO IJavaElement javaElement = project.findBySignature(moduleSignature); 
    60         IJavaElement javaElement = null; 
    61         if(javaElement != null && javaElement instanceof ICompilationUnit 
    62             && javaElement.exists()) 
    63         { 
    64             // Note: existance must be tested since an IcompilationUnit may 
    65             // be returned for non-existant modules 
    66             module = (ICompilationUnit) javaElement; 
    67             return module; 
    68         } 
     61        int index = moduleSignature.lastIndexOf('.'); 
     62        String packagePart = index > 0 ? moduleSignature.substring(0, index) : ""; 
     63        String modulePart = String.format("%1$s.d", index > 0 ?  
     64                moduleSignature.substring(index + 1) : moduleSignature); 
     65         
     66        ICompilationUnit module = null; 
     67        for(IPackageFragmentRoot root : project.getPackageFragmentRoots()) 
     68        { 
     69            IPackageFragment pkg = root.getPackageFragment(packagePart); 
     70            if (pkg.exists())&n