1 /+ Commented out because it produces no output file.
2 Gone back to phobos/std/cover for the moment.
5 * Code coverage analyzer.
9 * $(LI the execution counters are 32 bits in size, and can overflow)
10 * $(LI inline asm statements are not counted)
13 * Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com. All rights reserved.
14 * License: BSD style: $(LICENSE)
15 * Authors: Walter Bright, Sean Kelly
23 import core.sys.windows.windows;
26 import core.sys.posix.fcntl;
27 import core.sys.posix.unistd;
30 import core.stdc.stdio;
38 bool opIndex( size_t i )
45 return cast(bool) bt( ptr, i );
64 * Set path to where source files are located.
67 * pathname = The new path name.
69 extern (C) void dmd_coverSourcePath( char[] pathname )
76 * Set path to where listing files are to be written.
79 * pathname = The new path name.
81 extern (C) void dmd_coverDestPath( char[] pathname )
91 * flag = true means new data is summed with existing data in the listing
92 * file; false means a new listing file is always created.
94 extern (C) void dmd_coverSetMerge( bool flag )
101 * The coverage callback.
104 * filename = The name of the coverage file.
108 extern (C) void _d_cover_register( char[] filename, BitArray valid, uint[] data )
112 c.filename = filename;
121 const NUMLINES = 16384 - 1;
122 const NUMCHARS = 16384 * 16 - 1;
124 char[] srcbuf = new char[NUMCHARS];
125 char[][] srclines = new char[][NUMLINES];
126 char[] lstbuf = new char[NUMCHARS];
127 char[][] lstlines = new char[][NUMLINES];
129 foreach( Cover c; gdata )
131 if( !readFile( appendFN( srcpath, c.filename ), srcbuf ) )
133 splitLines( srcbuf, srclines );
137 if( !readFile( c.filename ~ ".lst", lstbuf ) )
139 splitLines( lstbuf, lstlines );
141 for( size_t i = 0; i < lstlines.length; ++i )
143 if( i >= c.data.length )
148 foreach( char c2; lstlines[i] )
154 case '0': case '1': case '2': case '3': case '4':
155 case '5': case '6': case '7': case '8': case '9':
156 count = count * 10 + c2 - '0';
166 FILE* flst = fopen( (c.filename ~ ".lst").ptr, "wb" );
169 continue; //throw new Exception( "Error opening file for write: " ~ lstfn );
174 for( int i = 0; i < c.data.length; i++ )
176 if( i < srclines.length )
179 char[] line = srclines[i];
181 line = expandTabs( line );
188 fprintf( flst, "0000000|%.*s\n", line );
192 fprintf( flst, " |%.*s\n", line );
198 fprintf( flst, "%7u|%.*s\n", n, line );
202 if( nyes + nno ) // no divide by 0 bugs
204 fprintf( flst, "%.*s is %d%% covered\n", c.filename, ( nyes * 100 ) / ( nyes + nno ) );
211 char[] appendFN( char[] path, char[] name )
214 const char sep = '\\';
216 const char sep = '/';
220 if( dest && dest[$ - 1] != sep )
227 bool readFile( char[] name, inout char[] buf )
231 auto wnamez = toUTF16z( name );
232 HANDLE file = CreateFileW( wnamez,
237 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
241 if( file == INVALID_HANDLE_VALUE )
243 scope( exit ) CloseHandle( file );
251 if( !ReadFile( file, &buf[pos], cast(DWORD)( buf.length - pos ), &num, null ) )
256 buf.length = pos * 2;
261 else version( linux )
263 char[] namez = new char[name.length + 1];
264 namez[0 .. name.length] = name;
266 int file = open( namez.ptr, O_RDONLY );
271 scope( exit ) close( file );
279 num = read( file, &buf[pos], cast(uint)( buf.length - pos ) );
285 buf.length = pos * 2;
293 void splitLines( char[] buf, inout char[][] lines )
299 for( ; pos < buf.length; ++pos )
307 lines ~= buf[beg .. pos];
309 if( buf[pos] == '\r' && pos < buf.length - 1 && buf[pos + 1] == '\n' )
317 lines ~= buf[beg .. pos];
322 char[] expandTabs( char[] string, int tabsize = 8 )
324 const dchar LS = '\u2028'; // UTF line separator
325 const dchar PS = '\u2029'; // UTF paragraph separator
327 bool changes = false;
328 char[] result = string;
332 foreach( size_t i, dchar c; string )
337 nspaces = tabsize - (column % tabsize);
342 result.length = string.length + nspaces - 1;
343 result.length = i + nspaces;
344 result[0 .. i] = string[0 .. i];
345 result[i .. i + nspaces] = ' ';
348 { int j = result.length;
349 result.length = j + nspaces;
350 result[j .. j + nspaces] = ' ';