1010# Since 2018, Costa Shulyupin, costa@MakeLinux.net
1111#
1212
13- from inspect import currentframe , getframeinfo , getouterframes , stack
13+ import inspect
14+ from inspect import (currentframe , getframeinfo , getouterframes , stack ,
15+ getmembers , isfunction )
16+ import types
1417import random
1518import os
1619import sys
20+ from sys import *
1721import collections
1822from munch import *
1923from subprocess import *
@@ -200,6 +204,11 @@ def func_referrers_all(name):
200204
201205
202206def referrers_tree (name , referrer = None , printed = None , level = 0 ):
207+ '''
208+ Arg: <identifier>
209+ Ex: nfs_root_data
210+ '''
211+ if not referrer :
203212 if os .path .isfile ('cscope.out' ):
204213 referrer = func_referrers_cscope
205214 else :
@@ -233,6 +242,7 @@ def referrers(name):
233242
234243
235244def referrers_dep (name , referrer = None , printed = None , level = 0 ):
245+ # Arg: <identifier>
236246 if not referrer :
237247 if os .path .isfile ('cscope.out' ):
238248 referrer = func_referrers_cscope
@@ -262,6 +272,10 @@ def referrers_dep(name, referrer=None, printed=None, level=0):
262272
263273
264274def call_tree (node , printed = None , level = 0 ):
275+ '''
276+ Arg: <identifier>
277+ Ex: start_kernel
278+ '''
265279 if not os .path .isfile ('cscope.out' ):
266280 print ("Please run: cscope -Rcbk" , file = sys .stderr )
267281 return False
@@ -324,10 +338,14 @@ def my_graph(name=None):
324338
325339
326340def reduce_graph (g , m = None ):
341+ '''
342+ Arg: <graph> [min in_degree]- removes leaves
343+ Ex2: \" write_dot(reduce_graph(read_dot('doxygen.dot')),'reduced.dot')\"
344+ '''
327345 rm = set ()
328- m = g .number_of_nodes () if not m else m
346+ m = g .number_of_nodes () + 1 if not m else m
329347 log (g .number_of_edges ())
330- rm = [n for (n , d ) in g .out_degree if not d and g .in_degree (n ) <= m ]
348+ rm = [n for (n , d ) in g .out_degree if not d and g .in_degree (n ) < m ]
331349 g .remove_nodes_from (rm )
332350 print (g .number_of_edges ())
333351 return g
@@ -437,16 +455,12 @@ def syscalls():
437455# write_dot to_agraph AGraph
438456# agwrite
439457# srcxray.py 'write_dot(syscalls(), "syscalls.dot")'
440- # srcxray.py "write_dot(import_cflow(), 'a.dot')"
441458# write_graphml
442- # F=sys_mount; srcxray.py "digraph_print(import_cflow(), ['$F'])" > $F.tree
443- # srcxray.py "leaves(read_dot('a.dot'))"
444459# srcxray.py "most_used(read_dot('a.dot'))"
445460# srcxray.py "digraph_print(read_dot('a.dot'))"
446461# srcxray.py "write_dot(reduce_graph(read_dot('no-loops.dot')),'reduced.dot')"
447462# a=sys_clone;srcxray.py "write_dot(rank_couples(reduce_graph(remove_loops(read_dot('$a.dot')))),'$a.dot')"
448463# srcxray.py "pprint(most_used(read_dot('a.dot')))"
449- # srcxray.py "write_dot(digraph_tree(read_dot('all.dot'), ['sys_clone']), 'sys_clone.dot')"
450464# srcxray.py "write_dot(add_rank('reduced.dot'), 'ranked.dot')"
451465# srcxray.py "write_dot(remove_loops(read_dot('reduced.dot')), 'no-loops.dot')"
452466
@@ -459,13 +473,6 @@ def cleanup(a):
459473 write_dot (dg , a )
460474
461475
462- def leaves (a ):
463- dg = to_dg (a )
464- log (dg )
465- # [x for x in G.nodes() if G.out_degree(x)==0 and G.in_degree(x)==1]
466- return {n : dg .in_degree (n ) for (n , d ) in dg .out_degree if not d }
467-
468-
469476def sort_dict (d ):
470477 return [a for a , b in sorted (d .items (), key = lambda k : k [1 ], reverse = True )]
471478
@@ -512,6 +519,10 @@ def digraph_predecessors(dg, starts, levels = 100, excludes = [], black_list=bla
512519
513520
514521def digraph_tree (dg , starts = None , black_list = black_list ):
522+ '''
523+ Arg: <graph> <list if starting nodes> - extract a subgraph from a graph
524+ Ex2: \" write_dot(digraph_tree(read_dot('doxygen.dot'), ['main']), 'main.dot')\"
525+ '''
515526 tree = nx .DiGraph ()
516527
517528 def sub (node ):
@@ -541,6 +552,9 @@ def sub(node):
541552
542553
543554def digraph_print (dg , starts = None , dst_fn = None , sort = False ):
555+ '''
556+ Arg: <graph> - print graphs as text tree
557+ '''
544558 dst = open (dst_fn , 'w' ) if dst_fn else None
545559 printed = set ()
546560
@@ -680,6 +694,7 @@ def cflow(a=None):
680694
681695
682696def import_cflow (a = None , cflow_out = None ):
697+ # Arg: $none_or_dir_or_file_or_mask
683698 cf = my_graph ()
684699 stack = list ()
685700 nprev = - 1
@@ -707,6 +722,10 @@ def import_cflow(a=None, cflow_out=None):
707722
708723
709724def import_outline (a = None ):
725+ '''
726+ Arg: <outline.txt> - convert tree text to graph
727+ Ex2: \" write_dot(import_outline('outline.txt'),'outline.dot')\"
728+ '''
710729 cf = my_graph ()
711730 stack = list ()
712731 nprev = - 1
@@ -750,6 +769,9 @@ def esc(s):
750769
751770
752771def write_dot (g , dot ):
772+ '''
773+ Arg: <graph> <file> - writes a graph into a file with custom attributes
774+ '''
753775 dot = str (dot )
754776 dot = open (dot , 'w' )
755777 dot .write ('strict digraph "None" {\n ' )
@@ -923,6 +945,7 @@ def cflow_dir(a):
923945
924946
925947def cflow_linux ():
948+ # Arg:
926949 dirs = ('init kernel kernel/time '
927950 'fs fs/ext4 block '
928951 'ipc net '
@@ -965,6 +988,9 @@ def cflow_linux():
965988
966989
967990def stats (a ):
991+ '''
992+ Arg: <dot file> - measures various simple statistical metrics of a graph
993+ '''
968994 dg = to_dg (a )
969995 stat = Munch ()
970996 im = dict ()
@@ -1067,6 +1093,10 @@ def import_symbols():
10671093
10681094
10691095def dir_tree (d = '.' ):
1096+ '''
1097+ Arg: [directory] - scan directory into graph
1098+ Ex2: \" write_dot(dir_tree('.'),'tree.dot')\"
1099+ '''
10701100 stack = list ()
10711101 nprev = - 1
10721102 g = my_graph ()
@@ -1095,6 +1125,10 @@ def dir_tree(d='.'):
10951125
10961126
10971127def doxygen (* input ):
1128+ '''
1129+ Arg: <source files>
1130+ Ex: *.c
1131+ '''
10981132 log (' ' .join ([i for i in input ]))
10991133 p = run (['doxygen' , '-' ], stdout = PIPE ,
11001134 input = "INPUT=" + ' ' .join ([i for i in input ]) + """
@@ -1171,25 +1205,10 @@ def doxygen_length(a):
11711205
11721206
11731207def usage ():
1174- print ("Usage:\n " )
1175- for c in ["referers_tree" , "call_tree" , "referers_dep" , "call_dep" ]:
1176- print (me , c , "<identifier>" )
11771208 print ("\n Try this:\n " )
11781209 print ("cd linux/init" )
11791210 print (me , "unittest" )
1180- print (me , "referers_tree nfs_root_data" )
1181- print (me , "referers nfs_root_data" )
1182- print (me , "call_tree start_kernel" )
1183- print (me , "import_cflow $none_or_dir_or_file_or_mask" )
1184- print (me , "stats $dot" )
1185- print (me , "leaves $dot" )
1186- print (me , "cflow_linux" )
1187- print (me , "\" write_dot(import_outline('outline.txt'),'outline.dot')\" " )
1188- print (me , "\" write_dot(dir_tree('.'),'tree.dot')\" " )
1189- print (me , "\" doxygen *.c\" " )
1190- print (me , "\" write_dot(digraph_tree(read_dot('doxygen.dot'), ['main']), 'main.dot')\" " )
1191- print (me , "\" write_dot(reduce_graph(read_dot('doxygen.dot')),'reduced.dot')\" " )
1192- print ("Emergency termination: ^Z, kill %1" )
1211+ print ("\n Emergency termination: ^Z, kill %1" )
11931212 print ()
11941213
11951214
@@ -1200,10 +1219,10 @@ def test_1(self):
12001219 self .assertEqual (list (g .successors ("2" )), ["3" , "4" ])
12011220 self .assertTrue (os .path .isdir ('include/linux/' ))
12021221 os .chdir ('init' )
1203- self .assertEqual ( ' \t \t \t \t \t prepare_namespace ^' , popen (
1204- 'srcxray.py referrers_tree nfs_root_data' )[ - 1 ] )
1205- self .assertEqual ('initrd_load: prepare_namespace' , popen (
1206- 'srcxray.py referrers_dep nfs_root_data' )[- 1 ])
1222+ self .assertRegex ( popen ( 'srcxray.py referrers_tree nfs_root_data' )[ - 1 ],
1223+ r'.*prepare_namespace.*' )
1224+ self .assertEqual ('initrd_load: prepare_namespace' ,
1225+ popen ( 'srcxray.py referrers_dep nfs_root_data' )[- 1 ])
12071226 self .assertEqual ('calibrate_delay_converge: __delay' ,
12081227 popen ('srcxray.py call_dep start_kernel' )[- 2 ])
12091228 self .assertEqual ('\t \t cpu_startup_entry' , popen (
@@ -1222,6 +1241,16 @@ def main():
12221241 ret = False
12231242 if len (sys .argv ) == 1 :
12241243 #print('Run', me, 'usage')
1244+ for m in getmembers (modules [__name__ ]):
1245+ if isfunction (m [1 ]) and m [1 ].__module__ == __name__ :
1246+ d = inspect .getdoc (m [1 ])
1247+ if not d :
1248+ continue
1249+ print ('\n ' + d .replace ('Arg:' , '\033 [1m' + m [1 ].__name__ + '\033 [0m' ).
1250+ replace ('Ex:' , '\033 [3mExample usage:\033 [0m\n ' + me +
1251+ ' ' + m [1 ].__name__ ).
1252+ replace ('Ex2:' , '\033 [3mExample usage:\033 [0m\n ' + me + ' ' )
1253+ )
12251254 usage ()
12261255 else :
12271256 while sys .argv [1 ].startswith ('--' ):
0 commit comments