106_scan_allpackage/
106_scan_allpackage.rs

1#[cfg(perlapi_ver26)]
2use std::env;
3
4#[cfg(perlapi_ver26)]
5use libperl_rs::*;
6
7#[cfg(perlapi_ver26)]
8mod eg;
9#[cfg(perlapi_ver26)]
10use eg::{op0::*,sv0::*,cv0::*,gv0::*};
11
12#[cfg(perlapi_ver26)]
13pub struct Walker<'a> {
14    pub perl: &'a Perl,
15    pub cv: *const libperl_sys::cv,
16}
17
18#[cfg(perlapi_ver26)]
19impl<'a> Walker<'a> {
20    pub fn walk(&'a self, o: *const op, level: isize) {
21        if o.is_null() {return}
22        for kid in sibling_iter(o) {
23            self.walk(kid, level+1);
24        }
25        print!("{}", "  ".repeat(level as usize));
26        let ox = op_extract(&self.perl, self.cv, o);
27        println!("{:?} {:?}", op_name(o), ox);
28    }
29}
30
31#[cfg(perlapi_ver26)]
32fn my_test() {
33    let mut perl = Perl::new();
34    perl.parse_env_args(env::args(), env::vars());
35    
36    let mut seen = Seen::new();
37    seen.insert("main".to_string(), true); // To avoid main::main::main...
38    stash_subs(&perl, "", &mut seen);
39}
40
41#[cfg(perlapi_ver26)]
42type Seen = std::collections::HashMap<String, bool>;
43
44#[cfg(perlapi_ver26)]
45fn stash_subs(perl: &Perl, pack: &str, seen: &mut Seen) {
46    println!("pack = {}", pack);
47
48    if seen.contains_key(pack) {return};
49    seen.insert(pack.to_string(), true);
50    
51    let stash = perl.gv_stashpv(pack, 0);
52    if stash.is_null() {return}
53
54    let emitter = |name: &String, cv: *const libperl_sys::cv| {
55        let walker = Walker {perl: &perl, cv};
56        println!("sub {:?} file {:?}", name, CvFILE(cv));
57        walker.walk(CvROOT(cv), 0);
58        println!("");
59    };
60
61    // let mut packages = Vec::new();
62    for (name, item) in eg::hv_iter0::HvIter::new(&perl, stash) {
63
64        // ref $main::{foo} eq 'CODE'
65        if let Some(Sv::CODE(cv)) = SvRV(item).map(|sv| sv_extract(sv)) {
66            emitter(&name, cv)
67        }
68        // ref (\$main::{foo}) eq 'GLOB'
69        else if let Sv::GLOB {gv, ..} = sv_extract(item) {
70            let cv = GvCV(gv);
71            if let Some(_file) = CvFILE(cv) {
72                emitter(&name, cv);
73            }
74            if name.ends_with("::") {
75                println!("package name = {}", name);
76                if let Some(pure) = name.get(..name.len() - 2) {
77                    if !seen.contains_key(pure) {
78                        // packages.push(String::from(pure.clone()));
79                        let mut fullpack = String::from(pack);
80                        fullpack.push_str("::");
81                        fullpack.push_str(pure);
82                        stash_subs(perl, fullpack.as_str(), seen);
83                    }
84                }
85            }
86        }
87    }
88    
89    // for pkg in packages {
90    //     stash_subs(perl, pkg.as_str(), seen);
91    // }
92}
93
94#[cfg(not(perlapi_ver26))]
95fn my_test() {
96    println!("Requires perl >= 5.26");
97}
98
99fn main() {
100    my_test();
101}