批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程
[批处理文件精品]批处理版照片整理器[批处理文件精品]纯批处理备份&还原驱动在线第三方下载
返回列表 发帖

[原创代码] [Perl]列举MinGW中指定C语言库的依赖关系

本帖最后由 523066680 于 2015-6-9 23:42 编辑

初始版本,做了格式化输出。

示例库文件: "windows.h"
相关目录保存于 @dirs 数组中

备注:如果一个函数库已经出现过,则忽略,避免进入死循环
     if ($Lv < 5) { 设定最大递归层,可不设限
  1. =info
  2.     523066680@163.com
  3.     2015-06-09
  4. =cut
  5. our @dirs = (
  6.     "C:/MinGW/lib/gcc/mingw32/4.7.2/include",
  7.     "C:/MinGW/Include"
  8. );
  9. our %name;
  10. our %hash;
  11. my $headfile = "windows.h";
  12. func(0, ".", $headfile);
  13. tree(\%hash);
  14. sub func {
  15.     our @dirs;
  16.     our %hash;
  17.     our %name;
  18.     my $fullpath;
  19.     my ($Lv, $parent, $fname) = @_;
  20.     my @all;
  21.     return if (exists $name{$fname});
  22.     $name{$fname} = 1;
  23.     $hash{$parent.":".$fname} = $Lv;
  24.     foreach (@dirs) {
  25.         $fullpath = "$_/$fname" if (-e "$_/$fname");
  26.     }
  27.     return 0 if (! defined $fullpath);
  28.     ReadFile(\@all, $fullpath);
  29.     foreach (@all) {
  30.         if (/#include <(.*)>/) {
  31.             if ($Lv < 5) {
  32.                 func($Lv+1, $parent.":".$fname, $1);
  33.             }
  34.         }
  35.     }
  36. }
  37. sub tree {
  38.     my $ref = shift;
  39.     my ($a, $b);
  40.     my ($e, $v) = (-1, undef);
  41.     foreach (sort keys %$ref) {
  42.         $v = $ref->{$_};
  43.         s/(.*:)([^:]+)$/$2/;
  44.         
  45.         if ( $v <= $e) {
  46.             print "\n" . " "x(length($1) - $v - 2  + ($v)*3);
  47.         }
  48.         print " > " . $2;
  49.         $e = $v;
  50.     }
  51. }
  52. sub ReadFile {
  53.     my ($aref, $fullpath) = (shift, shift);
  54.     open READ, "<", $fullpath or die "$!\n";
  55.     @{$aref} = <READ>;
  56.     close READ;
  57. }
复制代码

> windows.h > _mingw.h > sdkddkver.h
             > cderr.h
             > commdlg.h > unknwn.h > objfwd.h
                                    > wtypes.h > rpcndr.h > rpcnsip.h
             > ddeml.h
             > imm.h
             > lzexpand.h
             > mmsystem.h
             > nb30.h
             > ole2.h > objbase.h > cguid.h
                                  > objidl.h
                                  > stdlib.h
                      > oleauto.h > oaidl.h
                      > olectlid.h
                      > oleidl.h
             > rpc.h > excpt.h
                     > rpcdce.h > basetyps.h
                                > rpcdcep.h
                     > rpcnsi.h
                     > rpcnterr.h
             > shellapi.h > pshpack2.h
             > stdarg.h
             > winbase.h
             > wincon.h
             > windef.h
             > wingdi.h
             > winnetwk.h
             > winnls.h
             > winperf.h
             > winreg.h > reason.h
             > winresrc.h > commctrl.h > prsht.h
                          > dde.h
                          > dlgs.h
                          > winnt.h > basetsd.h
                                    > poppack.h
                                    > pshpack4.h
                                    > string.h > stddef.h > machine/ansi.h
                                                          > sys/_types.h
                                    > winerror.h
                          > winuser.h
                          > winver.h
             > winsock.h > mswsock.h
             > winspool.h
             > winsvc.h
1

评分人数

    • CrLf: 好东西摸摸大技术 + 1

按顺序输出

本帖最后由 523066680 于 2015-6-10 15:17 编辑

修正问题: 正则表达式(考虑部分#include 采用的是 双引号,以及#include 尾部含有注释<>""的情况)
.
  1. =info
  2.     523066680@163.com
  3.     2015-06-09
  4. =cut
  5. use feature 'state';
  6. our @dirs = (
  7.     "C:/MinGW/lib/gcc/mingw32/4.7.2/include",
  8.     "C:/MinGW/Include",
  9. );
  10. our %name;
  11. our %hash;
  12. my $headfile = "windows.h";
  13. func(0, ".", $headfile);
  14. sub func {
  15.     our @dirs;
  16.     our %name;
  17.     my $fullpath;
  18.     my ($Lv, $parent, $fname) = @_;
  19.     my @all;
  20.     foreach (@dirs) {
  21.         if (-e "$_/$fname") {
  22.             $fullpath = "$_/$fname";
  23.         }
  24.     }
  25.     return if (exists $name{$fname});
  26.     return if (! defined $fullpath);
  27.     $name{$fname} = 1;
  28.     Xprint($Lv, $parent, $fname);
  29.     ReadFile(\@all, $fullpath);
  30.     foreach (@all) {
  31.         if (/#include ["<](.*?)[">]/) {
  32.             func($Lv+1, $parent.":".$fname, $1);
  33.         }
  34.     }
  35. }
  36. sub Xprint {
  37.     state $e = -1;
  38.     my ($Lv, $parent, $fname) = @_;
  39.     if ( $Lv <= $e) {
  40.         print "\n";
  41.         print " "x(length($parent) + ($Lv)*2 - 1);
  42.     }
  43.     print " > " . $fname;
  44.     $e = $Lv;
  45. }
  46. sub ReadFile {
  47.     my ($aref, $fullpath) = (shift, shift);
  48.     open READ, "<", $fullpath or die "$!\n";
  49.     @{$aref} = <READ>;
  50.     close READ;
  51. }
复制代码
> windows.h > _mingw.h > sdkddkver.h
             > winresrc.h > winuser.h
                          > winnt.h > winerror.h
                                    > string.h > stddef.h
                                    > basetsd.h
                                    > pshpack4.h
                                    > poppack.h
                          > winver.h
                          > dde.h
                          > dlgs.h
                          > commctrl.h > prsht.h
             > stdarg.h
             > windef.h
             > wincon.h
             > winbase.h
             > wingdi.h
             > winnls.h
             > winnetwk.h
             > winreg.h > reason.h
             > winsvc.h
             > cderr.h
             > ddeml.h
             > imm.h
             > lzexpand.h
             > mmsystem.h
             > nb30.h
             > rpc.h > rpcdce.h > basetyps.h
                                > rpcdcep.h
                     > rpcnsi.h
                     > rpcnterr.h
                     > excpt.h
             > shellapi.h > pshpack2.h
             > winperf.h
             > commdlg.h > unknwn.h > objfwd.h
                                    > wtypes.h > rpcndr.h > rpcnsip.h
             > winspool.h
             > winsock.h > mswsock.h
             > ole2.h > objbase.h > stdlib.h
                                  > objidl.h
                                  > cguid.h
                      > olectlid.h
                      > oleauto.h > oaidl.h
                      > oleidl.h
1

评分人数

TOP

本帖最后由 523066680 于 2022-3-27 12:15 编辑

最近看到类似问题,发现以前的代码有一些写的不好的地方,更新一下

  • 增加递归层级限制
  • for循环不再使用匿名变量$_
  1. =info
  2.     523066680@163.com
  3.     2015-06-09
  4.     Update: 2022-03-27
  5. =cut
  6. use File::Slurp;
  7. STDOUT->autoflush(1);
  8. our $MAX_LEVEL = 6; # 递归层级
  9. our @dirs = (       # 搜索范围
  10.    "C:/MinGW/x86_64-w64-mingw32/include",
  11.    "C:/MinGW/Include",
  12. );
  13. our %names;
  14. our %tree;
  15. my $headfile = "windows.h";
  16. recur(0, ".", $headfile);
  17. dumptree(\%tree);
  18. sub recur
  19. {
  20.     my ($lv, $parent, $fname) = @_;
  21.     my @all;
  22.     return if (exists $names{$fname});    # 确保库文件名只处理一次
  23.     $names{$fname} = 1;
  24.     $tree{$parent." > ".$fname} = [ $parent, $fname, $lv];
  25.     my $fullpath;
  26.     # 遍历备选地址,找到包含该库文件的路径
  27.     grep { $fullpath = "$_/$fname" if -f "$_/$fname" } @dirs;
  28.     return 0 if (! defined $fullpath);
  29.     my @lines = read_file( $fullpath );
  30.     for my $e ( @lines )
  31.     {
  32.         if ( $e =~ /#include\s+["<](.*)[">]/ and $lv < $MAX_LEVEL )
  33.         {
  34.             recur($lv+1, $parent." > ".$fname, $1);
  35.         }
  36.     }
  37. }
  38. sub dumptree
  39. {
  40.     my $tree = shift;
  41.     my $level = -1;
  42.     for my $fullpath (sort keys %$tree)
  43.     {
  44.         my ($path, $fname, $v) = @{$tree->{$fullpath}};
  45.         # 同级或者向上层级,打印前置缩进;子级不换行,递进显示
  46.         print "\n" . " "x(length($path)-1) if $v <= $level;
  47.         print " > " . $fname;
  48.         $level = $v;
  49.     }
  50. }
复制代码

TOP

返回列表