Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

root/trunk/doc/dimple.d

Revision 454, 8.9 kB (checked in by jcomellas, 2 years ago)

* Corrected line endings to make them acceptable to Subversion with the

svn:eol-style property for the following files:

doc/html/candydoc/style.css
doc/html/candydoc/explorer.js
doc/html/candydoc/tree.js
doc/html/candydoc/util.js
lib/common/convert/dtoa.c
lib/compiler/gdc/critical.c
lib/compiler/dmd/adi.d
lib/compiler/gdc/std/intrinsic.d
lib/compiler/gdc/trace.d
lib/compiler/gdc/memset.d
lib/gc/gdc/gcx.d
lib/gc/gdc/gcgcc.d
lib/gc/gdc/win32.d
lib/gc/gdc/gcbits.d
tango/convert/Format.d
tango/core/Thread.di

* Added MIME types for all the files in the project using the svn:mime-type

Subversion property.

  • Property svn:mime-type set to text/x-dsrc
  • Property svn:eol-style set to native
Line 
1 import std.stream;
2 import std.stdio;
3 import std.path;
4 import std.regexp;
5
6 const char[] DIMPLE_VERSION = "0.13";
7
8 /* dimple, D import-list explorer
9  *
10  * Copyright (c) 2005 by Wang Zhen
11  * All Rights Reserved
12  * Webpage: http://www.shfls.org/w/d/dimple/
13  *
14  * See GNU General Public License for terms of use.
15  */
16
17 class ProducerExhausted : Exception{ this(){ super(""); } }
18
19 interface IProducer(T){ T next(); }
20
21 alias IProducer!(char) ICharProducer;
22
23 class FileCharStream : ICharProducer{
24     this(char[] filename){
25         _file = new BufferedFile(filename);
26     }
27     char next(){
28         if(_file.eof())
29             throw new ProducerExhausted;
30         else
31             return _file.getc();
32     }
33 private:
34     BufferedFile _file;
35 }
36
37 class CommentFilter : ICharProducer{
38 //todo: /+ nested /+ comment +/ +/
39 //todo: r"wysiwyg string literal"
40     this(ICharProducer parent){
41         _parent = parent;
42         _state = STATE.echo;
43         _cached = false;
44     }
45     char next(){       
46         static char c;
47         if(_cached){
48             _cached = false;
49             return c;
50         }
51         for(;;){
52             c = _parent.next();
53             if(c=='\r')
54                 continue;
55            
56             switch(_state){
57             case STATE.echo:
58                 switch(c){
59                 case '/': _state = STATE.slash; continue;
60                 case '"': _state = STATE.dquote; break;
61                 case '\'': _state = STATE.squote; break;
62                 case '`': _state = STATE.aquote; break;
63                 default:
64                 }
65                 break;
66             case STATE.aquote:
67                 if(c=='`')
68                     _state = STATE.echo;
69                 break;
70             case STATE.sqescape:
71                 _state = STATE.squote;
72                 break;
73             case STATE.squote:
74                 switch(c){
75                 case '\'': _state = STATE.echo; break;
76                 case '\\': _state = STATE.sqescape; break;
77                 default:
78                 }
79                 break;
80             case STATE.dquote:
81                 switch(c){
82                 case '"': _state = STATE.echo; break;
83                 case '\\': _state = STATE.dqescape; break;
84                 default:
85                 }
86                 break;
87             case STATE.dqescape:
88                 _state = STATE.dquote;
89                 break;
90             case STATE.slash:
91                 switch(c){
92                 case '/': _state = STATE.linecomment; continue;
93                 case '*': _state = STATE.blockcomment; return ' ';
94                 default: _state = STATE.echo; _cached = true; return '/';
95                 }
96             case STATE.linecomment:
97                 if(c!='\n')
98                     continue;
99                 _state = STATE.echo;
100                 break;
101             case STATE.blockcomment:
102                 switch(c){
103                 case '\n': return c;
104                 case '*': _state = STATE.star;
105                 default: continue;
106                 }
107             case STATE.star:
108                 switch(c){
109                 case '\n': return c;
110                 case '/': _state = STATE.echo;
111                 default: continue;
112                 }
113             }           
114             return c;           
115         }
116     }
117 private:
118     ICharProducer _parent;
119    
120     enum STATE { echo, slash, linecomment, blockcomment, star,
121                 dquote, dqescape, squote, sqescape, aquote,};
122     STATE _state;
123     bit _cached;
124 }
125
126 //kludge: simplified lexer
127 class Token{
128     this(char[] text){
129         _text = text;
130     }
131     char[] toString(){
132         return _text;
133     }
134 private:
135     //int _type;
136     char[] _text;
137 }
138
139 alias IProducer!(Token) ITokenProducer;
140
141 class TokenStream : ITokenProducer{
142 //todo: r"wysiwyg string literal"
143     this(ICharProducer parent){
144         _parent = parent;
145     }
146     Token next(){
147         char[] t;
148         static char c = ' ';
149         bit isws(char c){
150             return c==' '||c=='\n'||c=='\t';
151         }
152         while(isws(c))
153             c = _parent.next();
154            
155         switch(c){
156         case ';': c=' '; return new Token(";");
157         case ',': c=' '; return new Token(",");
158         case '"':
159             t ~= c;
160             L1: for(;;){                   
161                     t ~= c = _parent.next();
162                     switch(c){
163                     case '"': c = ' '; break L1;
164                     case '\\': t ~= c = _parent.next();
165                     default:
166                     }
167                 }
168             break;
169         case '\'':
170             t ~= c;
171             L2: for(;;){                   
172                     t ~= c = _parent.next();
173                     switch(c){
174                     case '\'': c = ' '; break L2;
175                     case '\\': t ~= c= _parent.next();
176                     default:
177                     }
178                 }
179             break;
180         case '`':
181             t ~= c;
182             for(;;){
183                 t ~= c = _parent.next();
184                 if(c=='`'){
185                     c = ' ';
186                     break;
187                 }
188             }
189             break;
190         default:
191             try{                   
192             L0: for(;;){
193                     t ~= c;
194                     c = _parent.next();
195                     switch(c){
196                     case ' ':
197                     case '\t':
198                     case '\n':
199                     case ';':
200                     case ',':
201                         break L0;
202                     default:
203                     }
204                 }
205             }catch(ProducerExhausted){
206                 c = ' ';
207             }
208             break;         
209         }       
210         return new Token(t);       
211     }
212 private:
213     ICharProducer _parent;
214 }
215
216 alias IProducer!(char[]) IStringProducer;
217
218 class ImportList : IStringProducer{
219     this(ITokenProducer parent){
220         _parent = parent;
221         _state = STATE.imp;
222     }
223     char[] next(){
224         Token t;
225         for(;;){
226             switch(_state){
227             case STATE.imp:
228                 while((t=_parent.next()).toString()!="import"){}
229                 _state = STATE.mod;
230                 break;
231             case STATE.mod:
232                 if((t=_parent.next()).toString()==";"){
233                     _state = STATE.imp;
234                     continue;
235                 }
236             }
237             return _parent.next().toString();
238         }
239     }
240 private:
241     ITokenProducer _parent;
242     enum STATE { imp, mod, }
243     STATE _state;
244 }
245
246 class Source{
247     this(char[] modulename){
248         _modulename = modulename;
249         _visible = false;
250     }
251     char[] modulename(){ return _modulename; }
252     char[] pathname(){
253         char[] result;
254         foreach(char c; _modulename)
255             result ~= (c=='.'?'/':c);               
256         return result ~ ".d";
257     }
258     char[] toString(){ return _modulename; }
259     bit visible(){ return _visible; }
260     void visible(bit v){ _visible = v; }
261     void linked(Source by){ _linked ~= by; }
262     Source[] linked(){ return _linked; }
263     void link(Source to){ _link ~= to; }
264     Source[] link(){ return _link; }
265     int din, dout;
266 private:
267     char[] _modulename;
268     bit _visible;
269     Source[] _linked, _link;
270 }
271
272 int usage(){
273     writef("dimple ", DIMPLE_VERSION,`
274 D import-list explorer
275 Copyright(c) 2005 by Wang Zhen
276 Webpage: http://www.shfls.org/w/d/dimple/
277
278 Usage:
279   dimple entry.module { -switch }
280  
281   entry.module     module identifier
282   -x=regexp        excluded module(s)
283  
284 Example:
285   dimple dmdscript.program "-x=\.(script|dobject)" | dot -Tps -ofdep.ps
286 `);
287     return 1;
288 }
289
290 int main(char[][]args){
291     if(args.length==1)
292         return usage();
293    
294     RegExp excluded;   
295     Source[] src;
296    
297     foreach(char[] a; args[1..args.length])
298         if(a.length>3 && a[0..3]=="-x=")
299             excluded = new RegExp(a[3..a.length], "");
300         else
301             src ~= new Source(a);
302
303     for(int i=0; i<src.length; ++i){       
304         Source curr = src[i];
305         if(excluded && excluded.test(curr.modulename))
306             continue;       
307         try{
308             ImportList imported;
309             try{
310                 imported =  new ImportList(
311                             new TokenStream(
312                             new CommentFilter(
313                             new FileCharStream(curr.pathname))));
314             }catch(OpenException){
315                 //writefln("  //ignoring ", curr.pathname);
316                 continue;
317             }
318            
319             curr.visible(true);         
320             for(;;){
321                 char[] mod = imported.next();
322 //                                writefln (mod);                                 
323                
324                 Source dep;
325                 foreach(Source s; src) {
326                     if(s.modulename == mod){
327                         dep = s;
328                         break;
329                     }
330                                 }
331
332                 if(!dep)                   
333                     src ~= dep = new Source(mod);               
334                 dep.linked(curr);               
335             }
336         }catch(ProducerExhausted){
337         }catch(Exception e){
338             return writefln("error : ", e), 1;
339         }
340     }
341    
342     int l = 0;
343     foreach(Source s; src)
344         if(s.visible)
345             src[l++] = s;
346     src.length = l;
347    
348     foreach(Source s; src)
349         foreach(Source r; s.linked)
350             r.link(s);     
351    
352     //memo: output in "graphviz dot" format
353     writefln("digraph d{
354                 edge [color=gray64];
355                 node [fontname=Helvetica, style=filled, color=gray, fillcolor=darkseagreen1, fontsize=12, height=0, width=0];
356                 graph [fontname=Helvetica, dpi=72, fontcolor=black];");
357        
358     foreach(Source s; src)     
359         foreach(Source r; s.link)
360             writefln (`"`, s, `" -> "`,  r, `"`,
361 //          `[weight=`, cast(int)(100.0/r.linked.length),`]`,
362             `;`);
363    
364         // emit colors and urls
365         auto BaseUrl = "http://svn.dsource.org/projects/tango/trunk/doc/html/";
366     foreach(Source s; src)     
367                 if (std.string.find(s.toString, "model.") > 0)
368                     writefln(`"`, s, "\" [fillcolor=khaki1, URL=\"%s\"];", BaseUrl~s.toString~".html");
369                 else
370                    writefln(`"`, s, "\" [fillcolor=darkseagreen1, URL=\"%s\"];", BaseUrl~s.toString~".html");
371
372
373
374     //memo: mark modules in a cycle of dependency
375    
376     //memo: step 1: reduce the set of candidate nodes
377     int dsum = 0;
378     foreach(Source s; src){
379         s.din = s.linked.length;
380         s.dout = s.link.length;
381         dsum += s.din - s.dout;
382 //      writefln(`//`, s, ` fan-in=`, s.din, ` fan-out=`, s.dout);
383     }
384     assert(dsum==0);   
385
386     bit rescan;
387     do{
388         rescan = false;
389         foreach(Source s; src)
390             if(s.din==0 && s.dout==0)
391                 continue;
392             else if(s.din==0){
393                 foreach(Source r; s.link)
394                     if(r.din)
395                         r.din--;
396                 s.dout = 0;
397                 rescan = true;
398             }else if(s.dout==0){
399                 foreach(Source r; s.linked)
400                     if(r.dout)
401                         r.dout--;
402                 s.din = 0;
403                 rescan = true;
404             }       
405     }while(rescan);
406    
407     //memo: step 2: calculate the transitive closure
408     Source[] candidates;
409     foreach(Source s; src)
410         if(s.din)
411             candidates ~= s;
412     int n = candidates.length;
413     bit[] mtx = new bit[n*n];
414     foreach(int i, Source a; candidates)
415         foreach(int j, Source b; candidates)
416             foreach(Source c; a.link)
417                 if(b==c){
418                     mtx[i*n+j] = true;
419                     break;
420                 }   
421    
422     for(int k=0; k<n; ++k)
423         for(int i=0; i<n; ++i)
424             for(int j=0; j<n; ++j)                 
425                 if(!mtx[i*n+j] && mtx[i*n+k] && mtx[k*n+j])
426                     mtx[i*n+j] = true; 
427
428     for(int i=0; i<n; ++i)
429         if(mtx[i*n+i])
430             writefln(`"`, candidates[i], `" [fillcolor=salmon];`);
431        
432     writefln(`}`);
433
434     return 0;
435 }
Note: See TracBrowser for help on using the browser.